def geometry(self): # TODO: this is a temp solution # TODO: add memoization or some other kind of caching A = Mesh.from_shape(self.shape) for shape, operation in self.features: A.quads_to_triangles() B = Mesh.from_shape(shape) B.quads_to_triangles() A = Part.operations[operation](A.to_vertices_and_faces(), B.to_vertices_and_faces()) geometry = Shape(*A) T = Transformation.from_frame_to_frame(Frame.worldXY(), self.frame) geometry.transform(T) return geometry
def __and__(self, other): """Compute the boolean intersection using the "&" operator of this shape and another. Parameters ---------- other : :class:`compas.geometry.Shape` The solid to intersect with. Returns ------- :class:`compas.geometry.Polyhedron` The resulting solid. Examples -------- >>> from compas.geometry import Box, Sphere >>> A = Box.from_width_height_depth(2, 2, 2) >>> B = Sphere([1, 1, 1], 1.0) >>> C = A & B # doctest: +SKIP """ from compas.geometry import boolean_intersection_mesh_mesh from compas.geometry import Polyhedron A = self.to_vertices_and_faces(triangulated=True) B = other.to_vertices_and_faces(triangulated=True) V, F = boolean_intersection_mesh_mesh(A, B) return Polyhedron(V, F)
def __sub__(self, other): """Compute the boolean difference using the "-" operator of this shape and another. Parameters ---------- other : :class:`Solid` The solid to subtract. Returns ------- :class:`Solid` The resulting solid. Examples -------- >>> from compas.geometry import Box, Sphere >>> A = Box.from_width_height_depth(2, 2, 2) >>> B = Sphere([1, 1, 1], 1.0) >>> C = A - B """ from compas.geometry import boolean_difference_mesh_mesh from compas.geometry import Polyhedron A = self.to_vertices_and_faces(triangulated=True) B = other.to_vertices_and_faces(triangulated=True) V, F = boolean_difference_mesh_mesh(A, B) return Polyhedron(V, F)
def data(self, data): self.attributes.update(data['attributes'] or {}) self.key = data['key'] self.frame.data = data['frame'] self.shape.data = data['shape'] self.features = [(Shape.from_data(shape), operation) for shape, operation in data['features']] self.transformations = deque([Transformation.from_data(T) for T in data['transformations']])
def from_polyhedron(cls, f): """Construct a mesh from a platonic solid. Parameters ---------- f : {4, 6, 8, 12, 20} The number of faces. Returns ------- :class:`compas.datastructures.Mesh` A mesh object. """ p = Polyhedron.from_platonicsolid(f) return cls.from_vertices_and_faces(p.vertices, p.faces)
def from_polyhedron(cls, f): """Construct a mesh from a platonic solid. Parameters ---------- f : int The number of faces. Should be one of ``4, 6, 8, 12, 20``. Returns ------- Mesh A mesh object. Examples -------- >>> """ p = Polyhedron(f) return cls.from_vertices_and_faces(p.vertices, p.faces)
def mesh_to_tets(self) -> List[Polyhedron]: """Convert the model mesh to a COMPAS mesh data structure.""" nodes = self.mesh.get_nodes() node_tags = nodes[0] node_coords = nodes[1].reshape((-1, 3), order='C') xyz = {} for tag, coords in zip(node_tags, node_coords): xyz[int(tag)] = coords elements = self.mesh.get_elements() tets = [] for etype, etags, ntags in zip(*elements): if etype == 4: # tetrahedron for i, etag in enumerate(etags): n = self.mesh.get_element_properties(etype)[3] vertices = [xyz[index] for index in ntags[i * n: i * n + n]] faces = [ [0, 1, 2], [0, 2, 3], [1, 3, 2], [0, 3, 1]] tets.append(Polyhedron(vertices, faces)) return tets
return [x, y, z] # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from compas.plotters import Plotter from compas.geometry import intersection_line_line from compas.geometry import midpoint_point_point from compas.geometry import centroid_points from compas.geometry import Polyhedron polyhedron = Polyhedron.generate(6) print(centroid_polyhedron(polyhedron)) vertices = [[1.0, 1.0, 2.0], [0.0, 0.0, 0.0], [1.0, 0.0, 2.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [0.0, 0.0, 1.0]] faces = [[4, 6, 7, 1], [5, 0, 6, 4], [4, 1, 3, 5], [3, 2, 0, 5], [1, 7, 2, 3], [6, 0, 2, 7]] faces[:] = [face[::-1] for face in faces] polyhedron = Polyhedron.from_vertices_and_faces(vertices, faces) print(centroid_polyhedron(polyhedron))
points = [Point3d(*self.vertices[key]) for key in face] if self.color: e.Display.DrawPolygon(points, self.color[i], True) else: e.Display.DrawPolygon(points, self._default_color, True) # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from random import shuffle from compas.geometry import Polyhedron polyhedron = Polyhedron.generate(6) faces = polyhedron.faces vertices = polyhedron.vertices colors = [(255, 255, 255), (255, 0, 0), (255, 255, 0), (0, 255, 0), (0, 255, 255), (0, 0, 255)] conduit = FacesConduit(vertices, faces, color=colors) with conduit.enabled(): for i in range(10): shuffle(colors) conduit.color = colors conduit.redraw(pause=1.0)
self.clear_faces() self.clear_edges() # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from compas.datastructures import Mesh from compas.geometry import Polyhedron from compas_rhino.helpers.artists.meshartist import MeshArtist poly = Polyhedron.generate(12) mesh = Mesh.from_vertices_and_faces(poly.vertices, poly.faces) artist = MeshArtist(mesh, layer='MeshArtist') artist.clear_layer() artist.draw_vertices() artist.redraw(0.0) artist.draw_vertexlabels() artist.redraw(1.0) artist.draw_faces() artist.redraw(1.0)
@pytest.mark.parametrize(("points"), [ [[0.0, 0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0]], ] ) def test_centroid_points_fails_when_input_is_not_complete_points(points): with pytest.raises(ValueError): centroid_points(points) @pytest.mark.parametrize(("polyhedron", "centroid"), [ (Polyhedron.generate(6), [0.0, 0.0, 0.0]), ] ) def test_centroid_polyhedron(polyhedron, centroid): x, y, z = centroid assert centroid_polyhedron(polyhedron) == [pytest.approx(x, 0.001), pytest.approx(y, 0.001), pytest.approx(z, 0.001)] # ============================================================================== # size # ============================================================================== @pytest.mark.parametrize(("polyhedron", "volume"), [ (Polyhedron.generate(6), None)
ab = subtract_vectors(b, a) ac = subtract_vectors(c, a) n = cross_vectors(ab, ac) V += dot_vectors(a, n) return V / 6. # ============================================================================== # Main # ============================================================================== if __name__ == "__main__": from compas.geometry import Polyhedron cube = Polyhedron.generate(6) L = length_vector(subtract_vectors(cube.vertices[0], cube.vertices[1])) V1 = L * L * L V2 = volume_polyhedron(cube) print(V1 - V2 <= 1e-6) # plotter = Plotter(figsize=(10, 7)) # polygon = [ # [0, 0, 0], # [1.0, 0, 0], # [1.0, 1.0, 0], # [0.5, 0.0, 0],
def test_centroid_points_fails_when_input_is_not_list_of_lists(points): with pytest.raises(TypeError): centroid_points(points) @pytest.mark.parametrize(("points"), [ [[0.0, 0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0]], ]) def test_centroid_points_fails_when_input_is_not_complete_points(points): with pytest.raises(ValueError): centroid_points(points) @pytest.mark.parametrize(("polyhedron", "centroid"), [ (Polyhedron.from_platonicsolid(6), [0.0, 0.0, 0.0]), ]) def test_centroid_polyhedron(polyhedron, centroid): x, y, z = centroid assert allclose(centroid_polyhedron(polyhedron), (x, y, z)) # ============================================================================== # size # ============================================================================== @pytest.mark.parametrize(("polyhedron", "volume"), [(Polyhedron.from_platonicsolid(6), None)]) def test_volume_polyhedron(polyhedron, volume): if volume is None:
import random from compas.geometry import Plane from compas.geometry import Circle from compas.geometry import Cone from compas.geometry import Polyhedron from compas_viewers.objectviewer import Arrow from compas_viewers.objectviewer import ObjectViewer viewer = ObjectViewer() plane = Plane([2, 0, 0], [0, 0, 1]) circle = Circle(plane, 0.5) cone = Cone(circle, 1) viewer.add(cone) polyhedron = Polyhedron(4) viewer.add(polyhedron) arrow = Arrow([-2, 0, 0], [0, 1, 1]) viewer.add(arrow) viewer.show()
def test_centroid_points_fails_when_input_is_not_list_of_lists(points): with pytest.raises(TypeError): centroid_points(points) @pytest.mark.parametrize(("points"), [ [[0.0, 0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0]], ]) def test_centroid_points_fails_when_input_is_not_complete_points(points): with pytest.raises(ValueError): centroid_points(points) @pytest.mark.parametrize(("polyhedron", "centroid"), [ (Polyhedron(6), [0.0, 0.0, 0.0]), ]) def test_centroid_polyhedron(polyhedron, centroid): x, y, z = centroid assert allclose(centroid_polyhedron(polyhedron), (x, y, z)) # ============================================================================== # size # ============================================================================== @pytest.mark.parametrize(("polyhedron", "volume"), [(Polyhedron(6), None)]) def test_volume_polyhedron(polyhedron, volume): if volume is None: L = length_vector(