Commits

Andy Finnell  committed c5430ea

renaming Geometry to FBGeometry to avoid any name collisions with host project

  • Participants
  • Parent commits 5ac4453

Comments (0)

Files changed (13)

File VectorBoolean.xcodeproj/project.pbxproj

 		A11131E513960B9D00C9395C /* NSBezierPath+Boolean.m in Sources */ = {isa = PBXBuildFile; fileRef = A11131E413960B9D00C9395C /* NSBezierPath+Boolean.m */; };
 		A192AB53139D843C00AF40BA /* FBBezierCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = A192AB52139D843B00AF40BA /* FBBezierCurve.m */; };
 		A192AB56139D863A00AF40BA /* FBBezierIntersection.m in Sources */ = {isa = PBXBuildFile; fileRef = A192AB55139D863900AF40BA /* FBBezierIntersection.m */; };
-		A192AB59139D8D6000AF40BA /* Geometry.m in Sources */ = {isa = PBXBuildFile; fileRef = A192AB58139D8D6000AF40BA /* Geometry.m */; };
+		A192AB59139D8D6000AF40BA /* FBGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = A192AB58139D8D6000AF40BA /* FBGeometry.m */; };
 		A1A3D0A713A9BCBA00678AA9 /* FBBezierGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A3D0A613A9BCB900678AA9 /* FBBezierGraph.m */; };
 		A1A3D0AB13A9CE1200678AA9 /* FBBezierContour.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A3D0AA13A9CE0F00678AA9 /* FBBezierContour.m */; };
 		A1A3D0AE13A9CE3D00678AA9 /* FBContourEdge.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A3D0AD13A9CE3B00678AA9 /* FBContourEdge.m */; };
 		A192AB52139D843B00AF40BA /* FBBezierCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBBezierCurve.m; sourceTree = "<group>"; };
 		A192AB54139D863900AF40BA /* FBBezierIntersection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBBezierIntersection.h; sourceTree = "<group>"; };
 		A192AB55139D863900AF40BA /* FBBezierIntersection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBBezierIntersection.m; sourceTree = "<group>"; };
-		A192AB57139D8D5F00AF40BA /* Geometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Geometry.h; sourceTree = "<group>"; };
-		A192AB58139D8D6000AF40BA /* Geometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Geometry.m; sourceTree = "<group>"; };
+		A192AB57139D8D5F00AF40BA /* FBGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBGeometry.h; sourceTree = "<group>"; };
+		A192AB58139D8D6000AF40BA /* FBGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBGeometry.m; sourceTree = "<group>"; };
 		A1A3D0A513A9BCB800678AA9 /* FBBezierGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBBezierGraph.h; sourceTree = "<group>"; };
 		A1A3D0A613A9BCB900678AA9 /* FBBezierGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBBezierGraph.m; sourceTree = "<group>"; };
 		A1A3D0A913A9CE0E00678AA9 /* FBBezierContour.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBBezierContour.h; sourceTree = "<group>"; };
 				A1C48B64139602480043E2C7 /* CanvasView.m */,
 				A1C48B66139602800043E2C7 /* Canvas.h */,
 				A1C48B67139602810043E2C7 /* Canvas.m */,
-				A192AB57139D8D5F00AF40BA /* Geometry.h */,
-				A192AB58139D8D6000AF40BA /* Geometry.m */,
+				A192AB57139D8D5F00AF40BA /* FBGeometry.h */,
+				A192AB58139D8D6000AF40BA /* FBGeometry.m */,
 				A11131E313960B9D00C9395C /* NSBezierPath+Boolean.h */,
 				A11131E413960B9D00C9395C /* NSBezierPath+Boolean.m */,
 				A1C48B5D1395FAE10043E2C7 /* NSBezierPath+Utilities.h */,
 		A1C48B2A1395FA370043E2C7 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
+				LastUpgradeCheck = 0460;
 				ORGANIZATIONNAME = "Fortunate Bear, LLC";
 			};
 			buildConfigurationList = A1C48B2D1395FA370043E2C7 /* Build configuration list for PBXProject "VectorBoolean" */;
 				A11131E513960B9D00C9395C /* NSBezierPath+Boolean.m in Sources */,
 				A192AB53139D843C00AF40BA /* FBBezierCurve.m in Sources */,
 				A192AB56139D863A00AF40BA /* FBBezierIntersection.m in Sources */,
