Commits

Anonymous committed 193d120

make sure duplicate crossings aren't inserted

  • Participants
  • Parent commits 6c7c7a1

Comments (0)

Files changed (5)

VectorBoolean/FBBezierGraph.m

 
 - (BOOL) insertCrossingsWithBezierGraph:(FBBezierGraph *)other
 {
-    BOOL hasIntersection = NO;
+    NSMutableArray *crossings = [NSMutableArray arrayWithCapacity:10];
     
     for (FBBezierContour *ourContour in self.contours) {
         for (FBContourEdge *ourEdge in ourContour.edges) {
                         [ourEdge addCrossing:ourCrossing];
                         [theirEdge addCrossing:theirCrossing];
                         
-                        hasIntersection = YES;
+                        // Keep track of the crossing
+                        [crossings addObject:ourCrossing];
                     }
                 }
             }
         }
     }
  
-    return hasIntersection;
+    // Find any duplicate crossings. These will happen at the endpoints of edges
+    NSUInteger removeCount = 0;
+    for (FBEdgeCrossing *crossing in crossings) {
+        if ( crossing.isAtStart && crossing.edge.previous.lastCrossing.isAtEnd ) {
+            FBEdgeCrossing *counterpart = crossing.counterpart;
+            [crossing removeFromEdge];
+            [counterpart removeFromEdge];
+            removeCount++;
+        }
+        if ( crossing.isAtEnd && crossing.edge.next.firstCrossing.isAtStart ) {
+            FBEdgeCrossing *counterpart = crossing.edge.next.firstCrossing.counterpart;
+            [crossing.edge.next.firstCrossing removeFromEdge];
+            [counterpart removeFromEdge];            
+            removeCount++;
+        }
+    }
+    return ([crossings count] - removeCount) > 0;
 }
 
 - (BOOL) doesEdge:(FBContourEdge *)edge1 crossEdge:(FBContourEdge *)edge2 atIntersection:(FBBezierIntersection *)intersection

VectorBoolean/FBContourEdge.h

 @property (readonly) FBEdgeCrossing *lastCrossing;
 
 - (void) addCrossing:(FBEdgeCrossing *)crossing;
+- (void) removeCrossing:(FBEdgeCrossing *)crossing;
 - (void) removeAllCrossings;
 
 @end

VectorBoolean/FBContourEdge.m

 #import "FBBezierContour.h"
 #import "FBDebug.h"
 
+@interface FBContourEdge ()
+
+- (void) sortCrossings;
+
+@end
+
 @implementation FBContourEdge
 
 @synthesize curve=_curve;
 {
     crossing.edge = self;
     [_crossings addObject:crossing];
+    [self sortCrossings];
+}
+
+- (void) removeCrossing:(FBEdgeCrossing *)crossing
+{
+    crossing.edge = nil;
+    [_crossings removeObject:crossing];
+    [self sortCrossings];
+}
+
+- (void) sortCrossings
+{
     [_crossings sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
         FBEdgeCrossing *crossing1 = obj1;
         FBEdgeCrossing *crossing2 = obj2;

VectorBoolean/FBEdgeCrossing.h

 + (id) crossingWithIntersection:(FBBezierIntersection *)intersection;
 - (id) initWithIntersection:(FBBezierIntersection *)intersection;
 
+- (void) removeFromEdge;
+
 @property (assign) FBContourEdge *edge;
 @property (assign) FBEdgeCrossing *counterpart;
 @property (readonly) CGFloat order;
 @property (readonly) FBBezierCurve *curve;
 @property (readonly) FBBezierCurve *leftCurve;
 @property (readonly) FBBezierCurve *rightCurve;
+@property (readonly, getter = isAtStart) BOOL atStart;
+@property (readonly, getter = isAtEnd) BOOL atEnd;
 
 @end

VectorBoolean/FBEdgeCrossing.m

     [super dealloc];
 }
 
+- (void) removeFromEdge
+{
+    [_edge removeCrossing:self];
+}
+
 - (CGFloat) order
 {
     return self.parameter;
     return _intersection.curve2RightBezier;
 }
 
+- (BOOL) isAtStart
+{
+    if ( self.edge.curve == _intersection.curve1 )
+        return _intersection.isAtStartOfCurve1;
+    
+    return _intersection.isAtStartOfCurve2;
+}
+
+- (BOOL) isAtEnd
+{
+    if ( self.edge.curve == _intersection.curve1 )
+        return _intersection.isAtStopOfCurve1;
+    
+    return _intersection.isAtStopOfCurve2;
+}
+
 - (NSString *) description
 {
     return [NSString stringWithFormat:@"<%@: isEntry = %d, isProcessed = %d, intersection = %@>",