|
4 | 4 |
|
5 | 5 | from math import sqrt |
6 | 6 | from compas.geometry import transform_points |
| 7 | +from compas.geometry import centroid_polygon |
7 | 8 | from compas.utilities import pairwise |
8 | 9 |
|
9 | | -from compas.geometry.shapes._shape import Shape |
| 10 | +from ._shape import Shape |
10 | 11 |
|
11 | 12 |
|
12 | 13 | class Polyhedron(Shape): |
@@ -95,7 +96,7 @@ def data(self, data): |
95 | 96 | # ========================================================================== |
96 | 97 |
|
97 | 98 | def __repr__(self): |
98 | | - return 'Polyhedron({0!r}, {1!r})'.format(self.vertices, self.faces) |
| 99 | + return '<Polyhedron with {} vertices and {} faces>'.format(len(self.vertices), len(self.faces)) |
99 | 100 |
|
100 | 101 | def __len__(self): |
101 | 102 | return 2 |
@@ -164,16 +165,19 @@ def from_platonicsolid(cls, f): |
164 | 165 |
|
165 | 166 | """ |
166 | 167 | if f == 4: |
167 | | - return cls(* tetrahedron()) |
168 | | - if f == 6: |
169 | | - return cls(* hexahedron()) |
170 | | - if f == 8: |
171 | | - return cls(* octahedron()) |
172 | | - if f == 12: |
173 | | - return cls(* dodecahedron()) |
174 | | - if f == 20: |
175 | | - return cls(* icosahedron()) |
176 | | - raise ValueError("The number of sides of a platonic solid must be one of: 4, 6, 8, 12, 20.") |
| 168 | + vertices, faces = tetrahedron() |
| 169 | + elif f == 6: |
| 170 | + vertices, faces = hexahedron() |
| 171 | + elif f == 8: |
| 172 | + vertices, faces = octahedron() |
| 173 | + elif f == 12: |
| 174 | + vertices, faces = dodecahedron() |
| 175 | + elif f == 20: |
| 176 | + vertices, faces = icosahedron() |
| 177 | + else: |
| 178 | + raise ValueError("The number of sides of a platonic solid must be one of: 4, 6, 8, 12, 20.") |
| 179 | + solid = cls(vertices, faces) |
| 180 | + return solid |
177 | 181 |
|
178 | 182 | @classmethod |
179 | 183 | def from_halfspaces(cls, halfspaces, interior_point): |
@@ -263,16 +267,49 @@ def from_planes(cls, planes): |
263 | 267 | # methods |
264 | 268 | # ========================================================================== |
265 | 269 |
|
266 | | - def to_vertices_and_faces(self): |
| 270 | + def to_vertices_and_faces(self, triangulated=False): |
267 | 271 | """Returns a list of vertices and faces. |
268 | 272 |
|
| 273 | + Parameters |
| 274 | + ---------- |
| 275 | + triangulated: bool, optional |
| 276 | + Flag indicating that the faces have to be triangulated. |
| 277 | +
|
269 | 278 | Returns |
270 | 279 | ------- |
271 | 280 | (vertices, faces) |
272 | 281 | A list of vertex locations and a list of faces, |
273 | 282 | with each face defined as a list of indices into the list of vertices. |
274 | 283 | """ |
275 | | - return self.vertices, self.faces |
| 284 | + if triangulated: |
| 285 | + vertices = self.vertices[:] |
| 286 | + faces = [] |
| 287 | + for face in self.faces: |
| 288 | + if len(face) > 3: |
| 289 | + centroid = centroid_polygon([vertices[index] for index in face]) |
| 290 | + index = len(vertices) |
| 291 | + vertices.append(centroid) |
| 292 | + for a, b in pairwise(face): |
| 293 | + faces.append([a, b, index]) |
| 294 | + else: |
| 295 | + faces.append(face) |
| 296 | + else: |
| 297 | + vertices = self.vertices |
| 298 | + faces = self.faces |
| 299 | + return vertices, faces |
| 300 | + |
| 301 | + def is_closed(self): |
| 302 | + """Verify that the polyhedron forms a closed surface. |
| 303 | +
|
| 304 | + Returns |
| 305 | + ------- |
| 306 | + bool |
| 307 | + True if the polyhedron is closed. |
| 308 | + False otherwise. |
| 309 | + """ |
| 310 | + from compas.datastructures import Mesh |
| 311 | + mesh = Mesh.from_vertices_and_faces(self.vertices, self.faces) |
| 312 | + return mesh.is_closed() |
276 | 313 |
|
277 | 314 | def transform(self, transformation): |
278 | 315 | """Transform the polyhedron. |
|
0 commit comments