-				A192AB59139D8D6000AF40BA /* Geometry.m in Sources */,
+				A192AB59139D8D6000AF40BA /* FBGeometry.m in Sources */,
 				A1A3D0A713A9BCBA00678AA9 /* FBBezierGraph.m in Sources */,
 				A1A3D0AB13A9CE1200678AA9 /* FBBezierContour.m in Sources */,
 				A1A3D0AE13A9CE3D00678AA9 /* FBContourEdge.m in Sources */,
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 10.6;
 				ONLY_ACTIVE_ARCH = YES;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 10.6;
 				SDKROOT = macosx;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				COMBINE_HIDPI_IMAGES = YES;
 				COPY_PHASE_STRIP = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				COMBINE_HIDPI_IMAGES = YES;
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				GCC_ENABLE_OBJC_EXCEPTIONS = YES;

File VectorBoolean/FBBezierContour.m

 #import "FBEdgeCrossing.h"
 #import "FBContourOverlap.h"
 #import "FBDebug.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 #import "FBBezierIntersection.h"
 #import "NSBezierPath+Utilities.h"
 

File VectorBoolean/FBBezierCurve.h

 //
 
 #import <Cocoa/Cocoa.h>
-#import "Geometry.h"
+#import "FBGeometry.h"
 
 @class FBBezierIntersectRange;
 

File VectorBoolean/FBBezierCurve.m

 
 #import "FBBezierCurve.h"
 #import "NSBezierPath+Utilities.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 #import "FBBezierIntersection.h"
 #import "FBBezierIntersectRange.h"
 

File VectorBoolean/FBBezierGraph.m

 #import "FBEdgeCrossing.h"
 #import "FBContourOverlap.h"
 #import "FBDebug.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 #import <math.h>
 
 

File VectorBoolean/FBBezierIntersectRange.h

 //
 
 #import <Foundation/Foundation.h>
-#import "Geometry.h"
+#import "FBGeometry.h"
 
 @class FBBezierCurve, FBBezierIntersection;
 

File VectorBoolean/FBBezierIntersection.m

 
 #import "FBBezierIntersection.h"
 #import "FBBezierCurve.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 
 static const CGFloat FBPointCloseThreshold = 1e-7;
 const CGFloat FBParameterCloseThreshold = 1e-5;

File VectorBoolean/FBContourEdge.m

 #import "FBBezierContour.h"
 #import "FBBezierIntersection.h"
 #import "FBBezierCurve.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 #import "FBDebug.h"
 
 

File VectorBoolean/FBGeometry.h

+//
+//  Geometry.h
+//  VectorBrush
+//
+//  Created by Andrew Finnell on 5/28/11.
+//  Copyright 2011 Fortunate Bear, LLC. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+CGFloat FBDistanceBetweenPoints(NSPoint point1, NSPoint point2);
+CGFloat FBDistancePointToLine(NSPoint point, NSPoint lineStartPoint, NSPoint lineEndPoint);
+NSPoint FBLineNormal(NSPoint lineStart, NSPoint lineEnd);
+NSPoint FBLineMidpoint(NSPoint lineStart, NSPoint lineEnd);
+
+NSPoint FBAddPoint(NSPoint point1, NSPoint point2);
+NSPoint FBScalePoint(NSPoint point, CGFloat scale);
+NSPoint FBUnitScalePoint(NSPoint point, CGFloat scale);
+NSPoint FBSubtractPoint(NSPoint point1, NSPoint point2);
+CGFloat FBDotMultiplyPoint(NSPoint point1, NSPoint point2);
+CGFloat FBPointLength(NSPoint point);
+CGFloat FBPointSquaredLength(NSPoint point);
+NSPoint FBNormalizePoint(NSPoint point);
+NSPoint FBNegatePoint(NSPoint point);
+NSPoint FBRoundPoint(NSPoint point);
+
+NSPoint FBRectGetTopLeft(NSRect rect);
+NSPoint FBRectGetTopRight(NSRect rect);
+NSPoint FBRectGetBottomLeft(NSRect rect);
+NSPoint FBRectGetBottomRight(NSRect rect);
+
+void FBExpandBoundsByPoint(NSPoint *topLeft, NSPoint *bottomRight, NSPoint point);
+NSRect FBUnionRect(NSRect rect1, NSRect rect2);
+
+BOOL FBArePointsClose(NSPoint point1, NSPoint point2);
+BOOL FBArePointsCloseWithOptions(NSPoint point1, NSPoint point2, CGFloat threshold);
+BOOL FBAreValuesClose(CGFloat value1, CGFloat value2);
+BOOL FBAreValuesCloseWithOptions(CGFloat value1, CGFloat value2, CGFloat threshold);
+
+//////////////////////////////////////////////////////////////////////////
+// Angle Range structure provides a simple way to store angle ranges
+//  and determine if a specific angle falls within. 
+//
+typedef struct FBAngleRange {
+    CGFloat minimum;
+    CGFloat maximum;
+} FBAngleRange;
+
+FBAngleRange FBAngleRangeMake(CGFloat minimum, CGFloat maximum);
+BOOL FBAngleRangeContainsAngle(FBAngleRange range, CGFloat angle);
+
+CGFloat NormalizeAngle(CGFloat value);
+CGFloat PolarAngle(NSPoint point);
+
+//////////////////////////////////////////////////////////////////////////////////
+// Parameter ranges
+//
+
+// FBRange is a range of parameter (t)
+typedef struct FBRange {
+    CGFloat minimum;
+    CGFloat maximum;
+} FBRange;
+
+extern FBRange FBRangeMake(CGFloat minimum, CGFloat maximum);
+extern BOOL FBRangeHasConverged(FBRange range, NSUInteger places);
+extern CGFloat FBRangeGetSize(FBRange range);
+extern CGFloat FBRangeAverage(FBRange range);
+extern CGFloat FBRangeScaleNormalizedValue(FBRange range, CGFloat value);
+
+extern BOOL FBTangentsCross(NSPoint edge1Tangents[2], NSPoint edge2Tangents[2]);

