Skip to content

Commit 9241fee

Browse files
committed
update opening element
1 parent 519a71f commit 9241fee

File tree

2 files changed

+169
-24
lines changed

2 files changed

+169
-24
lines changed

src/ifcplus/api/built_element.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def create_3pt_beam_or_column_or_member(
169169

170170
def create_opening_element(
171171
voided_element: ifcopenshell.entity_instance,
172-
profile_points: list[tuple[float, float]], # 2D profile in XY coords of opening
172+
profile: ifcopenshell.entity_instance,
173173
depth: float, # Extrusion depth in the local z direction of the opening element
174174
origin_relative_to_voided_element: tuple[float, float, float] = (0.0, 0.0, 0.0),
175175
z_axis_relative_to_voided_element: tuple[float, float, float] = (0.0, 0.0, 1.0),
@@ -178,59 +178,62 @@ def create_opening_element(
178178

179179
ifc4_file = voided_element.file
180180

181-
# Create Element
182181
opening_element = ifcopenshell.api.root.create_entity(
183182
file=ifc4_file,
184183
ifc_class="IfcOpeningElement",
185184
name=None,
186185
predefined_type=None,
187186
)
188-
ifcplus.api.placement.edit_object_placement(
189-
product=opening_element,
190-
place_object_relative_to_parent=False,
191-
)
192-
opening_element.ObjectPlacement.PlacementRelTo = voided_element.ObjectPlacement
193187

194-
# Add Profile
195-
profile = ifcplus.api.profile.add_arbitrary_profile_with_or_without_voids(
196-
file=ifc4_file,
197-
outer_profile=profile_points,
198-
inner_profiles=[],
199-
name=None,
200-
)
201-
202-
# Add and Assign Representation
203188
representation_item = ifcplus.api.geometry.add_extruded_area_solid(
204189
ifc4_file=ifc4_file,
205190
profile=profile,
206191
extrusion_depth=depth,
207-
repositioned_origin=origin_relative_to_voided_element,
208-
repositioned_x_axis=x_axis_relative_to_voided_element,
209-
repositioned_z_axis=z_axis_relative_to_voided_element,
192+
# repositioned_origin=origin_relative_to_voided_element,
193+
# repositioned_x_axis=x_axis_relative_to_voided_element,
194+
# repositioned_z_axis=z_axis_relative_to_voided_element,
195+
)
196+
197+
representation_type = ifcopenshell.util.representation.guess_type(
198+
items=[representation_item]
210199
)
200+
211201
shape_model = ifcplus.api.geometry.add_shape_model(
212202
ifc4_file=ifc4_file,
213203
shape_model_class="IfcShapeRepresentation",
214204
representation_identifier="Body",
215-
representation_type="SweptSolid",
205+
representation_type=cast(str, representation_type), # SweptSolid
216206
context_type="Model",
217207
target_view="MODEL_VIEW",
218208
items=[representation_item],
219209
)
210+
220211
ifcopenshell.api.geometry.assign_representation(
221212
file=ifc4_file,
222213
product=opening_element,
223214
representation=shape_model,
224215
)
225216

226-
# Void Relationship
227217
rel_voids_element = ifcopenshell.api.root.create_entity(
228218
file=ifc4_file,
229219
ifc_class="IfcRelVoidsElement",
230220
)
231221
rel_voids_element.RelatingBuildingElement = voided_element
232222
rel_voids_element.RelatedOpeningElement = opening_element
233223

224+
ifcplus.api.placement.edit_object_placement(
225+
product=opening_element,
226+
place_object_relative_to_parent=False,
227+
)
228+
opening_element.ObjectPlacement.PlacementRelTo = voided_element.ObjectPlacement
229+
opening_element.ObjectPlacement.RelativePlacement = (
230+
ifc4_file.createIfcAxis2Placement3D(
231+
ifc4_file.createIfcCartesianPoint(origin_relative_to_voided_element),
232+
ifc4_file.createIfcDirection(z_axis_relative_to_voided_element),
233+
ifc4_file.createIfcDirection(x_axis_relative_to_voided_element),
234+
)
235+
)
236+
234237
return opening_element
235238

236239

@@ -301,7 +304,7 @@ def create_2pt_wall(
301304
)
302305
length = float(np.linalg.norm(vector_from_start_point_to_end_point))
303306

304-
extruded_area_solid = ifcplus.api.geometry.add_extruded_area_solid(
307+
representation_item = ifcplus.api.geometry.add_extruded_area_solid(
305308
ifc4_file=ifc4_file,
306309
profile=ifcplus.api.profile.add_arbitrary_profile_with_or_without_voids(
307310
file=ifc4_file,
@@ -319,7 +322,7 @@ def create_2pt_wall(
319322
)
320323

321324
representation_type = ifcopenshell.util.representation.guess_type(
322-
items=[extruded_area_solid]
325+
items=[representation_item]
323326
)
324327

325328
shape_model = ifcplus.api.geometry.add_shape_model(
@@ -329,7 +332,7 @@ def create_2pt_wall(
329332
representation_type=cast(str, representation_type), # SweptSolid
330333
context_type="Model",
331334
target_view="MODEL_VIEW",
332-
items=[extruded_area_solid],
335+
items=[representation_item],
333336
)
334337

335338
ifcopenshell.api.geometry.assign_representation(

tests/ifcplus/api/test_built_element.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,145 @@ def test_add_straight_walls(
109109

110110
pprint(logger.statements)
111111
assert len(logger.statements) == 0
112+
113+
def test_add_straight_walls_with_openings(
114+
self,
115+
):
116+
117+
ifc4_file = ifcplus.api.project.create_ifc4_file(
118+
model_view_definition="ReferenceView_V1.2",
119+
precision=1e-4,
120+
)
121+
122+
project = ifc4_file.by_type(
123+
type="IfcProject",
124+
include_subtypes=False,
125+
)[0]
126+
127+
site = ifcopenshell.api.root.create_entity(
128+
file=ifc4_file,
129+
ifc_class="IfcSite",
130+
name="Site-01",
131+
)
132+
ifcopenshell.api.aggregate.assign_object(
133+
file=ifc4_file,
134+
products=[site],
135+
relating_object=project,
136+
)
137+
ifcplus.api.placement.edit_object_placement(
138+
product=site,
139+
repositioned_origin=(1.0, 1.0, 0.0),
140+
place_object_relative_to_parent=True,
141+
)
142+
143+
concrete_material = ifcplus.api.material.add_material_from_standard_library(
144+
ifc4_file=ifc4_file,
145+
region="Europe",
146+
material_name="C35/45",
147+
check_for_duplicate=True,
148+
)
149+
150+
steel_material = ifcplus.api.material.add_material_from_standard_library(
151+
ifc4_file=ifc4_file,
152+
region="Europe",
153+
material_name="S355",
154+
check_for_duplicate=True,
155+
)
156+
157+
wall_1 = ifcplus.api.built_element.create_2pt_wall(
158+
start_point_2d=(1.0, 1.0),
159+
end_point_2d=(7.0, 1.0),
160+
elevation=0.0,
161+
height=3.0,
162+
materials=[
163+
cast(ifcopenshell.entity_instance, concrete_material),
164+
cast(ifcopenshell.entity_instance, steel_material),
165+
cast(ifcopenshell.entity_instance, concrete_material),
166+
],
167+
thicknesses=[0.10, 0.10, 0.20],
168+
name="Wall-01",
169+
parent=site,
170+
place_object_relative_to_parent=True,
171+
)
172+
173+
opening_depth = 0.10 + 0.10 + 0.20
174+
175+
ifcplus.api.built_element.create_opening_element(
176+
voided_element=wall_1,
177+
profile=ifcplus.api.profile.add_parameterized_profile(
178+
ifc4_file=ifc4_file,
179+
profile_class="IfcRectangleProfileDef",
180+
dimensions=[2.0, 1.0],
181+
profile_name=None,
182+
check_for_duplicate=True,
183+
calculate_mechanical_properties=False,
184+
),
185+
depth=opening_depth,
186+
origin_relative_to_voided_element=(2.0, -opening_depth / 2.0, 1.5),
187+
z_axis_relative_to_voided_element=(0.0, 1.0, 0.0),
188+
x_axis_relative_to_voided_element=(-1.0, 0.0, 0.0),
189+
)
190+
191+
ifcplus.api.built_element.create_opening_element(
192+
voided_element=wall_1,
193+
profile=ifcplus.api.profile.add_parameterized_profile(
194+
ifc4_file=ifc4_file,
195+
profile_class="IfcCircleProfileDef",
196+
dimensions=[0.5],
197+
profile_name=None,
198+
check_for_duplicate=True,
199+
calculate_mechanical_properties=False,
200+
),
201+
depth=opening_depth,
202+
origin_relative_to_voided_element=(4.5, -opening_depth / 2.0, 2.0),
203+
z_axis_relative_to_voided_element=(0.0, 1.0, 0.0),
204+
x_axis_relative_to_voided_element=(-1.0, 0.0, 0.0),
205+
)
206+
207+
wall_2 = ifcplus.api.built_element.create_2pt_wall(
208+
start_point_2d=(1.0 + 8.0, 1.0),
209+
end_point_2d=(7.0 + 8.0, 1.0 + 2.0),
210+
elevation=1.0,
211+
height=3.0,
212+
materials=[
213+
cast(ifcopenshell.entity_instance, concrete_material),
214+
cast(ifcopenshell.entity_instance, steel_material),
215+
cast(ifcopenshell.entity_instance, concrete_material),
216+
],
217+
thicknesses=[0.10, 0.10, 0.20],
218+
name="Wall-01",
219+
parent=site,
220+
place_object_relative_to_parent=True,
221+
)
222+
223+
ifcplus.api.built_element.create_opening_element(
224+
voided_element=wall_2,
225+
profile=ifcplus.api.profile.add_parameterized_profile(
226+
ifc4_file=ifc4_file,
227+
profile_class="IfcRectangleProfileDef",
228+
dimensions=[2.0, 1.0],
229+
profile_name=None,
230+
check_for_duplicate=True,
231+
calculate_mechanical_properties=False,
232+
),
233+
depth=opening_depth,
234+
origin_relative_to_voided_element=(2.0, -opening_depth / 2.0, 1.5),
235+
z_axis_relative_to_voided_element=(0.0, 1.0, 0.0),
236+
x_axis_relative_to_voided_element=(-1.0, 0.0, 0.0),
237+
)
238+
239+
output_path = str(
240+
OUTPUT_DIR_FOR_BUILT_ELEMENT / "straight_walls_with_openings.ifc"
241+
)
242+
ifcplus.api.project.write_to_ifc_spf(
243+
ifc4_file=ifc4_file,
244+
file_path=output_path,
245+
add_annotations=True,
246+
)
247+
248+
logger = ifcopenshell.validate.json_logger()
249+
ifcopenshell.validate.validate(output_path, logger, express_rules=True)
250+
from pprint import pprint
251+
252+
pprint(logger.statements)
253+
assert len(logger.statements) == 0

0 commit comments

Comments
 (0)