Skip to content

droots can have low precision in some cases, which could affect Path.contains(_ point:) #92

@hfutrell

Description

@hfutrell

Here is an example where droots gets low precision in 0.11.0

The unit test that demonstrates this issue was removed because it is somewhat low priority and represents a longstanding issue.

 func testDrootsCubicWorldIssue4() {
        // this test was failing due to round-off it seems
        let roots = drootsCubicTestHelper(117.11706850363589,
                                          39.0399142482629,
                                          -2.3525217329734005e-06,
                                          -2.352663614146877e-06)
        
        
        let filtered = roots.filter { $0 >= 0 && $0 <= 1 }
        XCTAssertEqual(filtered.count, 1)
        XCTAssertEqual(filtered.first!, CGFloat(0.999858), accuracy: 1.0e-5)
    }

The answer is gets for the root is 0.9997828474060952 which is incorrect in the 4th digit.

There was another related unit test that failed for the same reason:

    func testCrossingsRemovedFifthRealWorldCase() {
        // this test fails for the same reason that
        // `testDrootsCubicWorldIssue4` fails
        // the path doesn't have any self-intersections
        // but the `contains` call gives the wrong results
        let cgPath = CGMutablePath()
        cgPath.move(to: CGPoint(x: -45.58408505173276, y: 4384.210079234615))
        cgPath.addCurve(to: CGPoint(x: 519.756427723393, y: 4384.14765017776),
                        control1: CGPoint(x: 110.51314747385496, y: 4228.07836809298),
                        control2: CGPoint(x: 363.6247165817579, y: 4228.050417652172))
        cgPath.addCurve(to: CGPoint(x: 519.8188567802481, y: 4949.488162952885),
                        control1: CGPoint(x: 675.8881388650282, y: 4540.244882703348),
                        control2: CGPoint(x: 675.9160893058358, y: 4793.356451811251))
        cgPath.addCurve(to: CGPoint(x: 501.53832994006814, y: 4967.769608589276),
                        control1: CGPoint(x: 513.7155041887056, y: 4955.5928615872745),
                        control2: CGPoint(x: 507.6055609674461, y: 4961.702072477192))
        cgPath.addCurve(to: CGPoint(x: -63.802186103924214, y: 4967.783798079717),
                        control1: CGPoint(x: 345.4277755233733, y: 5123.887999645149),
                        control2: CGPoint(x: 92.31620495194895, y: 5123.894352496412))
        cgPath.addCurve(to: CGPoint(x: -63.81637559436501, y: 4402.443282035724),
                        control1: CGPoint(x: -219.92057715979726, y: 4811.673243663022),
                        control2: CGPoint(x: -219.9269300110598, y: 4558.561673091597))
        cgPath.addCurve(to: CGPoint(x: -45.58408505173276, y: 4384.210079234615),
                        control1: CGPoint(x: -57.725037285805456, y: 4396.351638460308),
                        control2: CGPoint(x: -51.63917972581493, y: 4390.2665134127255))
        let path = Path(cgPath: cgPath)
        let result = path.crossingsRemoved()
//      seems to fail because we get the wrnog results here:
//       we get the right results with 1.0e-5
//        let curve = path.components[0].curves[0]
//        let point = curve.point(at: 0.5) - 1.0e-7 * curve.normal(at: 0.5)
//        XCTAssertFalse(path.contains(point))
        XCTAssertEqual(path, result)
    }

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions