Skip to content

Commit 7de8f70

Browse files
REFACTOR plate
1 parent 4cd1871 commit 7de8f70

File tree

1 file changed

+67
-86
lines changed

1 file changed

+67
-86
lines changed

src/compas_model/elements/plate.py

Lines changed: 67 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,136 @@
1-
import compas.datastructures # noqa: F401
1+
import numpy as np
22
from compas.datastructures import Mesh
33
from compas.geometry import Box
4+
from compas.geometry import Frame
5+
from compas.geometry import Point
6+
from compas.geometry import Polygon
7+
from compas.geometry import Vector
48
from compas.geometry import bounding_box
59
from compas.geometry import oriented_bounding_box
610
from compas.itertools import pairwise
11+
from numpy.typing import NDArray
712

813
from compas_model.elements import Element
9-
from compas_model.elements import Feature
10-
11-
12-
class PlateFeature(Feature):
13-
pass
1414

1515

1616
class PlateElement(Element):
17-
"""Class representing block elements.
17+
"""Class representing a block element.
1818
1919
Parameters
2020
----------
21-
shape : :class:`compas.datastructures.Mesh`
22-
The base shape of the block.
23-
features : list[:class:`PlateFeature`], optional
24-
Additional block features.
25-
is_support : bool, optional
26-
Flag indicating that the block is a support.
21+
polygon : :class:`compas.geometry.Polygon`
22+
The base polygon of the plate.
23+
thickness : float
24+
The total offset thickness above and blow the polygon
2725
frame : :class:`compas.geometry.Frame`, optional
2826
The coordinate frame of the block.
2927
name : str, optional
3028
The name of the element.
29+
shape : :class:`compas.datastructures.Mesh`, optional
30+
The base shape of the element.
3131
3232
Attributes
3333
----------
3434
shape : :class:`compas.datastructure.Mesh`
3535
The base shape of the block.
36-
features : list[:class:`PlateFeature`]
37-
A list of additional block features.
3836
is_support : bool
3937
Flag indicating that the block is a support.
4038
4139
"""
4240

4341
@property
44-
def __data__(self):
45-
# type: () -> dict
46-
data = super(PlateElement, self).__data__
47-
data["bottom"] = self._bottom
48-
data["top"] = self._top
49-
data["features"] = self.features
42+
def __data__(self) -> dict[str, any]:
43+
data: dict[str, any] = super(PlateElement, self).__data__
44+
data["polygon"] = self.polygon
45+
data["thickness"] = self.thickness
46+
data["frame"] = self.frame
47+
data["name"] = self.name
48+
data["shape"] = self.shape
5049
return data
5150

52-
def __init__(self, bottom, top, features=None, frame=None, name=None):
53-
# type: (compas.geometry.Polygon, compas.geometry.Polygon, list[PlateFeature] | None, compas.geometry.Frame | None, str | None) -> None
51+
@classmethod
52+
def __from_data__(cls, data: dict[str, any]) -> "PlateElement":
53+
return cls(polygon=data["polygon"], thickness=data["thickness"], frame=data["frame"], name=data["name"], shape=data["shape"])
5454

55+
def __init__(self, polygon: Polygon, thickness: float, frame: Frame = None, name: str = None, shape=None) -> "PlateElement":
5556
super(PlateElement, self).__init__(frame=frame, name=name)
56-
self._bottom = bottom
57-
self._top = top
58-
self.shape = self.compute_shape()
59-
self.features = features or [] # type: list[PlateFeature]
57+
self.polygon: Polygon = polygon
58+
self.thickness: float = thickness
59+
normal: Vector = polygon.normal
60+
down: Vector = normal * (0.0 * thickness)
61+
up: Vector = normal * (-1.0 * thickness)
62+
self.bottom: Polygon = polygon.copy()
63+
for point in self.bottom.points:
64+
point += down
65+
self.top: Polygon = polygon.copy()
66+
for point in self.top.points:
67+
point += up
68+
self.shape: Mesh = shape if shape else self.compute_shape()
69+
if not self.name:
70+
self.name = self.__class__.__name__
71+
72+
# def __init__(self, bottom: Polygon, top: Polygon, frame: Frame = None, name: str = None, shape: Mesh = None):
73+
# super(PlateElement, self).__init__(frame=frame, name=name)
74+
# self.bottom: Polygon = bottom
75+
# self.top: Polygon = top
76+
# self.shape: Mesh = shape if shape else self.compute_shape()
77+
# if not self.name:
78+
# self.name = self.__class__.__name__
6079

6180
@property
62-
def face_polygons(self):
63-
# type: () -> list[compas.geometry.Polygon]
81+
def face_polygons(self) -> list[Polygon]:
6482
return [self.geometry.face_polygon(face) for face in self.geometry.faces()] # type: ignore
6583

66-
def compute_shape(self):
67-
# type: () -> compas.datastructures.Mesh
68-
"""Compute the shape of the plate from the given polygons and features.
84+
def compute_shape(self) -> Mesh:
85+
"""Compute the shape of the plate from the given polygons.
6986
This shape is relative to the frame of the element.
7087
7188
Returns
7289
-------
7390
:class:`compas.datastructures.Mesh`
7491
7592
"""
76-
offset = len(self._bottom)
77-
vertices = self._bottom + self._top # type: ignore
78-
bottom = list(range(offset))
79-
top = [i + offset for i in bottom]
80-
faces = [bottom[::-1], top]
93+
offset: int = len(self.bottom)
94+
vertices: list[Point] = self.bottom.points + self.top.points # type: ignore
95+
bottom: list[int] = list(range(offset))
96+
top: list[int] = [i + offset for i in bottom]
97+
faces: list[list[int]] = [bottom[::-1], top]
8198
for (a, b), (c, d) in zip(pairwise(bottom + bottom[:1]), pairwise(top + top[:1])):
8299
faces.append([a, b, d, c])
83-
mesh = Mesh.from_vertices_and_faces(vertices, faces)
100+
mesh: Mesh = Mesh.from_vertices_and_faces(vertices, faces)
84101
return mesh
85102

86103
# =============================================================================
87104
# Implementations of abstract methods
88105
# =============================================================================
89106

90-
def compute_geometry(self, include_features=False):
91-
geometry = self.shape
92-
if include_features:
93-
if self.features:
94-
for feature in self.features:
95-
geometry = feature.apply(geometry)
96-
geometry.transform(self.worldtransformation)
97-
return geometry
98-
99-
def compute_aabb(self, inflate=0.0):
100-
points = self.geometry.vertices_attributes("xyz") # type: ignore
101-
box = Box.from_bounding_box(bounding_box(points))
107+
def compute_aabb(self, inflate: float = 0.0) -> Box:
108+
points: list[Point] = self.geometry.vertices_attributes("xyz")
109+
box: Box = Box.from_bounding_box(bounding_box(points))
102110
box.xsize += inflate
103111
box.ysize += inflate
104112
box.zsize += inflate
105113
return box
106114

107-
def compute_obb(self, inflate=0.0):
108-
points = self.geometry.vertices_attributes("xyz") # type: ignore
109-
box = Box.from_bounding_box(oriented_bounding_box(points))
115+
def compute_obb(self, inflate: float = 0.0) -> Box:
116+
points: list[Point] = self.geometry.vertices_attributes("xyz")
117+
box: Box = Box.from_bounding_box(oriented_bounding_box(points))
110118
box.xsize += inflate
111119
box.ysize += inflate
112120
box.zsize += inflate
113121
return box
114122

115-
def compute_collision_mesh(self):
116-
# TODO: (TvM) make this a pluggable with default implementation in core and move import to top
123+
def compute_collision_mesh(self) -> Mesh:
117124
from compas.geometry import convex_hull_numpy
118125

119-
points = self.geometry.vertices_attributes("xyz") # type: ignore
120-
vertices, faces = convex_hull_numpy(points)
121-
vertices = [points[index] for index in vertices] # type: ignore
126+
points: list[Point] = self.geometry.vertices_attributes("xyz")
127+
faces: NDArray[np.intc] = convex_hull_numpy(points)
128+
vertices: list[Point] = [points[index] for index in range(len(points))]
122129
return Mesh.from_vertices_and_faces(vertices, faces)
123130

124131
# =============================================================================
125132
# Constructors
126133
# =============================================================================
127134

128-
@classmethod
129-
def from_polygon_and_thickness(cls, polygon, thickness, features=None, frame=None, name=None):
130-
# type: (compas.geometry.Polygon, float, list[PlateFeature] | None, compas.geometry.Frame | None, str | None) -> PlateElement
131-
"""Create a plate element from a polygon and a thickness.
132-
133-
Parameters
134-
----------
135-
polygon : :class:`compas.geometry.Polygon`
136-
The base polygon of the plate.
137-
thickness : float
138-
The total offset thickness above and blow the polygon.
139-
140-
Returns
141-
-------
142-
:class:`PlateElement`
143-
144-
"""
145-
normal = polygon.normal
146-
down = normal * (-0.5 * thickness)
147-
up = normal * (+0.5 * thickness)
148-
bottom = polygon.copy()
149-
for point in bottom.points:
150-
point += down
151-
top = polygon.copy()
152-
for point in top.points:
153-
point += up
154-
plate = cls(bottom, top)
155-
return plate
135+
def rebuild(self, polygon: Polygon) -> "PlateElement":
136+
return self

0 commit comments

Comments
 (0)