Skip to content

Commit a54948a

Browse files
FIX simplification of elements and examples.
1 parent aba95fe commit a54948a

File tree

11 files changed

+111
-267
lines changed

11 files changed

+111
-267
lines changed

data/frame.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"Model::Line::Segments": [{"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, -3000.0, 0.0], "end": [-3000.0, -3000.0, 3800.0]}, "guid": "2fc7fca3-cf83-44a8-9338-31917268590b"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 0.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "aa520fb7-ff92-43da-b8c1-6a77754650f1"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 0.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "29a4ef5b-edf0-4bd6-95f5-20b864c49908"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 0.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "2263ec71-b010-499c-9614-3424307e6602"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, -3000.0, 3800.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "0ecd6ac6-1853-485b-8b50-3f07c7ec207d"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 3800.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "008c3470-f42b-4184-a2d3-6c0c5416f901"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 3800.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "94af457f-3386-4fb7-9f8f-24d05eed86d2"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 3800.0], "end": [-3000.0, -3000.0, 3800.0]}, "guid": "7c7014f7-d93c-4b17-a2d8-f8ff41f95a80"}], "Model::Mesh::Floor": [{"dtype": "compas.datastructures/Mesh", "data": {"attributes": {}, "default_vertex_attributes": {"x": 0.0, "y": 0.0, "z": 0.0}, "default_edge_attributes": {}, "default_face_attributes": {}, "vertex": {"0": {"x": -3000.0, "y": -3000.0, "z": 3800.0}, "1": {"x": -3000.0, "y": 3000.0, "z": 3800.0}, "2": {"x": 3000.0, "y": 3000.0, "z": 3800.0}, "3": {"x": 3000.0, "y": -3000.0, "z": 3800.0}}, "face": {"0": [0, 1, 2, 3]}, "facedata": {"0": {}}, "edgedata": {}, "max_vertex": 3, "max_face": 0}, "guid": "82f752d5-cf71-41e6-9aa0-742e41eddc14"}]}
1+
{"Model::Line::Segments": [{"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, -3000.0, 0.0], "end": [-3000.0, -3000.0, 3800.0]}, "guid": "5554c158-460a-45ed-9eef-217ecd7a5708"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 0.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "f457ba83-864d-4e64-9282-a24b3f5251b5"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 0.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "aa9195e3-5738-43d1-a12d-561c7632c0bf"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 0.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "a3154c66-a35d-4fb6-870c-9bc3377364be"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, -3000.0, 3800.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "6581d8db-73d0-434f-a58d-a4a48e904768"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 3800.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "08445beb-b6e9-478d-b481-10062a72f3fd"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 3800.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "95e3539f-d5fe-4df4-8a3b-e1a9a57c7aea"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 3800.0], "end": [-3000.0, -3000.0, 3800.0]}, "guid": "f556a3d0-2b8d-44a8-8951-040443228075"}], "Model::Mesh::Floor": [{"dtype": "compas.datastructures/Mesh", "data": {"attributes": {}, "default_vertex_attributes": {"x": 0.0, "y": 0.0, "z": 0.0}, "default_edge_attributes": {}, "default_face_attributes": {}, "vertex": {"0": {"x": -3000.0, "y": -3000.0, "z": 3800.0}, "1": {"x": -3000.0, "y": 3000.0, "z": 3800.0}, "2": {"x": 3000.0, "y": 3000.0, "z": 3800.0}, "3": {"x": 3000.0, "y": -3000.0, "z": 3800.0}}, "face": {"0": [0, 1, 2, 3]}, "facedata": {"0": {}}, "edgedata": {}, "max_vertex": 3, "max_face": 0}, "guid": "787458c5-682f-4688-adfe-8478f99142c4"}]}

docs/examples/elements/beam.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@
66
from compas_viewer import Viewer
77

88
# Create an element.
9-
beam: BeamElement = BeamElement(0.2, 0.3, 3)
10-
beam.copy()
9+
beam = BeamElement(0.2, 0.3, 3)
1110

1211
# Element transformation can be set or modified as an attribute.
13-
beam.transformation = Rotation.from_axis_and_angle([0, 1, 0], 3.14/2, beam.axis.midpoint)
14-
beam.transformation = Translation.from_vector([0, 0, 1.5])* beam.transformation # Rotate then translate
12+
beam.transformation = Rotation.from_axis_and_angle([0, 1, 0], 3.14 / 2, beam.center_line.midpoint)
13+
beam.transformation = Translation.from_vector([0, 0, 1.5]) * beam.transformation # Rotate then translate
1514

1615
# But the transformation is applied when beam.modelgeometry is computed.
1716
model = Model()
1817
model.add_element(beam)
19-
mesh_in_element_space : Mesh = beam.elementgeometry
20-
mesh_in_model_space : Mesh = beam.modelgeometry
18+
mesh_in_element_space: Mesh = beam.elementgeometry
19+
mesh_in_model_space: Mesh = beam.modelgeometry
2120

2221
# Vizualize.
2322
viewer = Viewer()

docs/examples/elements/column.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from compas_viewer import Viewer
55

66
# Create an element.
7-
column: ColumnElement = ColumnElement(0.2, 0.2, 3)
7+
column = ColumnElement(0.2, 0.2, 3)
88

99
# Element transformation can be set or modified as an attribute.
10-
vectors : list[list[float]] = [
10+
vectors: list[list[float]] = [
1111
[-3, -3, 0],
1212
[-3, 3, 0],
1313
[3, 3, 0],

docs/examples/elements/plate.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
from compas_viewer import Viewer
44

55
# Create an element.
6-
points : list[list[float]] = [
6+
points: list[list[float]] = [
77
[-3, -3, 0],
88
[-3, 3, 0],
99
[3, 3, 0],
1010
[3, -3, 0],
11-
1211
]
13-
polygon : Polygon = Polygon(points)
14-
plate: PlateElement = PlateElement(polygon=polygon, thickness=0.2)
15-
plate.copy()
12+
polygon: Polygon = Polygon(points)
13+
plate = PlateElement(polygon=polygon, thickness=0.2)
1614

1715
# Vizualize.
1816
viewer = Viewer()

docs/examples/interactions/000_boolean_modifier.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88
# Create an element.
99
beam0: BeamElement = BeamElement(0.2, 0.3, 3, name="beam0")
10-
beam1 : BeamElement = beam0.copy()
10+
beam1: BeamElement = beam0.copy()
1111
beam1.name = "beam1"
1212

1313
# Element transformation can be set or modified as an attribute.
14-
beam0.transformation = Rotation.from_axis_and_angle([0, 1, 0], 3.14/2, beam0.axis.midpoint)
15-
beam0.transformation = Translation.from_vector([0, 0, 1.5])* beam0.transformation # Rotate then translate
14+
R = Rotation.from_axis_and_angle([0, 1, 0], 3.14 / 2, beam0.center_line.midpoint)
15+
T = Translation.from_vector([0, 0, 1.5])
16+
beam0.transformation = T * R # Rotate then translate
1617

1718
# But the transformation is applied when beam.modelgeometry is computed.
1819
model = Model()

docs/examples/interactions/001_slicer_modifier.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88
# Create an element.
99
beam0: BeamElement = BeamElement(0.2, 0.3, 3, name="beam0")
10-
beam1 : BeamElement = beam0.copy()
10+
beam1: BeamElement = beam0.copy()
1111
beam1.name = "beam1"
1212

1313
# Element transformation can be set or modified as an attribute.
14-
beam0.transformation = Rotation.from_axis_and_angle([0, 1, 0], 3.14/2, beam0.axis.midpoint)
15-
beam0.transformation = Translation.from_vector([0, 0, 1.5])* beam0.transformation # Rotate then translate
14+
R = Rotation.from_axis_and_angle([0, 1, 0], 3.14 / 2, beam0.center_line.midpoint)
15+
T = Translation.from_vector([0, 0, 1.5])
16+
beam0.transformation = T * R # Rotate then translate
1617

1718
# But the transformation is applied when beam.modelgeometry is computed.
1819
model = Model()

docs/examples/interactions/002_frame.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
from compas.geometry import Frame
77
from compas.geometry import Line
88
from compas.geometry import Point
9+
from compas.geometry import Transformation
910
from compas.geometry import Translation
1011
from compas.geometry import Vector
11-
from compas.geometry.transformation import Transformation
1212
from compas.tolerance import TOL
1313
from compas_model.elements import BeamElement
1414
from compas_model.elements import ColumnElement
@@ -70,13 +70,13 @@
7070
beams = []
7171
for i in range(4, len(lines)):
7272
beam = BeamElement(width=300, depth=700, length=lines[i].length)
73-
target_frame = Frame(
74-
lines[i].start, Vector.Zaxis().cross(lines[i].vector), Vector.Zaxis()
75-
)
76-
beam.transformation = (
77-
Transformation.from_frame_to_frame(Frame.worldXY(), target_frame)
78-
* Translation.from_vector([0, beam.depth * -0.5, 0])
79-
)
73+
point = lines[i].start
74+
xaxis = Vector.Zaxis().cross(lines[i].vector)
75+
yaxis = Vector.Zaxis()
76+
target_frame = Frame(point, xaxis, yaxis)
77+
X = Transformation.from_frame_to_frame(Frame.worldXY(), target_frame)
78+
T = Translation.from_vector([0, beam.depth * -0.5, 0])
79+
beam.transformation = X * T
8080
beam.extend(150)
8181
model.add_element(beam)
8282
beams.append(beam)
@@ -90,8 +90,6 @@
9090
# =============================================================================
9191
# Visualize Final Model
9292
# =============================================================================
93-
TOL.lineardeflection = 100
94-
9593
config = Config()
9694
config.camera.target = [0, 0, 100]
9795
config.camera.position = [10000, -10000, 10000]

src/compas_model/elements/beam.py

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Optional
2+
from typing import Type
23

34
from compas.datastructures import Mesh
45
from compas.geometry import Box
@@ -9,11 +10,8 @@
910
from compas.geometry import Polygon
1011
from compas.geometry import Transformation
1112
from compas.geometry import Translation
12-
from compas.geometry import bounding_box
13-
from compas.geometry import identity_matrix
1413
from compas.geometry import intersection_line_plane
1514
from compas.geometry import is_point_in_polygon_xy
16-
from compas.geometry import oriented_bounding_box
1715
from compas_model.elements.element import Element
1816
from compas_model.elements.element import Feature
1917
from compas_model.interactions import BooleanModifier
@@ -51,26 +49,8 @@ class BeamElement(Element):
5149
The depth of the beam.
5250
length : float
5351
The length of the beam.
54-
is_support : bool
55-
Flag indicating if the beam is a support.
56-
frame_bottom : :class:`compas.geometry.Frame`
57-
Main frame of the beam.
58-
frame_top : :class:`compas.geometry.Frame`
59-
Second frame of the beam.
60-
axis : :class:`compas.geometry.Line`
52+
center_line : :class:`compas.geometry.Line`
6153
Line axis of the beam.
62-
section : :class:`compas.geometry.Polygon`
63-
Section polygon of the beam.
64-
polygon_bottom : :class:`compas.geometry.Polygon`
65-
The bottom polygon of the beam.
66-
polygon_top : :class:`compas.geometry.Polygon`
67-
The top polygon of the beam.
68-
transformation : :class:`compas.geometry.Transformation`
69-
Transformation applied to the beam.
70-
features : list[:class:`compas_model.features.BeamFeature`]
71-
Features of the beam.
72-
name : str
73-
The name of the beam.
7454
"""
7555

7656
@property
@@ -79,7 +59,6 @@ def __data__(self) -> dict:
7959
"width": self.width,
8060
"depth": self.depth,
8161
"length": self.length,
82-
"is_support": self.is_support,
8362
"transformation": self.transformation,
8463
"features": self._features,
8564
"name": self.name,
@@ -90,26 +69,16 @@ def __init__(
9069
width: float = 0.1,
9170
depth: float = 0.2,
9271
length: float = 3.0,
93-
is_support: bool = False,
9472
transformation: Optional[Transformation] = None,
9573
features: Optional[list[BeamFeature]] = None,
9674
name: Optional[str] = None,
9775
) -> "BeamElement":
98-
super().__init__(frame=Frame.worldXY(), transformation=transformation, features=features, name=name)
99-
100-
self.is_support: bool = is_support
76+
super().__init__(transformation=transformation, features=features, name=name)
10177

10278
self.width: float = width
10379
self.depth: float = depth
10480
self._length: float = length
10581

106-
self.points: list[list[float]] = [[-width * 0.5, -depth * 0.5, 0], [-width * 0.5, depth * 0.5, 0], [width * 0.5, depth * 0.5, 0], [width * 0.5, -depth * 0.5, 0]]
107-
108-
self.section: Polygon = Polygon(self.points)
109-
self.axis: Line = Line([0, 0, 0], [0, 0, length])
110-
self.frame_top: Frame = Frame(self.frame.point + self.axis.vector, self.frame.xaxis, self.frame.yaxis)
111-
self.polygon_bottom, self.polygon_top = self.compute_top_and_bottom_polygons()
112-
11382
def compute_elementgeometry(self) -> Mesh:
11483
"""Compute the shape of the beam from the given polygons .
11584
This shape is relative to the frame of the element.
@@ -119,13 +88,7 @@ def compute_elementgeometry(self) -> Mesh:
11988
:class:`compas.datastructures.Mesh`
12089
"""
12190
box: Box = Box.from_width_height_depth(self.width, self.length, self.depth)
122-
box.translate(
123-
[
124-
0,
125-
0,
126-
self.length * 0.5,
127-
]
128-
)
91+
box.translate([0, 0, self.length * 0.5])
12992
return box.to_mesh()
13093

13194
@property
@@ -135,12 +98,11 @@ def length(self) -> float:
13598
@length.setter
13699
def length(self, length: float):
137100
self._length = length
101+
self.compute_elementgeometry()
138102

139-
self.section = Polygon(list(self.points))
140-
141-
self.axis = Line([0, 0, 0], [0, 0, length])
142-
self.frame_top = Frame(self.frame.point + self.axis.vector, self.frame.xaxis, self.frame.yaxis)
143-
self.polygon_bottom, self.polygon_top = self.compute_top_and_bottom_polygons()
103+
@property
104+
def center_line(self) -> Line:
105+
return Line([0, 0, 0], [0, 0, self.length])
144106

145107
def extend(self, distance: float) -> None:
146108
"""Extend the beam.
@@ -167,11 +129,12 @@ def compute_aabb(self, inflate: float = 0.0) -> Box:
167129
:class:`compas.geometry.Box`
168130
The axis-aligned bounding box.
169131
"""
170-
points: list[list[float]] = self.geometry.vertices_attributes("xyz") # type: ignore
171-
box: Box = Box.from_bounding_box(bounding_box(points))
172-
box.xsize += inflate
173-
box.ysize += inflate
174-
box.zsize += inflate
132+
box = self.modelgeometry.aabb
133+
if self.inflate_aabb and self.inflate_aabb != 1.0:
134+
box.xsize += self.inflate_aabb
135+
box.ysize += self.inflate_aabb
136+
box.zsize += self.inflate_aabb
137+
self._aabb = box
175138
return box
176139

177140
def compute_obb(self, inflate: float = 0.0) -> Box:
@@ -187,11 +150,12 @@ def compute_obb(self, inflate: float = 0.0) -> Box:
187150
:class:`compas.geometry.Box`
188151
The oriented bounding box.
189152
"""
190-
points: list[list[float]] = self.geometry.vertices_attributes("xyz") # type: ignore
191-
box: Box = Box.from_bounding_box(oriented_bounding_box(points))
192-
box.xsize += inflate
193-
box.ysize += inflate
194-
box.zsize += inflate
153+
box = self.modelgeometry.obb
154+
if self.inflate_aabb and self.inflate_aabb != 1.0:
155+
box.xsize += self.inflate_obb
156+
box.ysize += self.inflate_obb
157+
box.zsize += self.inflate_obb
158+
self._obb = box
195159
return box
196160

197161
def compute_collision_mesh(self) -> Mesh:
@@ -202,25 +166,12 @@ def compute_collision_mesh(self) -> Mesh:
202166
:class:`compas.datastructures.Mesh`
203167
The collision mesh.
204168
"""
205-
from compas.geometry import convex_hull_numpy
206-
207-
points: list[list[float]] = self.geometry.vertices_attributes("xyz") # type: ignore
208-
vertices, faces = convex_hull_numpy(points)
209-
vertices = [points[index] for index in vertices] # type: ignore
210-
return Mesh.from_vertices_and_faces(vertices, faces)
169+
mesh = self.modelgeometry.convex_hull
170+
self._collision_mesh = mesh
171+
return mesh
211172

212173
def compute_point(self) -> Point:
213-
"""Computes a reference point for the element geometry (e.g. the centroid).
214-
215-
Returns
216-
-------
217-
:class:`compas.geometry.Point`
218-
The reference point.
219-
220-
"""
221-
222-
xform: Transformation = identity_matrix if self.modeltransformation is None else self.modeltransformation
223-
return self.frame.point.transformed(xform)
174+
return Point(*self.modelgeometry.centroid())
224175

225176
def compute_top_and_bottom_polygons(self) -> tuple[Polygon, Polygon]:
226177
"""Compute the top and bottom polygons of the beam.
@@ -244,31 +195,31 @@ def compute_top_and_bottom_polygons(self) -> tuple[Polygon, Polygon]:
244195
points1.append(result1)
245196
return Polygon(points0), Polygon(points1)
246197

247-
def _add_modifier_with_beam(self, target_element: "BeamElement", modifier_type: type[Modifier] = None, **kwargs) -> Modifier:
198+
def _add_modifier_with_beam(self, target_element: "BeamElement", modifier_type: Type[Modifier] = None, **kwargs) -> Modifier:
248199
if not modifier_type:
249200
raise ValueError("Modifier type is not defined, please define a modifier type e.g. SlicerModfier.")
250201

251-
if isinstance(modifier_type, type) and issubclass(modifier_type, BooleanModifier):
202+
if issubclass(modifier_type, BooleanModifier):
252203
return BooleanModifier(self.elementgeometry.transformed(self.modeltransformation))
253204

254-
if isinstance(modifier_type, type) and issubclass(modifier_type, SlicerModifier):
205+
if issubclass(modifier_type, SlicerModifier):
255206
return self._create_slicer_modifier(target_element)
256207

257208
raise ValueError(f"Unknown modifier type: {modifier_type}")
258209

259210
def _create_slicer_modifier(self, target_element: "BeamElement") -> Modifier:
260211
mesh = self.elementgeometry.transformed(self.modeltransformation)
261-
axis = target_element.axis.transformed(target_element.modeltransformation)
212+
center_line = target_element.center_line.transformed(target_element.modeltransformation)
262213

263-
p0 = axis.start
264-
p1 = axis.end
214+
p0 = center_line.start
215+
p1 = center_line.end
265216

266217
closest_distance_to_end_point = float("inf")
267218
closest_face = 0
268219
for face in self.elementgeometry.faces():
269220
polygon = mesh.face_polygon(face)
270221
frame = polygon.frame
271-
result = intersection_line_plane(axis, Plane.from_frame(frame))
222+
result = intersection_line_plane(center_line, Plane.from_frame(frame))
272223
if result:
273224
point = Point(*result)
274225
xform = Transformation.from_frame_to_frame(frame, Frame.worldXY())

0 commit comments

Comments
 (0)