File VectorBoolean/FBGeometry.m

+//
+//  Geometry.m
+//  VectorBrush
+//
+//  Created by Andrew Finnell on 5/28/11.
+//  Copyright 2011 Fortunate Bear, LLC. All rights reserved.
+//
+
+#import "FBGeometry.h"
+
+static const CGFloat FBPointClosenessThreshold = 1e-10;
+
+
+CGFloat FBDistanceBetweenPoints(NSPoint point1, NSPoint point2)
+{
+    CGFloat xDelta = point2.x - point1.x;
+    CGFloat yDelta = point2.y - point1.y;
+    return sqrt(xDelta * xDelta + yDelta * yDelta);
+}
+
+CGFloat FBDistancePointToLine(NSPoint point, NSPoint lineStartPoint, NSPoint lineEndPoint)
+{
+    CGFloat lineLength = FBDistanceBetweenPoints(lineStartPoint, lineEndPoint);
+    if ( lineLength == 0 )
+        return 0;
+    CGFloat u = ((point.x - lineStartPoint.x) * (lineEndPoint.x - lineStartPoint.x) + (point.y - lineStartPoint.y) * (lineEndPoint.y - lineStartPoint.y)) / (lineLength * lineLength);
+    NSPoint intersectionPoint = NSMakePoint(lineStartPoint.x + u * (lineEndPoint.x - lineStartPoint.x), lineStartPoint.y + u * (lineEndPoint.y - lineStartPoint.y));
+    return FBDistanceBetweenPoints(point, intersectionPoint);
+}
+
+NSPoint FBAddPoint(NSPoint point1, NSPoint point2)
+{
+    return NSMakePoint(point1.x + point2.x, point1.y + point2.y);
+}
+
+NSPoint FBUnitScalePoint(NSPoint point, CGFloat scale)
+{
+    NSPoint result = point;
+    CGFloat length = FBPointLength(point);
+    if ( length != 0.0 ) {
+        result.x *= scale/length;
+        result.y *= scale/length;
+    }
+    return result;
+}
+
+NSPoint FBScalePoint(NSPoint point, CGFloat scale)
+{
+    return NSMakePoint(point.x * scale, point.y * scale);
+}
+
+CGFloat FBDotMultiplyPoint(NSPoint point1, NSPoint point2)
+{
+    return point1.x * point2.x + point1.y * point2.y;
+}
+
+NSPoint FBSubtractPoint(NSPoint point1, NSPoint point2)
+{
+    return NSMakePoint(point1.x - point2.x, point1.y - point2.y);
+}
+
+CGFloat FBPointLength(NSPoint point)
+{
+    return sqrt((point.x * point.x) + (point.y * point.y));
+}
+
+CGFloat FBPointSquaredLength(NSPoint point)
+{
+    return (point.x * point.x) + (point.y * point.y);
+}
+
+NSPoint FBNormalizePoint(NSPoint point)
+{
+    NSPoint result = point;
+    CGFloat length = FBPointLength(point);
+    if ( length != 0.0 ) {
+        result.x /= length;
+        result.y /= length;
+    }
+    return result;
+}
+
+NSPoint FBNegatePoint(NSPoint point)
+{
+    return NSMakePoint(-point.x, -point.y);
+}
+
+NSPoint FBRoundPoint(NSPoint point)
+{
+    NSPoint result = { round(point.x), round(point.y) };
+    return result;
+}
+
+NSPoint FBLineNormal(NSPoint lineStart, NSPoint lineEnd)
+{
+    return FBNormalizePoint(NSMakePoint(-(lineEnd.y - lineStart.y), lineEnd.x - lineStart.x));
+}
+
+NSPoint FBLineMidpoint(NSPoint lineStart, NSPoint lineEnd)
+{
+    CGFloat distance = FBDistanceBetweenPoints(lineStart, lineEnd);
+    NSPoint tangent = FBNormalizePoint(FBSubtractPoint(lineEnd, lineStart));
+    return FBAddPoint(lineStart, FBUnitScalePoint(tangent, distance / 2.0));
+}
+
+NSPoint FBRectGetTopLeft(NSRect rect)
+{
+    return NSMakePoint(NSMinX(rect), NSMinY(rect));
+}
+
+NSPoint FBRectGetTopRight(NSRect rect)
+{
+    return NSMakePoint(NSMaxX(rect), NSMinY(rect));
+}
+
+NSPoint FBRectGetBottomLeft(NSRect rect)
+{
+    return NSMakePoint(NSMinX(rect), NSMaxY(rect));
+}
+
+NSPoint FBRectGetBottomRight(NSRect rect)
+{
+    return NSMakePoint(NSMaxX(rect), NSMaxY(rect));
+}
+
+void FBExpandBoundsByPoint(NSPoint *topLeft, NSPoint *bottomRight, NSPoint point)
+{
+    if ( point.x < topLeft->x )
+        topLeft->x = point.x;
+    if ( point.x > bottomRight->x )
+        bottomRight->x = point.x;
+    if ( point.y < topLeft->y )
+        topLeft->y = point.y;
+    if ( point.y > bottomRight->y )
+        bottomRight->y = point.y;
+}
+
+NSRect FBUnionRect(NSRect rect1, NSRect rect2)
+{
+    NSPoint topLeft = FBRectGetTopLeft(rect1);
+    NSPoint bottomRight = FBRectGetBottomRight(rect1);
+    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetTopLeft(rect2));
+    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetTopRight(rect2));
+    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetBottomRight(rect2));
+    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetBottomLeft(rect2));    
+    return NSMakeRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
+}
+
+BOOL FBArePointsClose(NSPoint point1, NSPoint point2)
+{
+    return FBArePointsCloseWithOptions(point1, point2, FBPointClosenessThreshold);
+}
+
+BOOL FBArePointsCloseWithOptions(NSPoint point1, NSPoint point2, CGFloat threshold)
+{
+    return FBAreValuesCloseWithOptions(point1.x, point2.x, threshold) && FBAreValuesCloseWithOptions(point1.y, point2.y, threshold);
+}
+
+BOOL FBAreValuesClose(CGFloat value1, CGFloat value2)
+{
+    return FBAreValuesCloseWithOptions(value1, value2, FBPointClosenessThreshold);
+}
+
+BOOL FBAreValuesCloseWithOptions(CGFloat value1, CGFloat value2, CGFloat threshold)
+{
+    CGFloat delta = value1 - value2;    
+    return (delta <= threshold) && (delta >= -threshold);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Helper methods for angles
+//
+static const CGFloat FB2PI = 2.0 * M_PI;
+
+// Normalize the angle between 0 and 2pi
+CGFloat NormalizeAngle(CGFloat value)
+{
+    while ( value < 0.0 )
+        value += FB2PI;
+    while ( value >= FB2PI )
+        value -= FB2PI;
+    return value;
+}
+
+// Compute the polar angle from the cartesian point
+CGFloat PolarAngle(NSPoint point)
+{
+    CGFloat value = 0.0;
+    if ( point.x > 0.0 )
+        value = atan(point.y / point.x);
+    else if ( point.x < 0.0 ) {
+        if ( point.y >= 0.0 )
+            value = atan(point.y / point.x) + M_PI;
+        else
+            value = atan(point.y / point.x) - M_PI;
+    } else {
+        if ( point.y > 0.0 )
+            value =  M_PI_2;
+        else if ( point.y < 0.0 )
+            value =  -M_PI_2;
+        else
+            value = 0.0;
+    }
+    return NormalizeAngle(value);
+}
+
+
+FBAngleRange FBAngleRangeMake(CGFloat minimum, CGFloat maximum)
+{
+    FBAngleRange range = { minimum, maximum };
+    return range;
+}
+
+BOOL FBAngleRangeContainsAngle(FBAngleRange range, CGFloat angle)
+{
+    if ( range.minimum <= range.maximum )
+        return angle > range.minimum && angle < range.maximum;
+    
+    // The range wraps around 0. See if the angle falls in the first half
+    if ( angle > range.minimum && angle <= FB2PI )
+        return YES;
+    
+    return angle >= 0.0 && angle < range.maximum;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// Parameter ranges
+//
+FBRange FBRangeMake(CGFloat minimum, CGFloat maximum)
+{
+    FBRange range = { minimum, maximum };
+    return range;
+}
+
+BOOL FBRangeHasConverged(FBRange range, NSUInteger places)
+{
+    CGFloat factor = pow(10.0, places);
+    NSInteger minimum = (NSInteger)(range.minimum * factor);
+    NSInteger maxiumum = (NSInteger)(range.maximum * factor);
+    return minimum == maxiumum;
+}
+
+CGFloat FBRangeGetSize(FBRange range)
+{
+    return range.maximum - range.minimum;
+}
+
+CGFloat FBRangeAverage(FBRange range)
+{
+    return (range.minimum + range.maximum) / 2.0;
+}
+
+CGFloat FBRangeScaleNormalizedValue(FBRange range, CGFloat value)
+{
+    return (range.maximum - range.minimum) * value + range.minimum;
+}
+
+
+BOOL FBTangentsCross(NSPoint edge1Tangents[2], NSPoint edge2Tangents[2])
+{    
+    // Calculate angles for the tangents
+    CGFloat edge1Angles[] = { PolarAngle(edge1Tangents[0]), PolarAngle(edge1Tangents[1]) };
+    CGFloat edge2Angles[] = { PolarAngle(edge2Tangents[0]), PolarAngle(edge2Tangents[1]) };
+    
+    // Count how many times edge2 angles appear between the self angles
+    FBAngleRange range1 = FBAngleRangeMake(edge1Angles[0], edge1Angles[1]);
+    NSUInteger rangeCount1 = 0;
+    if ( FBAngleRangeContainsAngle(range1, edge2Angles[0]) )
+        rangeCount1++;
+    if ( FBAngleRangeContainsAngle(range1, edge2Angles[1]) )
+        rangeCount1++;
+    
+    // Count how many times self angles appear between the edge2 angles
+    FBAngleRange range2 = FBAngleRangeMake(edge1Angles[1], edge1Angles[0]);
+    NSUInteger rangeCount2 = 0;
+    if ( FBAngleRangeContainsAngle(range2, edge2Angles[0]) )
+        rangeCount2++;
+    if ( FBAngleRangeContainsAngle(range2, edge2Angles[1]) )
+        rangeCount2++;
+    
+    // If each pair of angles split the other two, then the edges cross.
+    return rangeCount1 == 1 && rangeCount2 == 1;
+}

File VectorBoolean/Geometry.h

-//
-//  Geometry.h
-//  VectorBrush
-//
-//  Created by Andrew Finnell on 5/28/11.
-//  Copyright 2011 Fortunate Bear, LLC. All rights reserved.
-//
-
-#import <Cocoa/Cocoa.h>
-
-
-CGFloat FBDistanceBetweenPoints(NSPoint point1, NSPoint point2);
-CGFloat FBDistancePointToLine(NSPoint point, NSPoint lineStartPoint, NSPoint lineEndPoint);
-NSPoint FBLineNormal(NSPoint lineStart, NSPoint lineEnd);
-NSPoint FBLineMidpoint(NSPoint lineStart, NSPoint lineEnd);
-
-NSPoint FBAddPoint(NSPoint point1, NSPoint point2);
-NSPoint FBScalePoint(NSPoint point, CGFloat scale);
-NSPoint FBUnitScalePoint(NSPoint point, CGFloat scale);
-NSPoint FBSubtractPoint(NSPoint point1, NSPoint point2);
-CGFloat FBDotMultiplyPoint(NSPoint point1, NSPoint point2);
-CGFloat FBPointLength(NSPoint point);
-CGFloat FBPointSquaredLength(NSPoint point);
-NSPoint FBNormalizePoint(NSPoint point);
-NSPoint FBNegatePoint(NSPoint point);
-NSPoint FBRoundPoint(NSPoint point);
-
-NSPoint FBRectGetTopLeft(NSRect rect);
-NSPoint FBRectGetTopRight(NSRect rect);
-NSPoint FBRectGetBottomLeft(NSRect rect);
-NSPoint FBRectGetBottomRight(NSRect rect);
-
-void FBExpandBoundsByPoint(NSPoint *topLeft, NSPoint *bottomRight, NSPoint point);
-NSRect FBUnionRect(NSRect rect1, NSRect rect2);
-
-BOOL FBArePointsClose(NSPoint point1, NSPoint point2);
-BOOL FBArePointsCloseWithOptions(NSPoint point1, NSPoint point2, CGFloat threshold);
-BOOL FBAreValuesClose(CGFloat value1, CGFloat value2);
-BOOL FBAreValuesCloseWithOptions(CGFloat value1, CGFloat value2, CGFloat threshold);
-
-//////////////////////////////////////////////////////////////////////////
-// Angle Range structure provides a simple way to store angle ranges
-//  and determine if a specific angle falls within. 
-//
-typedef struct FBAngleRange {
-    CGFloat minimum;
-    CGFloat maximum;
-} FBAngleRange;
-
-FBAngleRange FBAngleRangeMake(CGFloat minimum, CGFloat maximum);
-BOOL FBAngleRangeContainsAngle(FBAngleRange range, CGFloat angle);
-
-CGFloat NormalizeAngle(CGFloat value);
-CGFloat PolarAngle(NSPoint point);
-
-//////////////////////////////////////////////////////////////////////////////////
-// Parameter ranges
-//
-
-// FBRange is a range of parameter (t)
-typedef struct FBRange {
-    CGFloat minimum;
-    CGFloat maximum;
-} FBRange;
-
-extern FBRange FBRangeMake(CGFloat minimum, CGFloat maximum);
-extern BOOL FBRangeHasConverged(FBRange range, NSUInteger places);
-extern CGFloat FBRangeGetSize(FBRange range);
-extern CGFloat FBRangeAverage(FBRange range);
-extern CGFloat FBRangeScaleNormalizedValue(FBRange range, CGFloat value);
-
-extern BOOL FBTangentsCross(NSPoint edge1Tangents[2], NSPoint edge2Tangents[2]);

File VectorBoolean/Geometry.m

-//
-//  Geometry.m
-//  VectorBrush
-//
-//  Created by Andrew Finnell on 5/28/11.
-//  Copyright 2011 Fortunate Bear, LLC. All rights reserved.
-//
-
-#import "Geometry.h"
-
-static const CGFloat FBPointClosenessThreshold = 1e-10;
-
-
-CGFloat FBDistanceBetweenPoints(NSPoint point1, NSPoint point2)
-{
-    CGFloat xDelta = point2.x - point1.x;
-    CGFloat yDelta = point2.y - point1.y;
-    return sqrt(xDelta * xDelta + yDelta * yDelta);
-}
-
-CGFloat FBDistancePointToLine(NSPoint point, NSPoint lineStartPoint, NSPoint lineEndPoint)
-{
-    CGFloat lineLength = FBDistanceBetweenPoints(lineStartPoint, lineEndPoint);
-    if ( lineLength == 0 )
-        return 0;
-    CGFloat u = ((point.x - lineStartPoint.x) * (lineEndPoint.x - lineStartPoint.x) + (point.y - lineStartPoint.y) * (lineEndPoint.y - lineStartPoint.y)) / (lineLength * lineLength);
-    NSPoint intersectionPoint = NSMakePoint(lineStartPoint.x + u * (lineEndPoint.x - lineStartPoint.x), lineStartPoint.y + u * (lineEndPoint.y - lineStartPoint.y));
-    return FBDistanceBetweenPoints(point, intersectionPoint);
-}
-
-NSPoint FBAddPoint(NSPoint point1, NSPoint point2)
-{
-    return NSMakePoint(point1.x + point2.x, point1.y + point2.y);
-}
-
-NSPoint FBUnitScalePoint(NSPoint point, CGFloat scale)
-{
-    NSPoint result = point;
-    CGFloat length = FBPointLength(point);
-    if ( length != 0.0 ) {
-        result.x *= scale/length;
-        result.y *= scale/length;
-    }
-    return result;
-}
-
-NSPoint FBScalePoint(NSPoint point, CGFloat scale)
-{
-    return NSMakePoint(point.x * scale, point.y * scale);
-}
-
-CGFloat FBDotMultiplyPoint(NSPoint point1, NSPoint point2)
-{
-    return point1.x * point2.x + point1.y * point2.y;
-}
-
-NSPoint FBSubtractPoint(NSPoint point1, NSPoint point2)
-{
-    return NSMakePoint(point1.x - point2.x, point1.y - point2.y);
-}
-
-CGFloat FBPointLength(NSPoint point)
-{
-    return sqrt((point.x * point.x) + (point.y * point.y));
-}
-
-CGFloat FBPointSquaredLength(NSPoint point)
-{
-    return (point.x * point.x) + (point.y * point.y);
-}
-
-NSPoint FBNormalizePoint(NSPoint point)
-{
-    NSPoint result = point;
-    CGFloat length = FBPointLength(point);
-    if ( length != 0.0 ) {
-        result.x /= length;
-        result.y /= length;
-    }
-    return result;
-}
-
-NSPoint FBNegatePoint(NSPoint point)
-{
-    return NSMakePoint(-point.x, -point.y);
-}
-
-NSPoint FBRoundPoint(NSPoint point)
-{
-    NSPoint result = { round(point.x), round(point.y) };
-    return result;
-}
-
-NSPoint FBLineNormal(NSPoint lineStart, NSPoint lineEnd)
-{
-    return FBNormalizePoint(NSMakePoint(-(lineEnd.y - lineStart.y), lineEnd.x - lineStart.x));
-}
-
-NSPoint FBLineMidpoint(NSPoint lineStart, NSPoint lineEnd)
-{
-    CGFloat distance = FBDistanceBetweenPoints(lineStart, lineEnd);
-    NSPoint tangent = FBNormalizePoint(FBSubtractPoint(lineEnd, lineStart));
-    return FBAddPoint(lineStart, FBUnitScalePoint(tangent, distance / 2.0));
-}
-
-NSPoint FBRectGetTopLeft(NSRect rect)
-{
-    return NSMakePoint(NSMinX(rect), NSMinY(rect));
-}
-
-NSPoint FBRectGetTopRight(NSRect rect)
-{
-    return NSMakePoint(NSMaxX(rect), NSMinY(rect));
-}
-
-NSPoint FBRectGetBottomLeft(NSRect rect)
-{
-    return NSMakePoint(NSMinX(rect), NSMaxY(rect));
-}
-
-NSPoint FBRectGetBottomRight(NSRect rect)
-{
-    return NSMakePoint(NSMaxX(rect), NSMaxY(rect));
-}
-
-void FBExpandBoundsByPoint(NSPoint *topLeft, NSPoint *bottomRight, NSPoint point)
-{
-    if ( point.x < topLeft->x )
-        topLeft->x = point.x;
-    if ( point.x > bottomRight->x )
-        bottomRight->x = point.x;
-    if ( point.y < topLeft->y )
-        topLeft->y = point.y;
-    if ( point.y > bottomRight->y )
-        bottomRight->y = point.y;
-}
-
-NSRect FBUnionRect(NSRect rect1, NSRect rect2)
-{
-    NSPoint topLeft = FBRectGetTopLeft(rect1);
-    NSPoint bottomRight = FBRectGetBottomRight(rect1);
-    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetTopLeft(rect2));
-    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetTopRight(rect2));
-    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetBottomRight(rect2));
-    FBExpandBoundsByPoint(&topLeft, &bottomRight, FBRectGetBottomLeft(rect2));    
-    return NSMakeRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
-}
-
-BOOL FBArePointsClose(NSPoint point1, NSPoint point2)
-{
-    return FBArePointsCloseWithOptions(point1, point2, FBPointClosenessThreshold);
-}
-
-BOOL FBArePointsCloseWithOptions(NSPoint point1, NSPoint point2, CGFloat threshold)
-{
-    return FBAreValuesCloseWithOptions(point1.x, point2.x, threshold) && FBAreValuesCloseWithOptions(point1.y, point2.y, threshold);
-}
-
-BOOL FBAreValuesClose(CGFloat value1, CGFloat value2)
-{
-    return FBAreValuesCloseWithOptions(value1, value2, FBPointClosenessThreshold);
-}
-
-BOOL FBAreValuesCloseWithOptions(CGFloat value1, CGFloat value2, CGFloat threshold)
-{
-    CGFloat delta = value1 - value2;    
-    return (delta <= threshold) && (delta >= -threshold);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Helper methods for angles
-//
-static const CGFloat FB2PI = 2.0 * M_PI;
-
-// Normalize the angle between 0 and 2pi
-CGFloat NormalizeAngle(CGFloat value)
-{
-    while ( value < 0.0 )
-        value += FB2PI;
-    while ( value >= FB2PI )
-        value -= FB2PI;
-    return value;
-}
-
-// Compute the polar angle from the cartesian point
-CGFloat PolarAngle(NSPoint point)
-{
-    CGFloat value = 0.0;
-    if ( point.x > 0.0 )
-        value = atan(point.y / point.x);
-    else if ( point.x < 0.0 ) {
-        if ( point.y >= 0.0 )
-            value = atan(point.y / point.x) + M_PI;
-        else
-            value = atan(point.y / point.x) - M_PI;
-    } else {
-        if ( point.y > 0.0 )
-            value =  M_PI_2;
-        else if ( point.y < 0.0 )
-            value =  -M_PI_2;
-        else
-            value = 0.0;
-    }
-    return NormalizeAngle(value);
-}
-
-
-FBAngleRange FBAngleRangeMake(CGFloat minimum, CGFloat maximum)
-{
-    FBAngleRange range = { minimum, maximum };
-    return range;
-}
-
-BOOL FBAngleRangeContainsAngle(FBAngleRange range, CGFloat angle)
-{
-    if ( range.minimum <= range.maximum )
-        return angle > range.minimum && angle < range.maximum;
-    
-    // The range wraps around 0. See if the angle falls in the first half
-    if ( angle > range.minimum && angle <= FB2PI )
-        return YES;
-    
-    return angle >= 0.0 && angle < range.maximum;
-}
-
-//////////////////////////////////////////////////////////////////////////////////
-// Parameter ranges
-//
-FBRange FBRangeMake(CGFloat minimum, CGFloat maximum)
-{
-    FBRange range = { minimum, maximum };
-    return range;
-}
-
-BOOL FBRangeHasConverged(FBRange range, NSUInteger places)
-{
-    CGFloat factor = pow(10.0, places);
-    NSInteger minimum = (NSInteger)(range.minimum * factor);
-    NSInteger maxiumum = (NSInteger)(range.maximum * factor);
-    return minimum == maxiumum;
-}
-
-CGFloat FBRangeGetSize(FBRange range)
-{
-    return range.maximum - range.minimum;
-}
-
-CGFloat FBRangeAverage(FBRange range)
-{
-    return (range.minimum + range.maximum) / 2.0;
-}
-
-CGFloat FBRangeScaleNormalizedValue(FBRange range, CGFloat value)
-{
-    return (range.maximum - range.minimum) * value + range.minimum;
-}
-
-
-BOOL FBTangentsCross(NSPoint edge1Tangents[2], NSPoint edge2Tangents[2])
-{    
-    // Calculate angles for the tangents
-    CGFloat edge1Angles[] = { PolarAngle(edge1Tangents[0]), PolarAngle(edge1Tangents[1]) };
-    CGFloat edge2Angles[] = { PolarAngle(edge2Tangents[0]), PolarAngle(edge2Tangents[1]) };
-    
-    // Count how many times edge2 angles appear between the self angles
-    FBAngleRange range1 = FBAngleRangeMake(edge1Angles[0], edge1Angles[1]);
-    NSUInteger rangeCount1 = 0;
-    if ( FBAngleRangeContainsAngle(range1, edge2Angles[0]) )
-        rangeCount1++;
-    if ( FBAngleRangeContainsAngle(range1, edge2Angles[1]) )
-        rangeCount1++;
-    
-    // Count how many times self angles appear between the edge2 angles
-    FBAngleRange range2 = FBAngleRangeMake(edge1Angles[1], edge1Angles[0]);
-    NSUInteger rangeCount2 = 0;
-    if ( FBAngleRangeContainsAngle(range2, edge2Angles[0]) )
-        rangeCount2++;
-    if ( FBAngleRangeContainsAngle(range2, edge2Angles[1]) )
-        rangeCount2++;
-    
-    // If each pair of angles split the other two, then the edges cross.
-    return rangeCount1 == 1 && rangeCount2 == 1;
-}

File VectorBoolean/NSBezierPath+Utilities.m

 //
 
 #import "NSBezierPath+Utilities.h"
-#import "Geometry.h"
+#import "FBGeometry.h"
 
 static const CGFloat FBDebugPointSize = 10.0;
 static const CGFloat FBDebugSmallPointSize = 3.0;