def Valtr(n): # create random components for x and y x = [random() for i in range(0, n)] y = [random() for i in range(0, n)] # sort x and y components x_vec = rand_coord_sort(x) y_vec = rand_coord_sort(x) # randomly combine x and y to create vectors shuffle(x_vec) shuffle(y_vec) vectors = [[x_vec[i], y_vec[i], 0] for i in range(n)] # sort vectors according to ascending angle atan_vec = [atan2(y_vec[i], x_vec[i]) for i in range(n)] id_order = argsort(atan_vec) vectors_sort = [[x_vec[i], y_vec[i], 0] for i in id_order] point_coord = [] point_coord.append([0, 0, 0]) # create polygon from vector addition (according to Valtr's proof, the polygon should close itself) for i in range(1, n): new_point = add(point_coord[i - 1], vectors_sort[i - 1]) point_coord.append([new_point[0], new_point[1], 0]) # define Polygon polygon = Polygon(point_coord) # check if polygon is really convex if polygon.is_convex() == False: print('This polygon is NOT convex!') return polygon
def test_data(): p = Polygon([ Point(random.random(), random.random(), random.random()) for i in range(10) ]) assert p.data == p.validate_data() o = Polygon.from_data(p.data) assert p == o assert not (p is o) assert o.data == o.validate_data()
def test___getitem__(): points = [[0, 0, x] for x in range(5)] polygon = Polygon(points) for x in range(5): assert polygon[x] == [0, 0, x] with pytest.raises(IndexError): polygon[6] = [0, 0, 6]
def plot(self): """Visualize the current map with the plotter. Returns ------- None """ from compas_plotters.plotter import Plotter from compas.geometry import Pointcloud from compas.geometry import Plane, Circle, Polygon plotter = Plotter(figsize=(16, 12)) w = 16 h = 10 n = len(self.colors) d = w / n cloud = Pointcloud.from_bounds(w, h, 0, n) white = Color.white() for i, color in enumerate(self.colors): c = Circle(Plane(cloud[i], [0, 0, 1]), 0.1) p = Polygon([[i * d, -2, 0], [(i + 1) * d, -2, 0], [(i + 1) * d, -1, 0], [i * d, -1, 0]]) plotter.add(c, facecolor=color, edgecolor=white, linewidth=0.5) plotter.add(p, facecolor=color, edgecolor=color) plotter.zoom_extents() plotter.show()
def test_equality(): points1 = [[0, 0, x] for x in range(5)] polygon1 = Polygon(points1) points2 = [[0, 0, x] for x in range(6)] polygon2 = Polygon(points2) points3 = [[0, 0, x] for x in range(5)] + [[0, 0, 0]] polygon3 = Polygon(points3) assert polygon1 == polygon1 assert polygon1 == points1 assert points1 == polygon1 assert polygon1 != polygon2 assert polygon2 != polygon1 assert polygon1 != points2 assert points2 != polygon1 assert polygon1 != 1 assert polygon1 == polygon3
def convex_polygon_area_compas(polygon_vertices): """Compute the area of a convex polygon using compas. Parameters ---------- polygon : sequence The XY coordinates of the vertices/corners of the polygon. The vertices are assumed to be in order. The polygon is assumed to be closed: the first and last vertex in the sequence should not be the same. Returns ------- float The area of the polygon. """ polygon = Polygon(polygon_vertices) if not polygon.is_convex: sys.exit("the polygon is not convex.") vectors = [] centroid = polygon.centroid area = 0.0 for p in polygon.points: vectors.append(Vector.from_start_end(centroid, p)) for i in range(len(vectors)): area += cross_vectors(vectors[i - 1], vectors[i])[2] / 2 return area
def surface_calc(upper_board, lower_board, intersection): if upper_board.length_vector != lower_board.length_vector: len_intersection = lower_board.width wid_intersection = upper_board.width else: # for now we assume that they are parallel in this case, potential error source for later, though len_intersection = min(upper_board.length, lower_board.length) wid_intersection = min(upper_board.width, lower_board.width) dim1 = scale_vector(upper_board.length_vector, len_intersection * .5) dim2 = scale_vector(upper_board.width_vector, wid_intersection * .5) # this procedure is necessary only because of the glue path planning to make sure points are always ordered clockwise ang = angle_vectors_signed(dim1, dim2, Vector(0, 0, 1)) if ang > 0: pt1 = intersection + dim1 - dim2 pt2 = intersection + dim1 + dim2 pt3 = intersection - dim1 + dim2 pt4 = intersection - dim1 - dim2 else: pt1 = intersection - dim1 + dim2 pt2 = intersection + dim1 + dim2 pt3 = intersection + dim1 - dim2 pt4 = intersection - dim1 - dim2 intersection_surf = Polygon([pt1, pt2, pt3, pt4]) return intersection_surf
def test___setitem__(): points = [[0, 0, x] for x in range(5)] polygon = Polygon(points) point = [1, 1, 4] polygon[4] = point assert polygon[4] == point assert isinstance(polygon[4], Point) assert polygon.lines[-2].end == point
def add_vertex_edge_for_load_support(network, sup_dic, load_dic, bars_len, key_removed_dic): """ Post-Processing Function: Adds vertices and edges in accordance with supports and loads returns the cured network """ if not key_removed_dic: load_sup_dic=merge_two_dicts(sup_dic, load_dic) else: load_dic_2=load_dic.copy() for key in key_removed_dic: load_dic_2.pop(key) load_dic_2=merge_two_dicts(load_dic_2, key_removed_dic[key]) load_sup_dic=merge_two_dicts(sup_dic, load_dic_2) # define arbitrary r to be added to get leaf vertex coordinates max_len=max(bars_len) r=max_len/3.0 # make a polygon and polyline from outer vertices of network points = network.to_points() cycles = network_find_cycles(network) mesh = Mesh.from_vertices_and_faces(points, cycles) if 0 in mesh.face and len(mesh.face)>1: mesh.delete_face(0) if len(mesh.face)==1: ver_lis=[key for key in mesh.vertices()] else: ver_lis=mesh.vertices_on_boundary(ordered=True) ver_lis_plyln=ver_lis[:] ver_lis_plyln.append(ver_lis[0]) pt_lis_plygn=[mesh.vertex_coordinates(key) for key in ver_lis] pt_lis_plyln=[mesh.vertex_coordinates(key) for key in ver_lis_plyln] plygn=Polygon(pt_lis_plygn) plyln=Polyline(pt_lis_plyln) # add leaf vertices for key in load_sup_dic: if load_sup_dic[key][0]!=0.0: pt_1=add_vectors(network.node_coordinates(key), (+r, 0.0, 0.0)) plyln_bln=is_point_on_polyline(pt_1, plyln.points, tol=0.001) plygn_bln=is_point_in_polygon_xy(pt_1, plygn.points) if plyln_bln or plygn_bln: pt_1=add_vectors(network.node_coordinates(key), (-r, 0.0, 0.0)) key_2=network.add_node(x=np.asscalar(pt_1[0]), y=pt_1[1], z=0.0) network.add_edge(key, key_2) if load_sup_dic[key][1]!=0.0: pt_2=add_vectors(network.node_coordinates(key), (0.0,+r, 0.0)) plyln_bln=is_point_on_polyline(pt_2, plyln.points, tol=0.001) plygn_bln=is_point_in_polygon_xy(pt_2, plygn.points) if plyln_bln or plygn_bln: pt_2=add_vectors(network.node_coordinates(key), (0.0,-r, 0.0)) key_2=network.add_node(x=pt_2[0], y=np.asscalar(pt_2[1]), z=0.0) network.add_edge(key, key_2) return network, plygn, plyln
def polygon_to_compas(polygon): """Convert a Rhino polygon to a COMPAS polygon. Parameters ---------- polygon : :class:`Rhino.Geometry.Polygon` Returns ------- :class:`compas.geometry.Polygon` """ return Polygon([point_to_compas(point) for point in polygon])
def get_convex_polygon_area(P): p = Polygon(P) pt_base = p.points[0] pts = p.points pts.pop(0) vectors = [pt_base - pt for pt in pts] #print(vectors) partial_areas = [ vectors[i].cross(vectors[i + 1]).length * 0.5 for i in range(0, len(vectors) - 1) ] #print(partial_areas) return sum(partial_areas)
def hexagongrid(): polygon = Polygon.from_sides_and_radius_xy(6, 1) vertices = polygon.points vertices.append(polygon.centroid) x, y, z = zip(*vertices) xmin = min(x) xmax = max(x) ymin = min(y) ymax = max(y) faces = [[0, 1, 6], [1, 2, 6], [2, 3, 6], [3, 4, 6], [4, 5, 6], [5, 0, 6]] mesh = Mesh.from_vertices_and_faces(vertices, faces) meshes = [] for i in range(2): T = Translation.from_vector([i * (xmax - xmin), 0, 0]) meshes.append(mesh.transformed(T)) for i in range(2): T = Translation.from_vector([i * (xmax - xmin), ymax - ymin, 0]) meshes.append(mesh.transformed(T)) mesh = meshes_join_and_weld(meshes) return mesh
blocks = [] for (a, b), (a1, b1), (a2, b2) in zip(pairwise(points[1:-1]), pairwise(points1), pairwise(points2)): p = (a + b) * 0.5 t = (b - a).unitized() n = Vector(0, 0, 1).cross(t) frame = Frame(p, t, n) frames.append(frame) l1 = (b1 - a1).length l2 = (b2 - a2).length block = Box(frame, min(l1, l2) - 0.03, 0.3, 0.1) blocks.append(Polygon(block.vertices[:4][::-1])) # ============================================================================== # Visualization # ============================================================================== plotter = GeometryPlotter(figsize=(16, 9)) plotter.add(controlpoly, linestyle='dotted', linewidth=0.5, color=(0.5, 0.5, 0.5)) for point in controlpoints: plotter.add(point, edgecolor=(1.0, 0.0, 0.0)) plotter.add(poly, color=(0.7, 0.7, 0.7), linewidth=0.5)
def test___repr__(): points = [[0, 0, x] for x in range(5)] polygon = Polygon(points) assert polygon == eval(repr(polygon))
from compas.geometry import Polygon from compas.geometry import Polyline from compas.geometry import Vector # Point assert [0, 5, 1] == Point(0, 5, 1) # Vector assert [0, 0, 1] == Vector(0, 0, 1) # Plane point = [0, 0, 0] vector = [1, 0, 0] assert (point, vector) == Plane(point, vector) # Frame point = [5, 0, 0] xaxis = [1, 0, 0] yaxis = [0, 1, 0] assert (point, xaxis, yaxis) == Frame(point, xaxis, yaxis) # Polyline p1 = [0, 0, 0] p2 = [1, 0, 0] p3 = [1, 1, 0] p4 = [0, 0, 0] assert [p1, p2, p3, p4] == Polyline([p1, p2, p3, p4]) # Polygon assert [p1, p2, p3] == Polygon([p1, p2, p3])
import random import math from compas.geometry import Pointcloud, Polygon from compas.geometry import Translation, Rotation from compas_plotters import GeometryPlotter pcl = Pointcloud.from_bounds(10, 5, 0, 10 * 4) base = Polygon.from_sides_and_radius_xy(5, 0.3) plotter = GeometryPlotter(show_axes=True) for point in pcl.points: plotter.add(point) plotter.zoom_extents() plotter.show()
from compas_plotters import GeometryPlotter # ============================================================================== # Parameters # ============================================================================== N = 50 W = 100 H = 50 # ============================================================================== # Objects # ============================================================================== cloud = Pointcloud.from_bounds(W, H, 0, N) polygon = Polygon.from_sides_and_radius_xy(5, 20.0) polygon.transform(Translation.from_vector([0.5 * W, 0.5 * H, 0])) box = Polygon([[0, 0], [W, 0], [W, H], [0, H]]) # ============================================================================== # Transformations # ============================================================================== # random translation vector per point in the cloud transformations = [ Translation.from_vector([ choice([-1, +1]) * random(), choice([-1, +1]) * random(), 0]) for _ in cloud]
from compas.geometry import Vector from compas.geometry import Polygon a = [1, 0, 0] b = [0, 1, 0] c = [-1, 0, 0] polygon = Polygon([a, b, c]) def get_area(polygon): center = polygon.center Atot = 0 points = polygon.points points.append(points[0]) for i in range(len(points) - 1): u = Vector.from_start_end(points[i], points[i + 1]) v = Vector.from_start_end(points[i], center) uxv = u.cross(v) Atot += uxv.length / 2 return Atot print(get_area(polygon))
# ============================================================================== # Main # ============================================================================== if __name__ == '__main__': from random import uniform from compas.geometry import Box from compas.geometry import Polygon from compas_plotters import GeometryPlotter n = 100 box = Box.from_width_height_depth(10, 3, 5) x, y, _ = zip(*box.points) xmin, xmax = min(x), max(x) ymin, ymax = min(y), max(y) x = [uniform(xmin, xmax) for i in range(n)] y = [uniform(ymin, ymax) for i in range(n)] z = [0] * n points = list(zip(x, y, z)) plotter = GeometryPlotter(show_axes=False) polygon = Polygon(points) plotter.add(polygon) plotter.zoom_extents() plotter.show()
def triangle(): return Polygon([[0, 0, 0], [1, 0, 0], [0, 1, 0]])
def hexagon(): polygon = Polygon.from_sides_and_radius_xy(6, 1) vertices = polygon.points vertices.append(polygon.centroid) faces = [[0, 1, 6], [1, 2, 6], [2, 3, 6], [3, 4, 6], [4, 5, 6], [5, 0, 6]] return Mesh.from_vertices_and_faces(vertices, faces)
left = block.attributes['sides']['left'] right = block.attributes['sides']['right'] left_poly = block.attributes['cut1']['left'] right_poly = block.attributes['cut1']['right'] # ============================================================================== # Visualization # ============================================================================== compas_rhino.clear() # cutter points = [[0, 0, 0], [0, 0, HEIGHT], [0, TABLE, HEIGHT], [0, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Left", color=(255, 0, 0)) artist.draw(show_edges=True, show_face=False) points = [[WIRE, 0, 0], [WIRE, 0, HEIGHT], [WIRE, TABLE, HEIGHT], [WIRE, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Right", color=(0, 255, 0)) artist.draw(show_edges=True, show_face=False) # blank and block
def biohazard(): polygon = Polygon.from_sides_and_radius_xy(6, 1) vertices = polygon.points vertices.append(polygon.centroid) faces = [[0, 1, 6], [2, 3, 6], [4, 5, 6]] return Mesh.from_vertices_and_faces(vertices, faces)
pts = polygon.points[:] + [polygon.points[0]] # calculate all triangle areas using polygon centroid areas = [area_from_3_pts(a, b, polygon.centroid) for a, b in pairwise(pts)] return sum(areas) def area_from_3_pts(a, b, c): """ Compute the area from three points Args: a: compas.geometry.Point, pt1 b: compas.geometry.Point, pt2 c: compas.geometry.Point, pt3 Returns: float: are of three points """ return 0.5 * (b - a).cross(c - a).length if __name__ == '__main__': from compas.geometry import Polygon polygon = Polygon([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [-0.5, 0.5, 0]]) area = convex_polygon_area(polygon) print("Polygon area is: ", area, "\nIs my result same as compas result: ", area == polygon.area)
def test_polygon(): points = [[0, 0, x] for x in range(5)] polygon = Polygon(points) assert polygon.points == points assert polygon.lines == [(a, b) for a, b in pairwise(points + points[:1])]
right_blank.append(right_x) # ============================================================================== # Visualization # ============================================================================== compas_rhino.clear() artist = MeshArtist(block, layer="ITA20::HotWire::Block") artist.draw_faces(color={left: (255, 0, 0), right: (0, 255, 0)}) artist = BoxArtist(blank, layer="ITA20::HotWire::Blank") artist.draw(show_edges=True, show_faces=False) points = [[0, 0, 0], [0, 0, HEIGHT], [0, TABLE, HEIGHT], [0, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Left", color=(255, 0, 0)) artist.draw(show_edges=True, show_face=False) points = [[WIRE, 0, 0], [WIRE, 0, HEIGHT], [WIRE, TABLE, HEIGHT], [WIRE, TABLE, 0]] polygon = Polygon(points) artist = PolygonArtist(polygon, layer="ITA20::HotWire::Right", color=(0, 255, 0)) artist.draw(show_edges=True, show_face=False) artist = PolylineArtist(left_poly, color=(255, 0, 0), layer="ITA20::HotWire::LeftCut") artist.draw() artist = PolylineArtist(right_poly, color=(0, 255, 0), layer="ITA20::HotWire::RightCut") artist.draw() compas_rhino.rs.Redraw()
if __name__ == '__main__': from compas.geometry import Point from compas.geometry import Vector from compas.geometry import Plane from compas.geometry import Line from compas.geometry import Polygon from compas.geometry import projection_matrix point = Point(0.0, 0.0, 0.0) normal = Vector(0.0, 0.0, 1.0) plane = Plane.from_point_and_normal(point, normal) line = Line([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]) triangle = Polygon([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]]) polygon = Polygon([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0]]) p = Point(1.0, 1.0, 1.0) print(repr(p)) print(p.distance_to_point(point)) print(p.distance_to_line(line)) print(p.distance_to_plane(plane)) print(p.in_triangle(triangle)) # print(p.in_polygon(polygon)) # print(p.in_polyhedron())
from compas.geometry import Pointcloud, Polygon from compas.geometry import Translation from compas_plotters import GeometryPlotter pcl = Pointcloud.from_bounds(10, 5, 0, 100) polygon = Polygon.from_sides_and_radius_xy(5, 2.0) polygon.transform(Translation.from_vector([5, 2.5, 0])) plotter = GeometryPlotter(show_axes=True) plotter.add(polygon, edgecolor=(0, 0, 1), facecolor=(0.7, 0.7, 1.0)) for point in pcl.points: facecolor = (1, 1, 1) plotter.add(point, facecolor=facecolor) plotter.zoom_extents() plotter.show()
Parameters polygon (compas.geometry.polygon) - 2D polygon Returns float - area of the polygon """ if not polygon.is_convex(): raise ValueError("Polygon is not convex") c = polygon.centroid area = 0 vertices = list(polygon) # area of the polygon is the sum of all triangles form by two consecutive vertices and centroid for i in range(len(vertices)): u = polygon[i - 1] v = polygon[i] area = area + (c - u).cross(c - v).length / 2 return area if __name__ == '__main__': from compas.geometry import Polygon polygon = Polygon([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0]]) print(area_polygon(polygon))
def square(): return Polygon.from_sides_and_radius_xy(4, sqrt(0.5**2 + 0.5**2))