From f9685e98315a3dbf793033a48f94da6519199b3f Mon Sep 17 00:00:00 2001 From: PBS Date: Wed, 26 Jul 2023 20:23:33 +0900 Subject: [PATCH 1/2] Strengthen ExpandToTransformedTest Improve the test so that the initial rectangle can be arbitrary, rather than a single point. This makes the test fail, which is fixed in the next commit. --- tests/elliptical-arc-test.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/elliptical-arc-test.cpp b/tests/elliptical-arc-test.cpp index 1f6eff7c..7ab8bae9 100644 --- a/tests/elliptical-arc-test.cpp +++ b/tests/elliptical-arc-test.cpp @@ -245,18 +245,20 @@ TEST(EllipticalArcTest, BezierIntersection) { TEST(EllipticalArcTest, ExpandToTransformedTest) { - auto test_curve = [] (EllipticalArc const &c) { - constexpr int N = 50; + auto test_curve = [] (EllipticalArc const &c, bool with_initial_bbox) { + constexpr int N = 200; for (int i = 0; i < N; i++) { auto angle = 2 * M_PI * i / N; auto transform = Affine(Rotate(angle)) * Scale(0.9, 1.2); + auto const box0 = with_initial_bbox ? Rect::from_xywh(10 * std::sin(angle * 13), 10 * std::sin(angle * 17), 5.0, 5.0) : OptRect(); + auto copy = std::unique_ptr(c.duplicate()); *copy *= transform; - auto box1 = copy->boundsExact(); + auto box1 = copy->boundsExact() | box0; auto pt = c.initialPoint() * transform; - auto box2 = Rect(pt, pt); + auto box2 = Rect(pt, pt) | box0; c.expandToTransformed(box2, transform); for (auto i : { X, Y }) { @@ -266,10 +268,12 @@ TEST(EllipticalArcTest, ExpandToTransformedTest) } }; - test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, 0.0, false, false, Point(1, 1))); - test_curve(EllipticalArc(Point(0, 0), 3.0, 2.0, M_PI / 6, false, false, Point(1, 1))); - test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, M_PI / 5, true, true, Point(1, 1))); - test_curve(EllipticalArc(Point(1, 0), 1.0, 0.0, M_PI / 5, false, false, Point(1, 1))); - test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(2, 0))); - test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(1, 0))); + for (auto b : { false, true }) { + test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, 0.0, false, false, Point(1, 1)), b); + test_curve(EllipticalArc(Point(0, 0), 3.0, 2.0, M_PI / 6, false, false, Point(1, 1)), b); + test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, M_PI / 5, true, true, Point(1, 1)), b); + test_curve(EllipticalArc(Point(1, 0), 1.0, 0.0, M_PI / 5, false, false, Point(1, 1)), b); + test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(2, 0)), b); + test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(1, 0)), b); + } } -- GitLab From b2f478f8298cec3755f3397b4248b16000b3a2ef Mon Sep 17 00:00:00 2001 From: PBS Date: Wed, 26 Jul 2023 20:26:11 +0900 Subject: [PATCH 2/2] Fix EllipticalArc::expandToTransformed() Don't use boundsFast() to cull elliptical arc segments because it works in the wrong coordinate system. In its place, add a correct culling check a bit later in the function, inside the lambda. Fixes https://gitlab.com/inkscape/lib2geom/-/issues/66 --- src/2geom/elliptical-arc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/2geom/elliptical-arc.cpp b/src/2geom/elliptical-arc.cpp index 63e534cd..64071fee 100644 --- a/src/2geom/elliptical-arc.cpp +++ b/src/2geom/elliptical-arc.cpp @@ -143,7 +143,7 @@ void EllipticalArc::expandToTransformed(Rect &bbox, Affine const &transform) con { bbox.expandTo(_final_point * transform); - if (isChord() || bbox.contains(_ellipse.boundsFast())) { + if (isChord()) { return; } @@ -154,10 +154,11 @@ void EllipticalArc::expandToTransformed(Rect &bbox, Affine const &transform) con auto const v = Point(trans[d], trans[d + 2]); auto const r = v.length(); auto const mid = trans[d + 4]; + auto const interval = Interval(mid - r, mid + r); if (_angles.isFull()) { - bbox[d].unionWith(Interval(mid - r, mid + r)); - } else { + bbox[d].unionWith(interval); + } else if (!bbox[d].contains(interval)) { auto const angle = Angle(v); if (_angles.contains(angle)) { bbox[d].expandTo(mid + r); -- GitLab