def test_core_perim(): perim_depth = 5 assert core_perim_zone_coordinates(footprint, perim_depth)[0] == expected_footprint assert get_core(footprint, perim_depth) == Polygon2D(expected_footprint["Core_Zone"]) for idx, zone in enumerate( get_perims(footprint, get_core(footprint, perim_depth)), 1): assert zone == Polygon2D(expected_footprint["Perimeter_Zone_%i" % idx])
def test_equal_polygon3D(): # type: () -> None poly1 = Polygon2D([(1, 0, 0), (0, 0, 0), (0, 1, 0), (1, 1, 0)]) poly2 = Polygon2D([(1, 1, 0), (1, 0, 0), (0, 0, 0), (0, 1, 0)]) assert poly1 == poly2 poly1 = Polygon2D([(1, 0, 0), (0, 0, 0), (0, 1, 0), (1, 1, 0)]) poly2 = Polygon2D(reversed([(1, 1, 0), (1, 0, 0), (0, 0, 0), (0, 1, 0)])) assert poly1 != poly2
def test_bounding_box(): # type: () -> None poly = Polygon2D([(0, 0), (0, 1), (1, 1), (1, 0)]) poly3d = Polygon3D([(0, 0, 0), (0, 1, 1), (1, 1, 1), (1, 0, 0)]) expected = Polygon2D([(1, 1, 1), (1, 0, 0), (0, 0, 0), (0, 1, 1)]) result = poly3d.bounding_box assert almostequal(result, expected)
def get_perims(footprint, core): perims = [] poly = Polygon2D(footprint) for edge in poly.edges: c1 = sorted( product([edge.p1] * len(core), core), key=lambda x: x[0].relative_distance(x[1]), )[0][1] c2 = sorted( product([edge.p2] * len(core), core), key=lambda x: x[0].relative_distance(x[1]), )[0][1] perims.append(Polygon2D([c1, edge.p1, edge.p2, c2])) return perims
def test_polygon_repr(): # type: () -> None s2D = Polygon2D([(0, 0), (2, 0), (2, 0), (0, 0)]) # vertical assert eval(repr(s2D)) == s2D s3D = Polygon3D([(0, 0, 0), (2, 0, 0), (2, 2, 0), (0, 2, 0)]) # vertical assert eval(repr(s3D)) == s3D
def test_polygon_attributes(): # type: () -> None poly2d = Polygon2D([(0, 0), (0, 1), (1, 1), (1, 0)]) assert len(poly2d) == 4 assert poly2d.xs == [0, 0, 1, 1] assert poly2d.ys == [0, 1, 1, 0] assert poly2d.zs == [0, 0, 0, 0] assert poly2d.vertices_list == [(0, 0), (0, 1), (1, 1), (1, 0)] assert poly2d.vertices == [Vector2D(*v) for v in poly2d]
def test_difference_2D_polys_single(): # type: () -> None """Simplest test for difference_2D_polys This has two squares in the horizontal plane which overlap in one place. Fails if the two original polygons do not have the intersection removed. """ s1 = Polygon2D([(0, 2), (2, 2), (2, 0), (0, 0)]) # clockwise s2 = Polygon2D([(1, 3), (3, 3), (3, 1), (1, 1)]) # clockwise # clockwise ex_s1 = [Polygon2D([(0, 2), (1, 2), (1, 1), (2, 1), (2, 0), (0, 0)])] ex_s2 = [Polygon2D([(1, 3), (3, 3), (3, 1), (2, 1), (2, 2), (1, 2)])] expected = [ex_s1, ex_s2] result = [s1.difference(s2), s2.difference(s1)] assert result[0] == expected[0] assert result[1] == expected[1]
def test_intersect_2D_polys_single(): # type: () -> None """Simplest test for intersect_2D_polys This has two squares in the horizontal plane which overlap in one place. Fails if the expected overlapping shape is not returned. """ # surface is already a flat plane with z == 0 s1 = Polygon2D([(0, 2), (2, 2), (2, 0), (0, 0)]) # clockwise s2 = Polygon2D([(1, 3), (3, 3), (3, 1), (1, 1)]) # clockwise expected = [Polygon2D([(1, 2), (2, 2), (2, 1), (1, 1)])] # clockwise result = s1.intersect(s2) for res, exp in zip(result, expected): assert res == exp result = s2.intersect(s1) for res, exp in zip(result, expected): assert res == exp
def point_in_poly(point, poly): "True if a 2D point is in or on the edge of a 2D poly." # TODO: add dynamic quasi infinite point distance with bounding box clue qip1_r = Vector2D(10000, 0) # quasi-infinite point 1 to the right qip2_r = Vector2D(10000, 1) # quasi-infinite point 2 to the right qip1_l = Vector2D(-10000, 0) # quasi-infinite point 1 to the left qip2_l = Vector2D(-10000, 1) # quasi-infinite point 2 to the left test_poly_r = Polygon2D([ point, qip1_r, qip2_r ]) #.order_points('upperleftcorner') # maybe we wouldn't need this anyway test_poly_l = Polygon2D([ point, qip1_l, qip2_l ]) #.order_points('upperleftcorner') # maybe we wouldn't need this anyway #poly = poly.order_points('upperleftcorner') # maybe we wouldn't need this anyway inter_r = poly.intersect(test_poly_r) inter_l = poly.intersect(test_poly_l) if len(inter_r) == 0: inter_r.append([0]) if len(inter_l) == 0: inter_l.append([0]) no_inter_r = len(inter_r[0]) no_inter_l = len(inter_l[0]) return True if no_inter_r == 3 or no_inter_l == 3 else False # we will see how robust this is # check this again later
def test_rotate(): # type: () -> None """Test for rotating 3D polygons into 2D and back again.""" # At the origin s1 = Polygon3D([(0, 0, 2), (2, 0, 2), (0, 0, 0)]) # vertical expected = Polygon2D([(0, 2), (2, 2), (0, 0)]) # convert to 2D result = s1.project_to_2D() assert result == expected # revert to 3D result = result.project_to_3D(s1) assert result == s1 # Away from the origin s1 = Polygon3D([(1, 0, 2), (3, 0, 2), (1, 0, 0)]) # vertical expected = Polygon2D([(1, 2), (3, 2), (1, 0)]) # convert to 2D result = s1.project_to_2D() assert result == expected # revert to 3D result = result.project_to_3D(s1) assert result == s1 # Away from the origin s1 = Polygon3D([(0, 1, 1), (2, 2, 0), (2, 2, 2), (0, 1, 2)]) # vertical expected = Polygon2D([(0.0, 1.0), (2.0, 0.0), (2.0, 2.0), (0.0, 2.0)]) # convert to 2D result = s1.project_to_2D() assert result == expected # revert to 3D result = result.project_to_3D(s1) assert result == s1
def point_in_poly_depr1(point, poly): "True if a 2D point is in a 2D poly. Deprecated: This left out the points on the right hand side edges" # add dynamic quasi infinite point distance with bounding box clue qip1 = Vector2D(10000, 0) # quasi-infinite point qip2 = Vector2D(10000, 1) # quasi-infinite point 2 test_poly = Polygon2D([ point, qip1, qip2 ]) #.order_points('upperleftcorner') # maybe we wouldn't need this anyway #poly = poly.order_points('upperleftcorner') # maybe we wouldn't need this anyway inter = poly.intersect(test_poly) if len(inter) == 0: return False else: no_inter = len(inter[0]) #print(inter) return True if no_inter == 3 else False
def minimal_set(polys): """Remove overlaps from a set of polygons. :param polys: List of polygons. :returns: List of polygons with no overlaps. """ normal = polys[0].normal_vector as_2d = [p.project_to_2D() for p in polys] as_shapely = [Polygon(p) for p in as_2d] lines = [p.boundary for p in as_shapely] borders = unary_union(lines) shapes = [Polygon2D(p.boundary.coords) for p in polygonize(borders)] as_3d = [p.project_to_3D(polys[0]) for p in shapes] if not almostequal(as_3d[0].normal_vector, normal): as_3d = [p.invert_orientation() for p in as_3d] return [p for p in as_3d if p.area > 0]
def test_add_polygon_to_polygon(): # type: () -> None # 2D poly1 = Polygon2D([(1, 0), (0, 0), (0, 1)]) poly2 = Polygon2D([(1, 0), (1, 0), (1, 0)]) expected = Polygon2D([(2, 0), (1, 0), (1, 1)]) result = poly1 + poly2 assert almostequal(result, expected) vector = Vector2D(1, 0) result = poly1 + vector assert almostequal(result, expected) vector = Vector3D(1, 0, 0) try: result = poly1 + vector # should fail assert False except ValueError: pass # 3D poly1 = Polygon2D([(1, 0, 1), (0, 0, 1), (0, 1, 1)]) poly2 = Polygon2D([(1, 0, 1), (1, 0, 1), (1, 0, 1)]) expected = Polygon2D([(2, 0, 2), (1, 0, 2), (1, 1, 2)]) result = poly1 + poly2 assert almostequal(result, expected) vector = Vector3D(1, 0, 1) result = poly1 + vector assert almostequal(result, expected) vector = Vector2D(1, 0) try: result = poly1 + vector # should fail assert False except ValueError: pass
def get_core(footprint, perim_depth=None): poly = Polygon2D(footprint) core = poly.buffer(distance=-perim_depth) return core