views:

169

answers:

1

I am working with drawing polygons based on a given line. I have the logic working out well except in cases where it appears that the polygon intersects itself. However, it doesn't seem to be 100% consistent, nor does it make sense based on what I'm reading. Below are two images created using the same code. The yellow polygons are the ones I'm concerned with.

Image: http://i31.tinypic.com/24cxxlf.png

I want every case to work like the first case (where the empty area "wrapped" by the polygon is not filled in).

These images are produced by this code:

BufferedImage drawingImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = drawingImage.createGraphics();
Polygon polygon = new Polygon(parsedPoints[0], parsedPoints[1], parsedPoints[0].length);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g.setColor(drawingColor);
g.fillPolygon(polygon);
float[] scales = {1f, 1f, 1f, 0.7f};
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);
graphics.drawImage(drawingImage, rop, 0, 0);
graphics.setStroke(new BasicStroke(2));
graphics.setColor(drawingColor);
graphics.drawPolygon(polygon);

(I'm filling the polygon applying a rescale to get some transparency to the fill, and then drawing the border without transparency.)

According to the Java documentation for the Graphics.fillPolygon method:

The area inside the polygon is defined using an even-odd fill rule, also known as the alternating rule.

If I understand that correctly, then in both cases a pixel contained within the area "wrapped" by the thick polygon would cross exactly two paths, so it would be considered "outside" the polygon.

So my questions are: (a) am I understanding the even-odd fill rule and (b) is there a way in Java to make the second image work more like the first?

Any thoughts on this would be greatly appreciated.

Thanks.

+2  A: 
  1. The rule applies per polygon. Java doesn't care about the polygon you drew even one statement ago.
  2. You seem to be misunderstanding the even-odd rule a bit. The practical version of the rule goes a bit like this...for each 'y' coordinate the polygon crosses, there's an ordered list of all the x coordinates where it crosses. The 'inside' of the polygon is the sections from each even-numbered index (0, 2, 4...) to the next odd-numbered index.
cHao
@cHao - Okay, but that doesn't seem to resolve why the first polygon fills correctly, and the second one doesn't. If I'm understanding what you're saying, we're looking at something like this. For a given row (y coordinate), we w ould have the following (excuse my poor ascii art):------| |-----------| |-------Isn't the filled area that I don't want filled still in an area that would be even-indexed?
Dante617
@Dante617: No, it's not. Like i mentioned, the rule is per polygon.
cHao
@cHao - Okay, I think I understand what you're saying. Essentially, once it really intersects, I end up with two polygons (in the case two "squares," one within the other). When it fills, it ends up filling twice. The inside square and the outside square. This explains why the inside is slightly darker than the rest, because it's being filled twice, not just once. Of course, now the question is, how can I get it to act the way I want it to.
Dante617
@Dante617: Well, in the current case, you could set the stroke to something wide, draw the polygon, then set it back to a skinny one and draw the same polygon again. That'd give you the first image in your example.
cHao
@cHao - Yeah, but that wouldn't work in all cases. Essentially, I'm being given the bounds of the polygon as a set of points. So, while in this case, just drawing it larger would work, it won't in all cases.
Dante617
@Dante617: I'm not talking about drawing it larger -- i'm talking about setting a wider stroke. You'd be tracing over the exact same points, but one of those times you'd trace with the equivalent of a highlighter rather than a pen.
cHao
@cHao - I think I understand your meaning, but in some cases there will be polygons of non-uniform width involved. I also just discovered that while I thought I was dealing with a single polygon, the information that I'm getting passed in the second case actually gets broken up into two polygons, so it's not even Java's logic that isn't getting in my way here. It's the data that's being sent.Thanks for all your help -- and your quick responses.
Dante617
@Dante617: Whether using the stroke will work depends on what your goal is. If you have a polygon you want to "cut out" of another, yeah -- stroke won't work. If you're just trying to highlight the polygon, though (as it looks like from your example), it should work fine.
cHao
@cHao - That's the thing I don't really want to "highlight" the bounds of the polygon, I do want to fill it. If I'm understanding your suggestion, the highlight wouldn't only surround the bounds, not the interior. Here is another example: http://i25.tinypic.com/27x1cao.jpg
Dante617
@cHao - Thanks again for all your help on this. I've got the problem understood, now, though, and it ends up being not related to my misunderstanding of the even-odd fill rule, but of what I'm getting for data. So feel free to consider this one closed and not spend any more time on it. :)
Dante617