Skip to content

Commit 4b7058e

Browse files
committed
ifccityjson: updated georeferencing & added option to split IFC files based on Level of Detail
1 parent fb1c340 commit 4b7058e

1 file changed

Lines changed: 54 additions & 12 deletions

File tree

src/ifccityjson/cityjson2ifc.py

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import ifcopenshell.api
2121
from geometry import GeometryIO
2222
from datetime import datetime
23+
import os
2324

2425
JSON_TO_IFC = {
2526
"Building": ["IfcBuilding"],
@@ -75,7 +76,7 @@ def __init__(self):
7576
self.configuration()
7677

7778
def configuration(self, file_destination="output.ifc", name_attribute=None, split=True):
78-
self.properties["file_destination"] = file_destination
79+
self.properties["file_destination"], self.properties["file_extension"] = os.path.splitext(file_destination)
7980
self.properties["name_attribute"] = name_attribute
8081
self.properties["split"] = split
8182

@@ -88,7 +89,10 @@ def convert(self, city_model):
8889
scale=self.properties["local_scale"])
8990
# self.build_vertices()
9091
self.create_IFC_classes()
91-
self.write_file()
92+
if self.properties["split"]:
93+
self.write_files()
94+
else:
95+
self.write_file()
9296

9397
def create_metadata(self):
9498
# Georeferencing
@@ -107,13 +111,13 @@ def create_metadata(self):
107111
if epsg:
108112
# Meter is assumed as unit for now
109113
unit = self.IFC_model.createIfcSIUnit(None, "LENGTHUNIT", None, "METRE")
110-
crs = self.IFC_model.create_entity("IfcProjectedCrs", Name=f"epsg:{epsg}")
111-
self.IFC_model.create_entity("IfcMapConversion", self.IFC_representation_context,
112-
**self.properties["local_translation"])
114+
self.properties["local_translation"]["TargetCRS"] = self.IFC_model.create_entity("IfcProjectedCrs", Name=f"epsg:{epsg}")
115+
self.properties["local_translation"]["SourceCRS"] = self.IFC_representation_context
116+
self.IFC_model.create_entity("IfcMapConversion", **self.properties["local_translation"])
113117

114118
def create_new_file(self):
115119
self.IFC_model = ifcopenshell.api.run("project.create_file")
116-
self.IFC_project = ifcopenshell.api.run("root.create_entity", self.IFC_model, **{"ifc_class": "IfcProject"})
120+
self.IFC_project = ifcopenshell.api.run("root.create_entity", self.IFC_model, **{"ifc_class": "IfcProject", "name": "My Project"})
117121
ifcopenshell.api.run("unit.assign_unit", self.IFC_model, length={"is_metric": True, "raw": "METERS"})
118122
self.properties["owner_history"] = self.create_owner_history()
119123
self.IFC_representation_context = ifcopenshell.api.run("context.add_context", self.IFC_model,
@@ -139,6 +143,10 @@ def create_new_file(self):
139143
self.IFC_site = ifcopenshell.api.run("root.create_entity", self.IFC_model,
140144
**{"ifc_class": "IfcSite",
141145
"name": "My Site"})
146+
self.IFC_model.create_entity("IfcRelAggregates",
147+
**{"GlobalId": ifcopenshell.guid.new(),
148+
"RelatedObjects": [self.IFC_site],
149+
"RelatingObject": self.IFC_project})
142150

143151
def create_owner_history(self):
144152
actor = self.IFC_model.createIfcActorRole("ENGINEER", None, None)
@@ -157,7 +165,31 @@ def create_owner_history(self):
157165
return ownerHistory
158166

159167
def write_file(self):
160-
self.IFC_model.write(self.properties["file_destination"])
168+
file = self.properties["file_destination"] + self.properties["file_extension"]
169+
self.IFC_model.write(file)
170+
171+
def write_files(self):
172+
for lod, IFC_representation_sub_context in self.IFC_representation_sub_contexts.items():
173+
sub_context_id = IFC_representation_sub_context.id()
174+
175+
# TODO this method makes a copy of the IFC_model by writing it and importing it,
176+
# TODO but maybe there is a better method.
177+
file = self.properties["file_destination"] + lod + self.properties["file_extension"]
178+
self.IFC_model.write(file)
179+
IFC_copied_model = ifcopenshell.open(file)
180+
181+
IFC_copied_model_sub_contexts = IFC_copied_model.by_type('IfcGeometricRepresentationSubContext')
182+
for sub_context in IFC_copied_model_sub_contexts:
183+
if sub_context.id() == sub_context_id:
184+
continue
185+
else:
186+
elements = IFC_copied_model.get_inverse(sub_context)
187+
for element in elements:
188+
IFC_copied_model.remove(element)
189+
IFC_copied_model.remove(sub_context)
190+
191+
IFC_copied_model.write(file)
192+
del IFC_copied_model
161193

162194
def create_IFC_classes(self):
163195
parents_children_relations = {"IfcSite": {'Parent': self.IFC_site, 'Children': []}}
@@ -223,14 +255,21 @@ def create_IFC_classes(self):
223255
parents_children_relations[obj_id]['Parent'] = IFC_object
224256

225257
if IFC_semantic_surface_children:
226-
self.IFC_model.create_entity("IfcRelAggregates",
258+
self.IFC_model.create_entity("IfcRelContainedInSpatialStructure",
227259
**{"GlobalId": ifcopenshell.guid.new(),
228-
"RelatedObjects": IFC_semantic_surface_children,
229-
"RelatingObject": IFC_object})
260+
"RelatedElements": IFC_semantic_surface_children,
261+
"RelatingStructure": IFC_object})
230262

231263
self.create_property_set(obj.attributes, IFC_object)
232264

233-
for parent_children in parents_children_relations.values():
265+
for parent, parent_children in parents_children_relations.items():
266+
if parent == "IfcSite":
267+
self.IFC_model.create_entity("IfcRelAggregates",
268+
**{"GlobalId": ifcopenshell.guid.new(),
269+
"RelatedObjects": parent_children['Children'],
270+
"RelatingObject": parent_children['Parent']})
271+
continue
272+
234273
self.IFC_model.create_entity("IfcRelContainedInSpatialStructure",
235274
**{"GlobalId": ifcopenshell.guid.new(),
236275
"RelatedElements": parent_children['Children'],
@@ -248,8 +287,11 @@ def create_IFC_semantic_surface_children(self, geometry, lod):
248287
# CREATE ENTITY
249288
surface_geometry = self.geometry.create_IFC_surface(self.IFC_model, geometry, surface_id)
250289
if surface_geometry:
251-
child_data["Representation"] = self.create_IFC_shape_representation(surface_geometry, 'brep', lod)
290+
IFC_shape_representation =self.create_IFC_shape_representation(surface_geometry, 'brep', lod)
291+
child_data["Representation"] = self.IFC_model.create_entity("IfcProductDefinitionShape",
292+
Representations=[IFC_shape_representation])
252293
IFC_semantic_surface_children.append(self.IFC_model.create_entity(IFC_child_class, **child_data))
294+
253295
return IFC_semantic_surface_children
254296

255297
def create_IFC_shape_representation(self, IFC_geometry, shape_representation_type, lod):

0 commit comments

Comments
 (0)