Skip to content

Commit 5310b89

Browse files
authored
Merge pull request #56 from BlockResearchGroup/new_feature_elements_and_interactions
Elements and Interactions
2 parents adc7001 + 2950874 commit 5310b89

File tree

18 files changed

+996
-22
lines changed

18 files changed

+996
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4040
* Added `compas_model.models.bvh.ElementBVH`.
4141
* Added `compas_model.models.bvh.ElementAABBNode`.
4242
* Added `compas_model.models.bvh.ElementOBBNode`.
43+
* Added `compas_model.elements.BeamElement`.
44+
* Added `compas_model.elements.ColumnElement`.
45+
* Added `compas_model.elements.PlateElement`.
4346
* Added `compas_model.models.Model.collisions` iterator.
4447
* Added `compas_model.models.graph.InteractionGraph.clear_edges`.
4548

data/frame.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +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": "fb541808-f597-4887-ad14-dfc9f6986049"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 0.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "af2c15a8-358e-4a76-9929-09220abb5a37"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 0.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "ad7b8d31-4b4c-460f-ba88-015cdbece5ef"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 0.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "7984e9ad-322e-43de-a3bf-0b85e71520c3"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, -3000.0, 3800.0], "end": [-3000.0, 3000.0, 3800.0]}, "guid": "54127e6c-3e59-486f-bdb1-104e3d640608"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, 3000.0, 3800.0], "end": [3000.0, -3000.0, 3800.0]}, "guid": "1c9712d8-c7eb-4b8d-8536-9f6150a8ee61"}, {"dtype": "compas.geometry/Line", "data": {"start": [-3000.0, 3000.0, 3800.0], "end": [3000.0, 3000.0, 3800.0]}, "guid": "ec1ef974-8366-4350-a998-87a0f6f1cd7a"}, {"dtype": "compas.geometry/Line", "data": {"start": [3000.0, -3000.0, 3800.0], "end": [-3000.0, -3000.0, 3800.0]}, "guid": "b59e5ff5-fe5b-42e8-945c-8c6b768617db"}], "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": "0334f95a-f3fa-4e72-9d43-07d5da2b19ee"}]}

docs/examples/elements/beam.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from compas.datastructures import Mesh
2+
from compas.geometry import Rotation
3+
from compas.geometry import Translation
4+
from compas_model.elements import BeamElement
5+
from compas_model.models import Model
6+
from compas_viewer import Viewer
7+
8+
# Create an element.
9+
beam = BeamElement(0.2, 0.3, 3)
10+
11+
# Element transformation can be set or modified as an attribute.
12+
R = Rotation.from_axis_and_angle([0, 1, 0], 3.14 / 2, beam.center_line.midpoint)
13+
T = Translation.from_vector([0, 0, 1.5])
14+
beam.transformation = T * R
15+
16+
# But the transformation is applied when beam.modelgeometry is computed.
17+
model = Model()
18+
model.add_element(beam)
19+
mesh_in_element_space: Mesh = beam.elementgeometry
20+
mesh_in_model_space: Mesh = beam.modelgeometry
21+
22+
# Vizualize.
23+
viewer = Viewer()
24+
viewer.scene.add(mesh_in_element_space)
25+
viewer.scene.add(mesh_in_model_space)
26+
viewer.show()

docs/examples/elements/column.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from compas.geometry import Translation
2+
from compas_model.elements import ColumnElement
3+
from compas_model.models import Model
4+
from compas_viewer import Viewer
5+
6+
# Create an element.
7+
column = ColumnElement(0.2, 0.2, 3)
8+
9+
# Element transformation can be set or modified as an attribute.
10+
vectors: list[list[float]] = [
11+
[-3, -3, 0],
12+
[-3, 3, 0],
13+
[3, 3, 0],
14+
[3, -3, 0],
15+
]
16+
17+
model = Model()
18+
for v in vectors:
19+
column_copy = column.copy()
20+
column_copy.transformation = Translation.from_vector(v)
21+
model.add_element(column_copy)
22+
23+
# Vizualize.
24+
viewer = Viewer()
25+
for element in model.elements():
26+
viewer.scene.add(element.modelgeometry)
27+
viewer.show()

