Method for checking if one path is inside another path (#105)

* Added method is_contained_by to the Path class

* Adding a requirements.txt file

Signed-off-by: David Romero <dromero.fisica@gmail.com>

* Correcting tests of is_contained_by
pull/114/head
David Romero 2020-06-19 21:36:22 -05:00 committed by GitHub
parent f99f9d6bb3
commit 90f8f76185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 2 deletions

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
numpy
svgwrite

View File

@ -115,7 +115,6 @@ def polygon(*points):
return Path(*[Line(points[i], points[(i + 1) % len(points)])
for i in range(len(points))])
# Conversion###################################################################
def bpoints2bezier(bpoints):
@ -2700,3 +2699,22 @@ class Path(MutableSequence):
def scaled(self, sx, sy=None, origin=0j):
"""Scale transform. See `scale` function for further explanation."""
return scale(self, sx=sx, sy=sy, origin=origin)
def is_contained_by(self, other):
"""Returns true if the path is fully contained in other closed path"""
assert isinstance(other, Path)
assert other.isclosed()
assert self != other
if self.intersect(other, justonemode=True):
return False
pt = self.point(0)
xmin, xmax, ymin, ymax = other.bbox()
pt_in_bbox = (xmin <= pt.real <= xmax) and (ymin <= pt.imag <= ymax)
if not pt_in_bbox:
return False
opt = complex(xmin-1, ymin-1)
return path_encloses_pt(pt, opt, other)

View File

@ -16,7 +16,6 @@ from svgpathtools.path import _NotImplemented4ArcException
# take too long and be too error prone. Instead the curves have been verified
# to be correct visually with the disvg() function.
def random_line():
x = (random.random() - 0.5) * 2000
y = (random.random() - 0.5) * 2000
@ -1783,6 +1782,33 @@ class TestPathTools(unittest.TestCase):
self.assertAlmostEqual(ccw_half_circle.area(), 3926.9908169872415, places=3)
self.assertAlmostEqual(ccw_half_circle.area(chord_length=1e-3), 3926.9908169872415, places=6)
def test_is_contained_by(self):
enclosing_shape = Path()
enclosing_shape.append(Line((0+0j), (0+100j)))
enclosing_shape.append(Line((0+100j), (100+100j)))
enclosing_shape.append(Line((100+100j), (100+0j)))
enclosing_shape.append(Line((100+0j), (0+0j)))
enclosed_path = Path()
enclosed_path.append(Line((10+10j), (90+90j)))
self.assertTrue(enclosed_path.is_contained_by(enclosing_shape))
not_enclosed_path = Path()
not_enclosed_path.append(Line((200+200j), (200+0j)))
self.assertFalse(not_enclosed_path.is_contained_by(enclosing_shape))
intersecting_path = Path()
intersecting_path.append(Line((50+50j), (200+50j)))
self.assertFalse(intersecting_path.is_contained_by(enclosing_shape))
larger_shape = Path()
larger_shape.append(Line((-10-10j), (-10+110j)))
larger_shape.append(Line((-10+110j), (110+110j)))
larger_shape.append(Line((110+110j), (110+-10j)))
larger_shape.append(Line((110-10j), (-10-10j)))
self.assertFalse(larger_shape.is_contained_by(enclosing_shape))
self.assertTrue(enclosing_shape.is_contained_by(larger_shape))
if __name__ == '__main__':
unittest.main()