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_bypull/114/head
parent
f99f9d6bb3
commit
90f8f76185
|
@ -0,0 +1,2 @@
|
|||
numpy
|
||||
svgwrite
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue