def test_polygon2d_init_from_regular_polygon(): """Test the initialization of Polygon2D from_regular_polygon.""" polygon = Polygon2D.from_regular_polygon(8, 2, Point2D(0, 1)) assert isinstance(polygon.vertices, tuple) assert len(polygon.vertices) == 8 for point in polygon.vertices: assert isinstance(point, Point2D) assert isinstance(polygon.segments, tuple) assert len(polygon.segments) == 8 for seg in polygon.segments: assert isinstance(seg, LineSegment2D) assert seg.length == pytest.approx(1.5307337, rel=1e-3) assert polygon.area == pytest.approx(11.3137084, rel=1e-3) assert polygon.perimeter == pytest.approx(1.5307337 * 8, rel=1e-3) assert not polygon.is_clockwise assert polygon.is_convex assert not polygon.is_self_intersecting polygon = Polygon2D.from_regular_polygon(3) assert len(polygon.vertices) == 3 polygon = Polygon2D.from_regular_polygon(20) assert len(polygon.vertices) == 20 with pytest.raises(AssertionError): polygon = Polygon2D.from_regular_polygon(2)
def test_intersect_polygon_segments_with_3_angled_rectangles(): """Tests that a vertex shared by 2 polygons is added only once to a 3rd polygon Make sure the addedvertex is which is colinear within tolerance. The polygons are rotated 45 degrees counter-clockwise to introduce floating-point closeness considerations. """ r2 = math.sqrt(2.0) tolerance = 0.02 expected_point = Point2D(r2, 0) pts0 = (Point2D(0, 0), Point2D(0.5 * r2 * 0.99, -0.5 * r2 * 0.99), Point2D(1.5 * r2 * 0.99, 0.5 * r2 * 0.99), Point2D(r2, r2)) polygon0 = Polygon2D(pts0) pts1 = (Point2D(0.5 * r2, -0.5 * r2), Point2D(r2, -r2), Point2D(1.5 * r2, -0.5 * r2), expected_point) polygon1 = Polygon2D(pts1) pts2 = (expected_point, Point2D(1.5 * r2, -0.5 * r2), Point2D(2 * r2, 0), Point2D(1.5 * r2, 0.5 * r2)) polygon2 = Polygon2D(pts2) polygons = Polygon2D.intersect_polygon_segments([polygon0, polygon1, polygon2], tolerance) # Extra vertex added to largest polygon, as expected assert len(polygons[0].segments) == 5 assert polygons[0].segments[1].p2 == polygons[0].vertices[2] assert polygons[0].segments[2].p1 == polygons[0].vertices[2] assert len(polygon1.segments) == 4 # No extra vertex added assert len(polygon2.segments) == 4 # No extra vertex added
def test_scale(): """Test the Polygon2D scale method.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon_1 = Polygon2D(pts_1) pts_2 = (Point2D(1, 1), Point2D(2, 1), Point2D(2, 2), Point2D(1, 2)) polygon_2 = Polygon2D(pts_2) origin_1 = Point2D(2, 0) origin_2 = Point2D(1, 1) new_polygon_1 = polygon_1.scale(2, origin_1) assert new_polygon_1[0] == Point2D(-2, 0) assert new_polygon_1[1] == Point2D(2, 0) assert new_polygon_1[2] == Point2D(2, 4) assert new_polygon_1[3] == Point2D(-2, 4) assert new_polygon_1.area == polygon_1.area ** 2 assert new_polygon_1.perimeter == polygon_1.perimeter * 2 assert new_polygon_1.is_clockwise is polygon_1.is_clockwise assert new_polygon_1.is_convex is polygon_1.is_convex assert new_polygon_1.is_self_intersecting is polygon_1.is_self_intersecting new_polygon_2 = polygon_2.scale(2, origin_2) assert new_polygon_2[0] == Point2D(1, 1) assert new_polygon_2[1] == Point2D(3, 1) assert new_polygon_2[2] == Point2D(3, 3) assert new_polygon_2[3] == Point2D(1, 3) assert new_polygon_2.area == 4 assert new_polygon_2.perimeter == polygon_2.perimeter * 2 assert new_polygon_2.is_clockwise is polygon_2.is_clockwise assert new_polygon_2.is_convex is polygon_2.is_convex assert new_polygon_2.is_self_intersecting is polygon_2.is_self_intersecting
def test_is_polygon_inside_outside(): """Test the is_polygon_inside and is_polygon_outside methods.""" bound_pts = [Point2D(0, 0), Point2D(4, 0), Point2D(4, 4), Point2D(0, 4)] hole_pts_1 = [ Point2D(1, 1), Point2D(1.5, 1), Point2D(1.5, 1.5), Point2D(1, 1.5) ] hole_pts_2 = [Point2D(2, 2), Point2D(3, 2), Point2D(3, 3), Point2D(2, 3)] hole_pts_3 = [Point2D(2, 2), Point2D(6, 2), Point2D(6, 6), Point2D(2, 6)] hole_pts_4 = [Point2D(5, 5), Point2D(6, 5), Point2D(6, 6), Point2D(5, 6)] polygon = Polygon2D(bound_pts) hole_1 = Polygon2D(hole_pts_1) hole_2 = Polygon2D(hole_pts_2) hole_3 = Polygon2D(hole_pts_3) hole_4 = Polygon2D(hole_pts_4) assert polygon.is_polygon_inside(hole_1) is True assert polygon.is_polygon_inside(hole_2) is True assert polygon.is_polygon_inside(hole_3) is False assert polygon.is_polygon_inside(hole_4) is False assert polygon.is_polygon_outside(hole_1) is False assert polygon.is_polygon_outside(hole_2) is False assert polygon.is_polygon_outside(hole_3) is False assert polygon.is_polygon_outside(hole_4) is True
def test_dict_to_object_win_par(): """Test the dict_to_object method with window parameters.""" simple_window = SingleWindow(5, 2, 0.8) ashrae_base1 = SimpleWindowRatio(0.4) ashrae_base2 = RepeatingWindowRatio(0.4, 2, 0.8, 3) bod_windows = RepeatingWindowWidthHeight(2, 1.5, 0.8, 3) origins = (Point2D(2, 1), Point2D(5, 0.5)) widths = (1, 3) heights = (1, 2) detailed_window1 = RectangularWindows(origins, widths, heights) pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window2 = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) assert isinstance(dict_to_object(simple_window.to_dict()), SingleWindow) assert isinstance(dict_to_object(ashrae_base1.to_dict()), SimpleWindowRatio) assert isinstance(dict_to_object(ashrae_base2.to_dict()), RepeatingWindowRatio) assert isinstance(dict_to_object(bod_windows.to_dict()), RepeatingWindowWidthHeight) assert isinstance(dict_to_object(detailed_window1.to_dict()), RectangularWindows) assert isinstance(dict_to_object(detailed_window2.to_dict()), DetailedWindows)
def test_polysplit_hashing(): """Test that tolerance sets hashing correctly from parent functions.""" poly = Polygon2D.from_array([[1.0123456789, 3.0123456789], [3.0123456789, 5.0123456789], [1.0123456789, 5.0123456789]]) # 7 digit tolerance w/ rounding tol = 1e-7 g = polysplit._skeleton_as_directed_graph(poly, holes=None, tol=tol) k = g.ordered_nodes[0].key assert k == '(1.0123457, 3.0123457)', k # 10 digit tolerance w/o rounding tol = 1e-10 g = polysplit._skeleton_as_directed_graph(poly, holes=None, tol=tol) k = g.ordered_nodes[0].key assert k == '(1.0123456789, 3.0123456789)', k # Test with number x 100 poly = Polygon2D.from_array([[100.0123456789, 300.0123456789], [300.0123456789, 500.0123456789], [100.0123456789, 500.0123456789]]) # 10 digit tolerance tol = 1e-7 g = polysplit._skeleton_as_directed_graph(poly, holes=None, tol=tol) k = g.ordered_nodes[0].key assert k == '(100.0123457, 300.0123457)', k # 10 digit tolerance w/o rounding tol = 1e-10 g = polysplit._skeleton_as_directed_graph(poly, holes=None, tol=tol) k = g.ordered_nodes[0].key assert k == '(100.0123456789, 300.0123456789)', k
def offset(polygon, distance, tol=1e-10): """Offset the polygon boundary by defined distance. Args: polygon: A Polygon2D object to offset. distance: Distance to offset. Only positive distance works in current implementation. tol: Tolerance for point equivalence. Returns: A list of offset contours as Polygon2D objects. """ _buffer_angle_tol = math.pi / 4 # 45 degrees # If positive do inward offset if distance > 0: _, offsets = polyskel.sub_polygons(polygon, distance, [], tol) return offsets # Init distance distance = abs(distance) sqrdist = distance * distance # Calculate buffer offset segments = list(polygon.segments) segments = segments + [segments[0]] buffer = 0.0 for i in range(len(segments) - 1): seg1, seg2 = segments[i], segments[i + 1] bisector = _offset_bisector(seg1, seg2, distance) if bisector.length > buffer: buffer = bisector.length buffer += (distance / 2.) # Make buffer buffer_frame = Polygon2D([ Point2D(polygon.max.x + buffer, polygon.max.y + buffer), Point2D(polygon.min.x - buffer, polygon.max.y + buffer), Point2D(polygon.min.x - buffer, polygon.min.y - buffer), Point2D(polygon.max.x + buffer, polygon.min.y - buffer) ]) holes = [list(reversed(polygon.vertices))] perimeter_sub_polygon = polyskel.sub_polygons(buffer_frame, distance, holes) mispqll = "" # Make a graph from the perimeter (offset) polygons so we infer the core polygons g = PolygonDirectedGraph(tol) for poly in perimeter_sub_polygon: pts = poly.vertices for i in range(len(pts) - 1): g.add_node(pts[i], [pts[i + 1]]) g.add_node(pts[-1], [pts[0]]) offset = Polygon2D([node.pt for node in g.exterior_cycles[-1]]) return offset, perimeter_sub_polygon
def test_geojson_coordinates_to_face3d(): """Test conversion of geojson nested list to face3d.""" # Set constants origin_lon_lat = (-70.0, 42.0) convert_facs = meters_to_long_lat_factors(origin_lon_lat) convert_facs = (1 / convert_facs[0], 1 / convert_facs[1]) # Test a Polygon geojson_polygon_coords = {'coordinates':[ [[-70.0, 42.0], [-69.99997578750273, 42.0], [-69.99997578750273, 42.00001799339205], [-70.0, 42.00001799339205], [-70.0, 42.0]]]} face3d = Model._geojson_coordinates_to_face3d( geojson_polygon_coords['coordinates'], origin_lon_lat, convert_facs) poly2d = Polygon2D([Point2D(v[0], v[1]) for v in face3d.vertices]) # Test that we get single polygon test_poly2d = Polygon2D( [Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)]) # Check length assert len(poly2d.vertices) == len(test_poly2d.vertices) # Check equivalence assert poly2d.is_equivalent(test_poly2d, 1e-5) # Test a Polygon w/ holes geojson_polygon_coords = {'coordinates':[ [[-70.0, 42.0], [-69.99997578750273, 42.0], [-69.99997578750273, 42.00001799339205], [-70.0, 42.00001799339205], [-70.0, 42.0]], [[-70.0, 42.0], [-69.99997578750273, 42.00001799339205], [-70.0, 42.00001799339205], [-70.0, 42.0]]]} face3d = Model._geojson_coordinates_to_face3d( geojson_polygon_coords['coordinates'], origin_lon_lat, convert_facs) # Check if hole exists assert face3d.has_holes # Convert to polygon polyhole2d = Polygon2D([Point2D(v[0], v[1]) for v in face3d.holes[0]]) # Test that we get single polygon test_polyhole2d = Polygon2D([Point2D(0, 0), Point2D(2, 2), Point2D(0, 2)]) # Check length assert len(polyhole2d.vertices) == len(test_polyhole2d.vertices) # Check equivalence assert polyhole2d.is_equivalent(test_polyhole2d, 1e-5)
def test_polygon2d_to_from_dict(): """Test the to/from dict of Polygon2D objects.""" pts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon = Polygon2D(pts) polygon_dict = polygon.to_dict() new_polygon = Polygon2D.from_dict(polygon_dict) assert isinstance(new_polygon, Polygon2D) assert new_polygon.to_dict() == polygon_dict
def test_is_self_intersecting(): """Test the is_self_intersecting property.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon_1 = Polygon2D(pts_1) pts_2 = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 0), Point2D(2, 2)) polygon_2 = Polygon2D(pts_2) assert not polygon_1.is_self_intersecting assert polygon_2.is_self_intersecting
def test_is_valid(): """Test the is_valid property.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2)) pts_2 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 0)) polygon_1 = Polygon2D(pts_1) polygon_2 = Polygon2D(pts_2) assert polygon_1.is_valid assert not polygon_2.is_valid
def window_par_detailed_windows(directory): pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) dest_file = os.path.join(directory, 'window_par_detailed_windows.json') with open(dest_file, 'w') as fp: json.dump(detailed_window.to_dict(), fp, indent=4)
def test_perimeter_core_subpolygons_hole_error(): """Test throwing an exception if hole doesn't get computed in straight skeleton.""" # Construct a simple rectangle poly = Polygon2D.from_array([[0, 0], [6, 0], [6, 8], [0, 8]]) holes = [Polygon2D.from_array([[2, 2], [4, 2], [4, 6], [2, 6]])] # Run method with pytest.raises(RuntimeError): _ = polysplit.perimeter_core_subpolygons(poly, 1, holes)
def test_detailed_init(): """Test the initalization of DetailedWindows and basic properties.""" pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) str(detailed_window) # test the string representation assert detailed_window.polygons[0].vertices == pts_1 assert detailed_window.polygons[1].vertices == pts_2
def test_remove_colinear_vertices(): """Test the remove_colinear_vertices method of Polygon2D.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) pts_2 = (Point2D(0, 0), Point2D(1, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon_1 = Polygon2D(pts_1) polygon_2 = Polygon2D(pts_2) assert len(polygon_1.remove_colinear_vertices(0.0001).vertices) == 4 assert len(polygon_2.remove_colinear_vertices(0.0001).vertices) == 4
def test_detailed_dict_methods(): """Test the to/from dict methods.""" pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) glz_dict = detailed_window.to_dict() new_detailed_window = DetailedWindows.from_dict(glz_dict) assert new_detailed_window == detailed_window assert glz_dict == new_detailed_window.to_dict()
def test_is_convex(): """Test the convex property.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon_1 = Polygon2D(pts_1) pts_2 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1), Point2D(1, 2), Point2D(0, 2)) polygon_2 = Polygon2D(pts_2) assert polygon_1.is_convex assert not polygon_2.is_convex
def test_intersect_segments_multiple_intersections(): """Tests that polygons having multiple intersections are ordered correctly.""" pts1 = (Point2D(0, 0), Point2D(5, 0), Point2D(5, 5), Point2D(0, 5)) pts2 = (Point2D(6, 4), Point2D(5, 4), Point2D(5, 3), Point2D(6, 3)) pts3 = (Point2D(5, 3), Point2D(6, 3), Point2D(6, 4), Point2D(5, 4)) pts4 = (Point2D(7, 4), Point2D(5, 4), Point2D(5, 3), Point2D(6, 3), Point2D(6, 2), Point2D(5, 2), Point2D(5, 1), Point2D(7, 1)) pts5 = (Point2D(5, 3), Point2D(6, 3), Point2D(6, 2), Point2D(5, 2), Point2D(5, 1), Point2D(7, 1), Point2D(7, 4), Point2D(5, 4)) poly1 = Polygon2D(pts1) poly2 = Polygon2D(pts2) poly3 = Polygon2D(pts3) poly4 = Polygon2D(pts4) poly5 = Polygon2D(pts5) int_polys1 = Polygon2D.intersect_segments(poly1, poly2, 0.01) int_polys2 = Polygon2D.intersect_segments(poly1, poly3, 0.01) int_polys3 = Polygon2D.intersect_segments(poly1, poly4, 0.01) int_polys4 = Polygon2D.intersect_segments(poly1, poly4, 0.01) assert int_polys1[0].vertices == int_polys2[0].vertices == \ (Point2D(0, 0), Point2D(5, 0), Point2D(5, 3), Point2D(5, 4), Point2D(5, 5), Point2D(0, 5)) assert int_polys3[0].vertices == int_polys4[0].vertices == \ (Point2D(0, 0), Point2D(5, 0), Point2D(5, 1), Point2D(5, 2), Point2D(5, 3), Point2D(5, 4), Point2D(5, 5), Point2D(0, 5))
def test_detailed_scale(): """Test the scale method.""" pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) new_detailed_window = detailed_window.scale(2) assert new_detailed_window.polygons[0].vertices == \ (Point2D(4, 2), Point2D(6, 2), Point2D(6, 4), Point2D(4, 4)) assert new_detailed_window.polygons[1].vertices == \ (Point2D(10, 1), Point2D(16, 1), Point2D(16, 5), Point2D(10, 5))
def test_detailed_flip(): """Test the flip method.""" pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) new_detailed_window = detailed_window.flip(10) assert new_detailed_window.polygons[0].vertices == \ tuple(reversed((Point2D(8, 1), Point2D(7, 1), Point2D(7, 2), Point2D(8, 2)))) assert new_detailed_window.polygons[1].vertices == \ tuple(reversed((Point2D(5, 0.5), Point2D(2, 0.5), Point2D(2, 2.5), Point2D(5, 2.5))))
def test_polygon_offset_outward(): """Test the offset method""" # Construct a simple rectangle poly = [[1, 1], [3, 1], [3, 5], [1, 5]] poly = Polygon2D.from_array(poly) # Make solution polygon (list of polygons) chk_off = Polygon2D.from_array([[0, 0], [4, 0], [4, 6], [0, 6]]) # Run method offset = polyskel.offset(poly, -1, [])
def test_clockwise(): """Test the clockwise property.""" pts_1 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon_1 = Polygon2D(pts_1) pts_2 = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) polygon_2 = Polygon2D(pts_2) assert not polygon_1.is_clockwise assert polygon_2.is_clockwise assert polygon_1.reverse().is_clockwise assert polygon_1.area == 4 assert polygon_2.area == 4
def test_polygon_offset_inward(): """Test the offset method""" # Construct a simple rectangle poly = [[0, 0], [4, 0], [4, 6], [0, 6]] poly = Polygon2D.from_array(poly) # Make solution polygon (list of polygons) chk_off = Polygon2D.from_array([[1, 1], [3, 1], [3, 5], [1, 5]]) # Run method offset = polyskel.offset(poly, 1, []) assert offset[0].is_equivalent(chk_off, 1e-2)
def test_equality(): """Test the equality of Polygon2D objects.""" pts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) pts_2 = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0.1, 2)) polygon = Polygon2D(pts) polygon_dup = polygon.duplicate() polygon_alt = Polygon2D(pts_2) assert polygon is polygon assert polygon is not polygon_dup assert polygon == polygon_dup assert hash(polygon) == hash(polygon_dup) assert polygon != polygon_alt assert hash(polygon) != hash(polygon_alt)
def test_detailed_equality(): """Test the equality of DetailedWindows.""" pts_1 = (Point2D(2, 1), Point2D(3, 1), Point2D(3, 2), Point2D(2, 2)) pts_2 = (Point2D(5, 0.5), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) pts_3 = (Point2D(5, 0.4), Point2D(8, 0.5), Point2D(8, 2.5), Point2D(5, 2.5)) detailed_window = DetailedWindows((Polygon2D(pts_1), Polygon2D(pts_2))) detailed_window_dup = detailed_window.duplicate() detailed_window_alt = DetailedWindows((Polygon2D(pts_1),)) assert detailed_window is detailed_window assert detailed_window is not detailed_window_dup assert detailed_window == detailed_window_dup assert hash(detailed_window) == hash(detailed_window_dup) assert detailed_window != detailed_window_alt assert hash(detailed_window) != hash(detailed_window_alt)
def chart_border2d(self): """Get a Polyline2D for the border of the plot.""" base_pt = Point2D(self._base_point.x, self._base_point.y) width = self._container.max_point.x - self._container.min_point.x height = self._container.max_point.y - self._container.min_point.y pgon = Polygon2D.from_rectangle(base_pt, Vector2D(0, 1), width, height) return Polyline2D.from_polygon(pgon)
def test_mesh2d_init_from_polygon_grid_concave(): """Test the initalization of Mesh2D from_polygon_grid.""" verts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1), Point2D(1, 2), Point2D(0, 2)) polygon = Polygon2D(verts) mesh = Mesh2D.from_polygon_grid(polygon, 0.5, 0.5, False) assert len(mesh.vertices) == 21 assert len(mesh.faces) == 12 assert mesh.area == 3 assert mesh.min.x == 0 assert mesh.min.y == 0 assert mesh.max.x == 2 assert mesh.max.y == 2 assert mesh.center.x == 1 assert mesh.center.y == 1 assert mesh.centroid.x == pytest.approx(0.83, rel=1e-2) assert mesh.centroid.y == pytest.approx(0.83, rel=1e-2) assert len(mesh.face_areas) == 12 assert mesh.face_areas[0] == 0.25 assert len(mesh.face_centroids) == 12 assert mesh._is_color_by_face is False assert mesh.colors is None
def test_reflect(): """Test the Polygon2D reflect method.""" pts = (Point2D(1, 1), Point2D(2, 1), Point2D(2, 2), Point2D(1, 2)) polygon = Polygon2D(pts) origin_1 = Point2D(1, 0) normal_1 = Vector2D(1, 0) normal_2 = Vector2D(-1, -1).normalize() test_1 = polygon.reflect(normal_1, origin_1) assert test_1[0].x == pytest.approx(1, rel=1e-3) assert test_1[0].y == pytest.approx(1, rel=1e-3) assert test_1[2].x == pytest.approx(0, rel=1e-3) assert test_1[2].y == pytest.approx(2, rel=1e-3) assert polygon.area == pytest.approx(test_1.area, rel=1e-3) assert polygon.perimeter == pytest.approx(test_1.perimeter, rel=1e-3) assert polygon.is_clockwise is not test_1.is_clockwise assert polygon.is_convex is test_1.is_convex assert polygon.is_self_intersecting is test_1.is_self_intersecting test_1 = polygon.reflect(normal_2, Point2D(0, 0)) assert test_1[0].x == pytest.approx(-1, rel=1e-3) assert test_1[0].y == pytest.approx(-1, rel=1e-3) assert test_1[2].x == pytest.approx(-2, rel=1e-3) assert test_1[2].y == pytest.approx(-2, rel=1e-3) test_2 = polygon.reflect(normal_2, origin_1) assert test_2[0].x == pytest.approx(0, rel=1e-3) assert test_2[0].y == pytest.approx(0, rel=1e-3) assert test_2[2].x == pytest.approx(-1, rel=1e-3) assert test_2[2].y == pytest.approx(-1, rel=1e-3)
def chart_border(self): """Get a Polyline2D for the border of the plot.""" width = self._x_dim * len(self._months_int) height = self._y_dim pgon = Polygon2D.from_rectangle(self._base_point, Vector2D(0, 1), width, height) return Polyline2D.from_polygon(pgon)
def test_polygon2d_init(): """Test the initialization of Polygon2D objects and basic properties.""" pts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2)) polygon = Polygon2D(pts) str(polygon) # test the string representation of the polygon assert isinstance(polygon.vertices, tuple) assert len(polygon.vertices) == 4 assert len(polygon) == 4 for point in polygon: assert isinstance(point, Point2D) assert isinstance(polygon.segments, tuple) assert len(polygon.segments) == 4 for seg in polygon.segments: assert isinstance(seg, LineSegment2D) assert seg.length == 2 assert polygon.area == 4 assert polygon.perimeter == 8 assert not polygon.is_clockwise assert polygon.is_convex assert not polygon.is_self_intersecting assert polygon.vertices[0] == polygon[0] p_array = polygon.to_array() assert isinstance(p_array, tuple) assert len(p_array) == 4 for arr in p_array: assert isinstance(p_array, tuple) assert len(arr) == 2