docs/examples/elements/plate.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from compas.geometry import Polygon
2+
from compas_model.elements import PlateElement
3+
from compas_viewer import Viewer
4+
5+
# Create an element.
6+
points: list[list[float]] = [
7+
[-3, -3, 0],
8+
[-3, 3, 0],
9+
[3, 3, 0],
10+
[3, -3, 0],
11+
]
12+
polygon: Polygon = Polygon(points)
13+
plate = PlateElement(polygon=polygon, thickness=0.2)
14+
15+
# Vizualize.
16+
viewer = Viewer()
17+
viewer.scene.add(plate.elementgeometry)
18+
viewer.show()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from compas.geometry import Rotation
2+
from compas.geometry import Translation
3+
from compas_model.elements import BeamElement
4+
from compas_model.interactions import BooleanModifier
5+
from compas_model.models import Model
6+
from compas_viewer import Viewer
7+
8+
# Create an element.
9+
beam0: BeamElement = BeamElement(0.2, 0.3, 3, name="beam0")
10+
beam1: BeamElement = beam0.copy()
11+
beam1.name = "beam1"
12+
13+
# Element transformation can be set or modified as an attribute.
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
17+
18+
# But the transformation is applied when beam.modelgeometry is computed.
19+
model = Model()
20+
model.add_element(beam0)
21+
model.add_element(beam1)
22+
23+
model.add_interaction(beam1, beam0)
24+
model.add_modifier(beam1, beam0, BooleanModifier)
25+
26+
# Vizualize.
27+
viewer = Viewer()
28+
for element in model.elements():
29+
viewer.scene.add(element.modelgeometry, hide_coplanaredges=True)
30+
viewer.show()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from compas.geometry import Rotation
2+
from compas.geometry import Translation
3+
from compas_model.elements import BeamElement
4+
from compas_model.interactions import SlicerModifier
5+
from compas_model.models import Model
6+
from compas_viewer import Viewer
7+
8+
# Create an element.
9+
beam0: BeamElement = BeamElement(0.2, 0.3, 3, name="beam0")
10+
beam1: BeamElement = beam0.copy()
11+
beam1.name = "beam1"
12+
13+
# Element transformation can be set or modified as an attribute.
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
17+
18+
# But the transformation is applied when beam.modelgeometry is computed.
19+
model = Model()
20+
model.add_element(beam0)
21+
model.add_element(beam1)
22+
23+
model.add_interaction(beam0, beam1)
24+
model.add_modifier(beam0, beam1, SlicerModifier)
25+
26+
# Vizualize.
27+
viewer = Viewer()
28+
for element in model.elements():
29+
viewer.scene.add(element.modelgeometry, hide_coplanaredges=True)
30+
viewer.show()
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from pathlib import Path
2+
3+
from compas import json_dump
4+
from compas import json_load
5+
from compas.datastructures import Mesh
6+
from compas.geometry import Frame
7+
from compas.geometry import Line
8+
from compas.geometry import Point
9+
from compas.geometry import Transformation
10+
from compas.geometry import Translation
11+
from compas.geometry import Vector
12+
from compas.tolerance import TOL
13+
from compas_model.elements import BeamElement
14+
from compas_model.elements import ColumnElement
15+
from compas_model.models import Model
16+
from compas_viewer import Viewer
17+
from compas_viewer.config import Config
18+
19+
# =============================================================================
20+
# Create Geometry
21+
# =============================================================================
22+
points = [
23+
Point(-3000, -3000, 0),
24+
Point(-3000, 3000, 0),
25+
Point(3000, 3000, 0),
26+
Point(3000, -3000, 0),
27+
Point(-3000, -3000, 3800),
28+
Point(-3000, 3000, 3800),
29+
Point(3000, 3000, 3800),
30+
Point(3000, -3000, 3800),
31+
]
32+
33+
lines = [
34+
Line(points[0], points[4]),
35+
Line(points[1], points[5]),
36+
Line(points[2], points[6]),
37+
Line(points[3], points[7]),
38+
Line(points[4], points[5]),
39+
Line(points[6], points[7]),
40+
Line(points[5], points[6]),
41+
Line(points[7], points[4]),
42+
]
43+
44+
mesh = Mesh.from_vertices_and_faces(points[4:], [[0, 1, 2, 3]])
45+
46+
# =============================================================================
47+
# Serialize Geometry into a JSON file
48+
# =============================================================================
49+
model_input = {"Model::Line::Segments": lines, "Model::Mesh::Floor": [mesh]}
50+
json_dump(model_input, Path("data/frame.json"))
51+
52+
53+
# =============================================================================
54+
# Load Geometry from JSON and Create Model
55+
# =============================================================================
56+
rhino_geometry = json_load(Path("data/frame.json"))
57+
lines = rhino_geometry["Model::Line::Segments"]
58+
59+
model = Model()
60+
61+
# Add columns
62+
columns = []
63+
for i in range(4):
64+
column = ColumnElement(300, 300, lines[i].length)
65+
column.transformation = Transformation.from_frame_to_frame(Frame.worldXY(), Frame(lines[i].start))
66+
model.add_element(column)
67+
columns.append(column)
68+
69+
# Add beams
70+
beams = []
71+
for i in range(4, len(lines)):
72+
beam = BeamElement(width=300, depth=700, length=lines[i].length)
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
80+
beam.extend(150)
81+
model.add_element(beam)
82+
beams.append(beam)
83+
84+
# Add interactions and modifiers
85+
for column in columns:
86+
for beam in beams:
87+
model.add_interaction(column, beam)
88+
model.add_modifier(column, beam) # column -> cuts -> beam
89+
90+
# =============================================================================
91+
# Visualize Final Model
92+
# =============================================================================
93+
config = Config()
94+
config.camera.target = [0, 0, 100]
95+
config.camera.position = [10000, -10000, 10000]
96+
config.camera.near = 10
97+
config.camera.far = 100000
98+
99+
viewer = Viewer(config=config)
100+
for element in model.elements():
101+
viewer.scene.add(element.modelgeometry, hide_coplanaredges=True)
102+
viewer.show()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
from .element import reset_computed
22
from .element import Element
33
from .element import Feature
4+
from .beam import BeamElement
5+
from .beam import BeamFeature
6+
from .column import ColumnElement
7+
from .column import ColumnFeature
8+
from .plate import PlateElement
9+
from .plate import PlateFeature
410

511

612
__all__ = [
713
"reset_computed",
814
"Element",
915
"Feature",
16+
"BeamElement",
17+
"BeamFeature",
18+
"ColumnElement",
19+
"ColumnFeature",
20+
"PlateElement",
21+
"PlateFeature",
1022
]

0 commit comments

Comments
 (0)