From 80f01d6b5912032688e1095ecbf5486ea6e16a79 Mon Sep 17 00:00:00 2001 From: Holmes Futrell Date: Tue, 4 Jun 2019 11:31:10 -0700 Subject: [PATCH] test data from a real world case where roots was failing. --- BezierKit/BezierKitTests/UtilsTests.swift | 15 +++++++++++++++ BezierKit/Library/PathComponent.swift | 8 ++++---- BezierKit/Library/Utils.swift | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/BezierKit/BezierKitTests/UtilsTests.swift b/BezierKit/BezierKitTests/UtilsTests.swift index f686fd34..6cd82fcf 100644 --- a/BezierKit/BezierKitTests/UtilsTests.swift +++ b/BezierKit/BezierKitTests/UtilsTests.swift @@ -24,4 +24,19 @@ class UtilsTests: XCTestCase { XCTAssertTrue(Utils.clamp(CGFloat.nan, -1.0, 1.0).isNaN) } + func testRootsRealWorldIssue() { + let points: [CGPoint] = [ + CGPoint(x:523.4257521858988, y: 691.8949684622992), + CGPoint(x:523.1393916834338, y: 691.8714265856051), + CGPoint(x:522.8595588275791, y: 691.7501129962762), + CGPoint(x:522.6404735257349, y: 691.531027694432) + ] + let curve = CubicBezierCurve(points: points) + let y: CGFloat = 691.87778055040201 + let line = LineSegment(p0: CGPoint(x: 0, y: y), p1: CGPoint(x: 1, y: y)) + let r = Utils.roots(points: points, line: line) + let filtered = r.filter { $0 >= 0 && $0 <= 1 } + XCTAssertEqual(curve.compute(CGFloat(filtered[0])).y, y, accuracy: CGFloat(1.0e-5)) + } + } diff --git a/BezierKit/Library/PathComponent.swift b/BezierKit/Library/PathComponent.swift index 84a860e5..9999e106 100644 --- a/BezierKit/Library/PathComponent.swift +++ b/BezierKit/Library/PathComponent.swift @@ -402,11 +402,11 @@ import Foundation let d0 = p1.y - p0.y let d1 = p2.y - p1.y var last: CGFloat = 0.0 - Utils.droots(d0, d1, callback: { t in + Utils.droots(d0, d1) { t in guard t > 0, t < 1 else { return } callback(curve.split(from: last, to: t)) last = t - }) + } if last < 1.0 { callback(curve.split(from: last, to: 1.0)) } @@ -422,11 +422,11 @@ import Foundation let d1 = p2.y - p1.y let d2 = p3.y - p2.y var last: CGFloat = 0.0 - Utils.droots(d0, d1, d2, callback: { t in + Utils.droots(d0, d1, d2) { t in guard t > 0, t < 1 else { return } callback(curve.split(from: last, to: t)) last = t - }) + } if last < 1.0 { callback(curve.split(from: last, to: 1.0)) } diff --git a/BezierKit/Library/Utils.swift b/BezierKit/Library/Utils.swift index 374d38ce..e7e4614b 100644 --- a/BezierKit/Library/Utils.swift +++ b/BezierKit/Library/Utils.swift @@ -185,7 +185,7 @@ internal class Utils { let temp2 = 3*pb let temp3 = -3*pc let d = temp1 + temp2 + temp3 + pd - let smallValue = 1.0e-10 + let smallValue = 1.0e-8 if abs(d) < smallValue { let temp1 = 3*points[0] let temp2 = -6*points[1]