I created a GridPoint class that inherits from java.awt.Point as a Point2D class with integer coordinates, to help me with the refactoring.
I haven't figured out why VisibleAreaSegment.getArea() adds those really long projected points to the list, and thus I can't change them to use integers.
I tried to get rid of GraphicsUtil.getProjectedPoint completely. The only thing stopping me is, again, VisibleAreaSegment.getArea().
The other red marks (vbl.AreaTree, zone.AreaData) are places where the code gets arbitrary paths and makes points out of them, making it impossible to use integer coordinates without a more abstract understanding of what paths can exist.
GridPoint's extra functions (functions that aren't in java.awt.Point) ended up not used (except in getProjectedPoint). I tried to do the computations directly because premature optimization is the best thing ever. The upshot of this is that GridPoint can be completely replaced by Point once getProjectedPoint dies (and one more location, but that one is just a toString for debugging). If the red marks can't be removed, or if you want to test my work, then replace all of the GridPoints with Point2D.Doubles, and change all of the .x and .y to .getX() and .getY().
In GraphicsUtil, I changed the broken and unused createLine function to something that works, but might not be what's wanted. Oh well. I also wrote in comments for the original up to a point. The function should probably just be removed.
AreaFace:
+ Combined the two AreaFace classes from the zone and zone.vbl packages.
+ Reworked to reduce reliance on angle measurements. The classes that use it were also reworked. In particular, "midpoint" and the "double facing" variable aren't needed. Instead, I keep a "facing" point that represents a direction, and a faceTo(Point) function that (like compareTo) returns a positive, negative, or 0 that tells you whether the face is facing toward, away, or neither (is colinear with) relative to the given point.
- Notably, there is a question about facing that hasn't been resolved. See main for testing against the old way. faceTo(Point) can stay, but the meaning of its return is up for debate, so faces(Point) may need to change, and the comments about them, too.
- The code that uses facing (AreaMeta) needs to be tested with this new way. The Geometry.getAngle weirdness is screwing me up. But every time I think I proved that my code is wrong, it still works.
- "boolean faces(Point)" also needs to deal with the case of the line segment being colinear with the origin in question. My opinion is, choose the way that eliminates the most faces, so you deal with less.
AreaMeta: There are two. I worked with them as similarly as I could.
+ Eliminated the circular link list and replaced it with a non-circular ArrayList. Should be a minor speed improvement.
+ Add detection of emptiness. It should never come up, but if your code wants to check for emptiness...
+ Changed the computation for holes: replaced angle-based computation with area-based computation, which should be a speed improvement, since trig is not as fast as a few basic int operations.
- I would've combine the two AreaMetas, but I needed more time to understand them.
- The two AreaMetas have different behaviors when abs(angle) == 90. I don't know why, but I assumed it was an oversight gave them the same behavior (or at least tried to).
- The two AreaMetas also have reversed faces from one another, in computeFaces(). In other words, when one added Face(A,B), the other added Face(B,A). No idea why, but I just realized it may screw up my facing test in getVisibleAreas/getVisibleAreas, and also mean that they DID have the same behavior for abs(angle)==90.
VisibleAreaSegment:
+ Changed the algorithm for getPath, as well as the internal data structure to something less redundant.
- Want to reduce getArea().
- I bet the faceList could be eliminated completely in favor of a list of vertices.
Zip with the zone and vbl package files attached. GraphicsUtil is here:
https://dl.dropbox.com/u/2954556/GraphicsUtil.java