Java - Filling a Custom Shape

abrightwell picture abrightwell · Jul 26, 2010 · Viewed 9k times · Source

I have created a custom shape, essentially it is a collection of four Arc2D objects.

When these arcs are drawn they form what could be considered a four point rounded star shape, kind of like a clover. Where one arc ends, the other begins. They form a square in the center. So imagine, taking a square and drawing half circles on every side.

I can draw this shape to a Graphics2D object, but when I fill it, it will only fill the arcs and not the center square. Filling this internal square is my problem.

I have implemented the getPathIterator() method, below. I have implemented the contains() methods as well. But it will still only fill the arcs.

I tried to add a Rectangle. When filling the shape, the rectangle/square would be filled properly, however it draws the rectangle as well, which obviously should be expected, but definitely not the desired result.

So, does anyone have any ideas on how to "fill" such a shape?

public PathIterator getPathIterator(AffineTransform at) {
    GeneralPath gp = new GeneralPath

    for (Arc2D arcs : this.arcs) {
        gp.append(arc, false);
    }

    return gp.getPathIterator(at);
}

Answer

Erick Robertson picture Erick Robertson · Jul 26, 2010

Whenever I create a shape, I always create a Path2D.Double object. Then, I use moveTo to get to the starting location, and a combination of lineTo() and curveTo() to move around the path. Then, when I'm done, I call closePath(). It has always filled correctly.

I don't have any experience with implementing getPathIterator, but I do notice that you don't do a closePath(). I don't know if that's required or not, but I do feel like taking my approach will work.

Here is an example that fills a rounded rectangle:

double width = 300;
double height = 400;
Path2D.Double path = new Path2D.Double();
path.moveTo(0.0, 8.0);
path.curveTo(0.0, 0.0, 8.0, 0.0, 8.0, 0.0);
path.lineTo(width - 8.0, 0.0);
path.curveTo(width, 0.0, width, 8.0, width, 8.0);
path.lineTo(width, height - 8.0);
path.curveTo(width, height, width - 8.0, height, width - 8.0, height);
path.lineTo(8.0, height);
path.curveTo(0.0, .height, 0.0, height - 8.0, 0, height - 8.0);
path.closePath();
g2.fill(path);