Skip to content

Commit c5c790d

Browse files
authored
Merge pull request #12 from hfutrell/0.1.6-release
0.1.6 release
2 parents 26217dd + c36e223 commit c5c790d

14 files changed

+344
-270
lines changed

BezierKit.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
Pod::Spec.new do |s|
77
s.name = "BezierKit"
8-
s.version = "0.1.4"
9-
s.summary = "BezierKit is a library for Bézier curves written in Swift and based on the popular JavaScript library Bezier.js"
8+
s.version = "0.1.6"
9+
s.summary = "comprehensive Bezier curve library written in Swift based on the popular Bezier.js library"
1010
s.homepage = "https://github.com/hfutrell/BezierKit"
1111
s.license = "MIT"
1212
s.author = { "Holmes Futrell" => "holmesfutrell@gmail.com" }

BezierKit/BezierKitTests/BoundingBoxTests.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,54 @@ class BoundingBoxTests: XCTestCase {
6161
XCTAssertEqual(box.upperBoundOfDistance(to: p4), sqrt(17.0))
6262
XCTAssertEqual(box.upperBoundOfDistance(to: p5), sqrt(52.0))
6363
}
64+
65+
func testArea() {
66+
let box = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
67+
XCTAssertEqual(box.area, 2.0)
68+
let emptyBox = BoundingBox.empty
69+
XCTAssertEqual(emptyBox.area, 0.0)
70+
}
71+
72+
func testOverlaps() {
73+
let box1 = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
74+
let box2 = BoundingBox(p1: CGPoint(x: 2.5, y: 6.0), p2: CGPoint(x: 3.0, y: 8.0))
75+
let box3 = BoundingBox(p1: CGPoint(x: 2.5, y: 4.0), p2: CGPoint(x: 3.0, y: 8.0))
76+
XCTAssertFalse(box1.overlaps(box2))
77+
XCTAssertTrue(box1.overlaps(box3))
78+
XCTAssertFalse(box1.overlaps(BoundingBox.empty))
79+
}
80+
81+
func testUnionEmpty1() {
82+
var empty1 = BoundingBox.empty
83+
let empty2 = BoundingBox.empty
84+
XCTAssertEqual(empty1.union(empty2), BoundingBox.empty)
85+
}
86+
87+
func testUnionEmpty2() {
88+
var empty = BoundingBox.empty
89+
let box = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
90+
XCTAssertEqual(empty.union(box), box)
91+
}
92+
93+
func testUnion() {
94+
var box1 = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
95+
let box2 = BoundingBox(p1: CGPoint(x: 2.5, y: 6.0), p2: CGPoint(x: 3.0, y: 8.0))
96+
XCTAssertEqual(box1.union(box2), BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 8.0)))
97+
}
98+
99+
func testCGRect() {
100+
// test a standard box
101+
let box1 = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
102+
XCTAssertEqual(box1.cgRect, CGRect(origin: CGPoint(x: 2.0, y: 3.0), size: CGSize(width: 1.0, height: 2.0)))
103+
// test the empty box
104+
XCTAssertEqual(BoundingBox.empty.cgRect, CGRect.null)
105+
}
106+
107+
func testInitFirstSecond() {
108+
let box1 = BoundingBox(p1: CGPoint(x: 2.0, y: 3.0), p2: CGPoint(x: 3.0, y: 5.0))
109+
let box2 = BoundingBox(p1: CGPoint(x: 1.0, y: 1.0), p2: CGPoint(x: 2.0, y: 2.0))
110+
let result = BoundingBox(first: box1, second: box2)
111+
XCTAssertEqual(result, BoundingBox(p1: CGPoint(x: 1.0, y: 1.0), p2: CGPoint(x: 3.0, y: 5.0)))
112+
}
113+
64114
}

BezierKit/BezierKitTests/PathTests.swift

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class PathTests: XCTestCase {
2323

2424
func testInitCGPathEmpty() {
2525
// trivial test of an empty path
26-
let path = Path(CGMutablePath())
26+
let path = Path(cgPath: CGMutablePath())
2727
XCTAssert(path.subpaths.isEmpty)
2828
}
2929

@@ -32,7 +32,7 @@ class PathTests: XCTestCase {
3232
// simple test of a rectangle (note that this CGPath uses a moveTo())
3333
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 1, height: 2))
3434
let cgPath1 = CGPath(rect: rect, transform: nil)
35-
let path1 = Path(cgPath1)
35+
let path1 = Path(cgPath: cgPath1)
3636

3737
let p1 = CGPoint(x: 0.0, y: 0.0)
3838
let p2 = CGPoint(x: 1.0, y: 0.0)
@@ -50,7 +50,7 @@ class PathTests: XCTestCase {
5050
// test of a ellipse (4 cubic curves)
5151
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 1, height: 2))
5252
let cgPath2 = CGPath(ellipseIn: rect, transform: nil)
53-
let path2 = Path(cgPath2)
53+
let path2 = Path(cgPath: cgPath2)
5454

