mathandy / svgpathtools

A collection of tools for manipulating and analyzing SVG Path objects and Bezier curves.
MIT License
557 stars 142 forks source link

Path.intersect() withholds some intersections from the result due to a typo #94

Closed StanLivitski closed 3 years ago

StanLivitski commented 5 years ago

With the following shapes intersecting in 2 places:


from svgpathtools.parser import parse_path

# clipping rectangle
p1 = parse_path('M0.0 0.0 L27.84765625 0.0 L27.84765625 242.6669922 L0.0 242.6669922 z')

# frame with curved corners
p2 = parse_path('M166.8359375,235.5478516c0,3.7773438-3.0859375,6.8691406-6.8701172,6.8691406H7.1108398c-3.7749023,0-6.8608398-3.0917969-6.8608398-6.8691406V7.1201172C0.25,3.3427734,3.3359375,0.25,7.1108398,0.25h152.8549805c3.7841797,0,6.8701172,3.0927734,6.8701172,6.8701172v228.4277344z')

I see this REPL output:


>>> print(len(p1.intersect(p2)))
2
>>> print(len(p2.intersect(p1)))
1

This seems to be caused by Path.intersect() removing some intersections from the result due to a typo. If I patch svgpathtools/path.py version 1.3.3 at line 2196 as follows:

<            pts = [seg1.point(_t1) for _T1, _seg1, _t1 in list(zip(*intersection_list))[0]]
---
>            pts = [_seg1.point(_t1) for _T1, _seg1, _t1 in list(zip(*intersection_list))[0]]

I get the expected result:


>>> print(len(p1.intersect(p2)))
2
>>> print(len(p2.intersect(p1)))
2

BTW, it would be nice to make a new release of svgpathtools and pick up all bug fixes accumulated since last summer, including a fix for this issue :)

tatarize commented 3 years ago

Confirmed. By definition the intersections are the same going either direction.

    def test_issue_94(self):
        # clipping rectangle
        p1 = Path('M0.0 0.0 L27.84765625 0.0 L27.84765625 242.6669922 L0.0 242.6669922 z')
        # clipping rectangle
        p2 = Path('M166.8359375,235.5478516c0,3.7773438-3.0859375,6.8691406-6.8701172,6.8691406H7.1108398c-3.7749023,0-6.8608398-3.0917969-6.8608398-6.8691406V7.1201172C0.25,3.3427734,3.3359375,0.25,7.1108398,0.25h152.8549805c3.7841797,0,6.8701172,3.0927734,6.8701172,6.8701172v228.4277344z')
        self.assertEqual(len(p1.intersect(p2)), len(p2.intersect(p1)))

Ran 1 test in 0.062s

FAILED (failures=1)

1 != 2

Expected :2 Actual :1