Commits

Anonymous committed 7b81b71

add concept of if a contour is filled or a hole

  • Participants
  • Parent commits eb7a5b6

Comments (0)

Files changed (3)

File VectorBoolean/FBBezierContour.h

 @class FBBezierCurve;
 @class FBEdgeCrossing;
 
+typedef enum FBContourInside {
+    FBContourInsideFilled,
+    FBContourInsideHole
+} FBContourInside;
+
 @interface FBBezierContour : NSObject<NSCopying> {
     NSMutableArray *_edges;
     NSRect _bounds;
+    FBContourInside _inside;
 }
 
 - (void) addCurve:(FBBezierCurve *)curve;
 @property (readonly) NSArray *edges;
 @property (readonly) NSRect bounds;
 @property (readonly) NSPoint testPoint;
+@property (readonly) NSPoint firstPoint;
+@property FBContourInside inside;
 
 @end

File VectorBoolean/FBBezierContour.m

 @implementation FBBezierContour
 
 @synthesize edges=_edges;
+@synthesize inside=_inside;
 
 - (id)init
 {
     return _bounds;
 }
 
+- (NSPoint) firstPoint
+{
+    if ( [_edges count] == 0 )
+        return NSZeroPoint;
+
+    FBContourEdge *edge = [_edges objectAtIndex:0];
+    return edge.curve.endPoint1;
+}
+
 - (NSPoint) testPoint
 {
     if ( [_edges count] == 0 )

File VectorBoolean/FBBezierGraph.m

 - (void) addContour:(FBBezierContour *)contour;
 - (void) addBezierGraph:(FBBezierGraph *)graph;
 - (void) round;
+- (FBContourInside) contourInsides:(FBBezierContour *)contour;
 
 @property (readonly) NSArray *contours;
 @property (readonly) NSRect bounds;
                     break;
             }
         }
+        
+        for (contour in _contours)
+            contour.inside = [self contourInsides:contour];
     }
     
     return self;
     return (intersectCount % 2) == 1;
 }
 
+- (FBContourInside) contourInsides:(FBBezierContour *)testContour
+{
+    NSPoint testPoint = testContour.firstPoint;
+    NSPoint lineEndPoint = NSMakePoint(testPoint.x > NSMinX(self.bounds) ? NSMinX(self.bounds) - 10 : NSMaxX(self.bounds) + 10, testPoint.y); /* just move us outside the bounds of the graph */
+    FBBezierCurve *testCurve = [FBBezierCurve bezierCurveWithLineStartPoint:testPoint endPoint:lineEndPoint];
+
+    NSUInteger intersectCount = 0;
+    for (FBBezierContour *contour in self.contours) {
+        if ( contour == testContour )
+            continue; // don't test self intersections
+        for (FBContourEdge *edge in contour.edges) {
+            NSArray *intersections = [testCurve intersectionsWithBezierCurve:edge.curve];
+            for (FBBezierIntersection *intersection in intersections) {
+                if ( intersection.isTangent )
+                    continue;
+                intersectCount++;
+            }
+        }
+    }
+
+    return (intersectCount % 2) == 1 ? FBContourInsideHole : FBContourInsideFilled;
+}
+
 - (void) markCrossingsAsEntryOrExitWithBezierGraph:(FBBezierGraph *)otherGraph markInside:(BOOL)markInside
 {
     for (FBBezierContour *contour in _contours) {