5555
let p1 = CGPoint(x: 1.0, y: 1.0)
5656
let p2 = CGPoint(x: 0.5, y: 2.0)
@@ -87,7 +87,7 @@ class PathTests: XCTestCase {
8787
cgPath3.addQuadCurve(to: p1, control: p6)
8888
cgPath3.closeSubpath()
8989

90-
let path3 = Path(cgPath3)
90+
let path3 = Path(cgPath: cgPath3)
9191
XCTAssertEqual(path3.subpaths.count, 1)
9292
XCTAssertEqual(path3.subpaths[0].curves.count, 4)
9393
XCTAssertEqual(path3.subpaths[0].curves[1] as! QuadraticBezierCurve, QuadraticBezierCurve(p0: p2, p1: p3, p2: p4))
@@ -107,7 +107,7 @@ class PathTests: XCTestCase {
107107
cgPath4.move(to: p3)
108108
cgPath4.addLine(to: p4)
109109

110-
let path4 = Path(cgPath4)
110+
let path4 = Path(cgPath: cgPath4)
111111
XCTAssertEqual(path4.subpaths.count, 2)
112112
XCTAssertEqual(path4.subpaths[0].curves.count, 1)
113113
XCTAssertEqual(path4.subpaths[1].curves.count, 1)
@@ -121,12 +121,12 @@ class PathTests: XCTestCase {
121121
let circleCGPath = CGMutablePath()
122122
circleCGPath.addEllipse(in: CGRect(origin: CGPoint(x: 2.0, y: 3.0), size: CGSize(width: 2.0, height: 2.0)))
123123

124-
let circlePath = Path(circleCGPath) // a circle centered at (3, 4) with radius 2
124+
let circlePath = Path(cgPath: circleCGPath) // a circle centered at (3, 4) with radius 2
125125

126126
let rectangleCGPath = CGMutablePath()
127127
rectangleCGPath.addRect(CGRect(origin: CGPoint(x: 3.0, y: 4.0), size: CGSize(width: 2.0, height: 2.0)))
128128

129-
let rectanglePath = Path(rectangleCGPath)
129+
let rectanglePath = Path(cgPath: rectangleCGPath)
130130

131131
let intersections = rectanglePath.intersects(path: circlePath)
132132

@@ -139,7 +139,7 @@ class PathTests: XCTestCase {
139139
let circleCGPath = CGMutablePath()
140140
circleCGPath.addEllipse(in: CGRect(origin: CGPoint(x: -1.0, y: -1.0), size: CGSize(width: 2.0, height: 2.0)))
141141

142-
let circlePath = Path(circleCGPath) // a circle centered at origin with radius 1
142+
let circlePath = Path(cgPath: circleCGPath) // a circle centered at origin with radius 1
143143

144144
let d = CGFloat(0.1)
145145
let p1 = CGPoint(x: -3.0, y: 0.0)
@@ -155,4 +155,34 @@ class PathTests: XCTestCase {
155155

156156
}
157157

158+
func testEquatable() {
159+
let rect = CGRect(origin: CGPoint(x: -1, y: -1), size: CGSize(width: 2, height: 2))
160+
let path1 = Path(cgPath: CGPath(rect: rect, transform: nil))
161+
let path2 = Path(cgPath: CGPath(ellipseIn: rect, transform: nil))
162+
let path3 = Path(cgPath: CGPath(rect: rect, transform: nil))
163+
XCTAssertNotEqual(path1, path2)
164+
XCTAssertEqual(path1, path3)
165+
}
166+
167+
func testIsEqual() {
168+
let rect = CGRect(origin: CGPoint(x: -1, y: -1), size: CGSize(width: 2, height: 2))
169+
let path1 = Path(cgPath: CGPath(rect: rect, transform: nil))
170+
let path2 = Path(cgPath: CGPath(ellipseIn: rect, transform: nil))
171+
let path3 = Path(cgPath: CGPath(rect: rect, transform: nil))
172+
173+
let string = "hello" as NSString
174+
175+
XCTAssertFalse(path1.isEqual(nil))
176+
XCTAssertFalse(path1.isEqual(string))
177+
XCTAssertFalse(path1.isEqual(path2))
178+
XCTAssertTrue(path1.isEqual(path3))
179+
}
180+
181+
func testEncodeDecode() {
182+
let rect = CGRect(origin: CGPoint(x: -1, y: -1), size: CGSize(width: 2, height: 2))
183+
let path = Path(cgPath: CGPath(rect: rect, transform: nil))
184+
let data = NSKeyedArchiver.archivedData(withRootObject: path)
185+
let decodedPath = NSKeyedUnarchiver.unarchiveObject(with: data) as! Path
186+
XCTAssertEqual(decodedPath, path)
187+
}
158188
}

BezierKit/BezierKitTests/PolyBezierTests.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,70 @@ class PolyBezierTests: XCTestCase {
3737
}
3838
}
3939

40+
private let p1 = CGPoint(x: 0.0, y: 1.0)
41+
private let p2 = CGPoint(x: 2.0, y: 1.0)
42+
private let p3 = CGPoint(x: 2.5, y: 0.5)
43+
private let p4 = CGPoint(x: 2.0, y: 0.0)
44+
private let p5 = CGPoint(x: 0.0, y: 0.0)
45+
private let p6 = CGPoint(x: -0.5, y: 0.25)
46+
private let p7 = CGPoint(x: -0.5, y: 0.75)
47+
private let p8 = CGPoint(x: 0.0, y: 1.0)
48+
49+
func testEquatable() {
50+
51+
let l1 = LineSegment(p0: p1, p1: p2)
52+
let q1 = QuadraticBezierCurve(p0: p2, p1: p3, p2: p4)
53+
let l2 = LineSegment(p0: p4, p1: p5)
54+
let c1 = CubicBezierCurve(p0: p5, p1: p6, p2: p7, p3: p8)
55+
56+
let polyBezier1 = PolyBezier(curves: [l1, q1, l2, c1])
57+
let polyBezier2 = PolyBezier(curves: [l1, q1, l2])
58+
let polyBezier3 = PolyBezier(curves: [l1, q1, l2, c1])
59+
60+
var altC1 = c1
61+
altC1.p2.x = -0.25
62+
let polyBezier4 = PolyBezier(curves: [l1, q1, l2, altC1])
63+
64+
XCTAssertNotEqual(polyBezier1, polyBezier2) // polyBezier2 is missing 4th path element, so not equal
65+
XCTAssertEqual(polyBezier1, polyBezier3) // same path elements means equal
66+
XCTAssertNotEqual(polyBezier1, polyBezier4) // polyBezier4 has an element with a modified path
67+
}
68+
69+
func testIsEqual() {
70+
71+
let l1 = LineSegment(p0: p1, p1: p2)
72+
let q1 = QuadraticBezierCurve(p0: p2, p1: p3, p2: p4)
73+
let l2 = LineSegment(p0: p4, p1: p5)
74+
let c1 = CubicBezierCurve(p0: p5, p1: p6, p2: p7, p3: p8)
75+
76+
let polyBezier1 = PolyBezier(curves: [l1, q1, l2, c1])
77+
let polyBezier2 = PolyBezier(curves: [l1, q1, l2, c1])
78+
var altC1 = c1
79+
altC1.p2.x = -0.25
80+
let polyBezier3 = PolyBezier(curves: [l1, q1, l2, altC1])
81+
82+
let string = "hello!" as NSString
83+
84+
XCTAssertFalse(polyBezier1.isEqual(string))
85+
XCTAssertFalse(polyBezier1.isEqual(nil))
86+
XCTAssertTrue(polyBezier1.isEqual(polyBezier1))
87+
XCTAssertTrue(polyBezier1.isEqual(polyBezier2))
88+
XCTAssertFalse(polyBezier1.isEqual(polyBezier3))
89+
}
90+
91+
func testNSCoder() {
92+
93+
let l1 = LineSegment(p0: p1, p1: p2)
94+
let q1 = QuadraticBezierCurve(p0: p2, p1: p3, p2: p4)
95+
let l2 = LineSegment(p0: p4, p1: p5)
96+
let c1 = CubicBezierCurve(p0: p5, p1: p6, p2: p7, p3: p8)
97+
let polyBezier = PolyBezier(curves: [l1, q1, l2, c1])
98+
99+
let data = NSKeyedArchiver.archivedData(withRootObject: polyBezier)
100+
let decodedPolyBezier = NSKeyedUnarchiver.unarchiveObject(with: data) as! PolyBezier
101+
XCTAssertEqual(polyBezier, decodedPolyBezier )
102+
103+
}
104+
40105
}
41106

BezierKit/Library/BezierCurve.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,21 @@ extension BezierCurve {
580580

581581
public let defaultIntersectionThreshold = CGFloat(0.5)
582582

583+
// MARK: factory
584+
585+
internal func createCurve(from points: [CGPoint]) -> BezierCurve? {
586+
switch points.count {
587+
case 2:
588+
return LineSegment(points: points)
589+
case 3:
590+
return QuadraticBezierCurve(points: points)
591+
case 4:
592+
return CubicBezierCurve(points: points)
593+
default:
594+
return nil
595+
}
596+
}
597+
583598
public func == (left: BezierCurve, right: BezierCurve) -> Bool {
584599
return left.points == right.points
585600
}

0 commit comments

Comments
 (0)