mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +00:00
Allow topological reference export of structural members. See #756.
This commit is contained in:
@@ -130,7 +130,7 @@ class IfcParser():
|
|||||||
self.classifications = self.get_classifications()
|
self.classifications = self.get_classifications()
|
||||||
self.classification_references = self.get_classification_references()
|
self.classification_references = self.get_classification_references()
|
||||||
self.objectives = self.get_objectives()
|
self.objectives = self.get_objectives()
|
||||||
self.representations = self.get_representations()
|
self.load_representations()
|
||||||
self.materials = self.get_materials()
|
self.materials = self.get_materials()
|
||||||
self.styled_items = self.get_styled_items()
|
self.styled_items = self.get_styled_items()
|
||||||
self.qtos = self.get_qtos()
|
self.qtos = self.get_qtos()
|
||||||
@@ -668,55 +668,67 @@ class IfcParser():
|
|||||||
})
|
})
|
||||||
return elements
|
return elements
|
||||||
|
|
||||||
def get_representations(self):
|
def load_representations(self):
|
||||||
results = {}
|
|
||||||
if not self.ifc_export_settings.has_representations:
|
if not self.ifc_export_settings.has_representations:
|
||||||
return results
|
return
|
||||||
for product in self.selected_products + self.type_products:
|
for product in self.selected_products + self.type_products:
|
||||||
obj = product['raw']
|
self.load_product_representations(product)
|
||||||
if self.is_point_cloud(obj):
|
|
||||||
self.append_point_cloud_representation(obj, results)
|
|
||||||
continue
|
|
||||||
elif obj.data is None or obj.data.name in results:
|
|
||||||
continue
|
|
||||||
|
|
||||||
self.append_default_representation(obj, results)
|
def load_product_representations(self, product):
|
||||||
self.append_curve_axis_representation(obj, results)
|
obj = product['raw']
|
||||||
self.append_representation_per_context(obj, results)
|
|
||||||
return results
|
if obj.data and obj.data.name in self.representations:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.append_default_representation(obj)
|
||||||
|
|
||||||
|
if self.is_point_cloud(obj):
|
||||||
|
self.append_point_cloud_representation(obj)
|
||||||
|
elif self.is_structural(obj):
|
||||||
|
self.append_structural_reference_representation(obj)
|
||||||
|
elif obj.type == 'CURVE':
|
||||||
|
self.append_curve_axis_representation(obj)
|
||||||
|
|
||||||
|
self.append_representation_per_context(obj)
|
||||||
|
|
||||||
def is_point_cloud(self, obj):
|
def is_point_cloud(self, obj):
|
||||||
return hasattr(obj, 'point_cloud_visualizer') \
|
return hasattr(obj, 'point_cloud_visualizer') \
|
||||||
and obj.point_cloud_visualizer.uuid
|
and obj.point_cloud_visualizer.uuid
|
||||||
|
|
||||||
def append_default_representation(self, obj, results):
|
def is_structural(self, obj):
|
||||||
if not self.is_mesh_context_sensitive(obj.data.name):
|
return 'IfcStructural' in obj.name
|
||||||
results['Model/Body/MODEL_VIEW/{}'.format(obj.data.name)] = self.get_representation(
|
|
||||||
|
def append_default_representation(self, obj):
|
||||||
|
if obj.data and not self.is_mesh_context_sensitive(obj.data.name):
|
||||||
|
self.representations['Model/Body/MODEL_VIEW/{}'.format(obj.data.name)] = self.get_representation(
|
||||||
obj.data, obj, 'Model', 'Body', 'MODEL_VIEW')
|
obj.data, obj, 'Model', 'Body', 'MODEL_VIEW')
|
||||||
|
|
||||||
def append_point_cloud_representation(self, obj, results):
|
def append_point_cloud_representation(self, obj):
|
||||||
results['Model/Body/MODEL_VIEW/{}'.format(obj.name)] = self.get_representation(
|
self.representations['Model/Body/MODEL_VIEW/{}'.format(obj.name)] = self.get_representation(
|
||||||
obj.point_cloud_visualizer, obj, 'Model', 'Body', 'MODEL_VIEW')
|
obj.point_cloud_visualizer, obj, 'Model', 'Body', 'MODEL_VIEW')
|
||||||
|
|
||||||
def append_curve_axis_representation(self, obj, results):
|
def append_curve_axis_representation(self, obj):
|
||||||
if obj.type == 'CURVE':
|
self.representations['Model/Axis/GRAPH_VIEW/{}'.format(obj.data.name)] = self.get_representation(
|
||||||
results['Model/Axis/GRAPH_VIEW/{}'.format(obj.data.name)] = self.get_representation(
|
obj.data, obj, 'Model', 'Axis', 'GRAPH_VIEW')
|
||||||
obj.data, obj, 'Model', 'Axis', 'GRAPH_VIEW')
|
|
||||||
|
|
||||||
def append_representation_per_context(self, obj, results):
|
def append_structural_reference_representation(self, obj):
|
||||||
|
self.representations['Model/Reference/GRAPH_VIEW/{}'.format(obj.data.name)] = self.get_representation(
|
||||||
|
obj.data, obj, 'Model', 'Reference', 'GRAPH_VIEW')
|
||||||
|
|
||||||
|
def append_representation_per_context(self, obj):
|
||||||
name = self.get_ifc_representation_name(obj.data.name)
|
name = self.get_ifc_representation_name(obj.data.name)
|
||||||
for context in self.ifc_export_settings.context_tree:
|
for context in self.ifc_export_settings.context_tree:
|
||||||
for subcontext in context['subcontexts']:
|
for subcontext in context['subcontexts']:
|
||||||
for target_view in subcontext['target_views']:
|
for target_view in subcontext['target_views']:
|
||||||
mesh_name = '/'.join([context['name'], subcontext['name'], target_view, name])
|
mesh_name = '/'.join([context['name'], subcontext['name'], target_view, name])
|
||||||
try:
|
mesh = bpy.data.meshes.get(mesh_name)
|
||||||
mesh = bpy.data.meshes[mesh_name]
|
if not mesh:
|
||||||
except:
|
mesh = bpy.data.curves.get(mesh_name)
|
||||||
continue
|
if mesh:
|
||||||
results[mesh_name] = self.get_representation(
|
self.representations[mesh_name] = self.get_representation(
|
||||||
mesh, obj, context['name'], subcontext['name'], target_view)
|
mesh, obj, context['name'], subcontext['name'], target_view)
|
||||||
|
|
||||||
def get_representation(self, mesh, obj, context, subcontext, target_view, is_generated=False):
|
def get_representation(self, mesh, obj, context, subcontext, target_view):
|
||||||
return {
|
return {
|
||||||
'ifc': None,
|
'ifc': None,
|
||||||
'raw': mesh,
|
'raw': mesh,
|
||||||
@@ -725,10 +737,11 @@ class IfcParser():
|
|||||||
'subcontext': subcontext,
|
'subcontext': subcontext,
|
||||||
'target_view': target_view,
|
'target_view': target_view,
|
||||||
'is_curve': isinstance(mesh, bpy.types.Curve),
|
'is_curve': isinstance(mesh, bpy.types.Curve),
|
||||||
|
'is_point_cloud': self.is_point_cloud(obj),
|
||||||
|
'is_structural': self.is_structural(obj),
|
||||||
'is_wireframe': mesh.BIMMeshProperties.is_wireframe if hasattr(mesh, 'BIMMeshProperties') else False,
|
'is_wireframe': mesh.BIMMeshProperties.is_wireframe if hasattr(mesh, 'BIMMeshProperties') else False,
|
||||||
'is_swept_solid': mesh.BIMMeshProperties.is_swept_solid if hasattr(mesh, 'BIMMeshProperties') else False,
|
'is_swept_solid': mesh.BIMMeshProperties.is_swept_solid if hasattr(mesh, 'BIMMeshProperties') else False,
|
||||||
'is_generated': is_generated,
|
'is_generated': False,
|
||||||
'is_point_cloud': self.is_point_cloud(obj),
|
|
||||||
'attributes': {'Name': mesh.name}
|
'attributes': {'Name': mesh.name}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,28 +879,14 @@ class IfcParser():
|
|||||||
names = []
|
names = []
|
||||||
if self.is_point_cloud(obj):
|
if self.is_point_cloud(obj):
|
||||||
names.append('Model/Body/MODEL_VIEW/{}'.format(obj.name))
|
names.append('Model/Body/MODEL_VIEW/{}'.format(obj.name))
|
||||||
if obj.data is None:
|
|
||||||
return names
|
return names
|
||||||
if not self.is_mesh_context_sensitive(obj.data.name):
|
|
||||||
names.append('Model/Body/MODEL_VIEW/{}'.format(obj.data.name))
|
|
||||||
name = self.get_ifc_representation_name(obj.data.name)
|
name = self.get_ifc_representation_name(obj.data.name)
|
||||||
for context in self.ifc_export_settings.context_tree:
|
for context in self.ifc_export_settings.context_tree:
|
||||||
for subcontext in context['subcontexts']:
|
for subcontext in context['subcontexts']:
|
||||||
for target_view in subcontext['target_views']:
|
for target_view in subcontext['target_views']:
|
||||||
mesh_name = '/'.join([context['name'], subcontext['name'], target_view, name])
|
mesh_name = '/'.join([context['name'], subcontext['name'], target_view, name])
|
||||||
|
if mesh_name in self.representations:
|
||||||
if context['name'] == 'Model' \
|
|
||||||
and subcontext['name'] == 'Axis' \
|
|
||||||
and target_view == 'GRAPH_VIEW' \
|
|
||||||
and obj.type == 'CURVE':
|
|
||||||
names.append(mesh_name)
|
names.append(mesh_name)
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
mesh = bpy.data.meshes[mesh_name]
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
names.append(mesh_name)
|
|
||||||
return names
|
return names
|
||||||
|
|
||||||
def get_spatial_structure_elements_tree(self, collections, name_filter):
|
def get_spatial_structure_elements_tree(self, collections, name_filter):
|
||||||
@@ -1648,7 +1647,13 @@ class IfcExporter():
|
|||||||
and representation['subcontext'] == 'Axis' \
|
and representation['subcontext'] == 'Axis' \
|
||||||
and representation['target_view'] == 'GRAPH_VIEW':
|
and representation['target_view'] == 'GRAPH_VIEW':
|
||||||
return self.file.createIfcRepresentationMap(
|
return self.file.createIfcRepresentationMap(
|
||||||
self.origin, self.create_axis_representation(representation))
|
self.origin, self.create_curve_axis_representation(representation))
|
||||||
|
elif representation['is_structural'] \
|
||||||
|
and representation['context'] == 'Model' \
|
||||||
|
and representation['subcontext'] == 'Reference' \
|
||||||
|
and representation['target_view'] == 'GRAPH_VIEW':
|
||||||
|
return self.file.createIfcRepresentationMap(
|
||||||
|
self.origin, self.create_structural_reference_representation(representation))
|
||||||
elif representation['context'] == 'Plan' \
|
elif representation['context'] == 'Plan' \
|
||||||
or representation['subcontext'] == 'Axis' \
|
or representation['subcontext'] == 'Axis' \
|
||||||
or representation['is_wireframe']:
|
or representation['is_wireframe']:
|
||||||
@@ -1750,13 +1755,20 @@ class IfcExporter():
|
|||||||
# Find tangent and return.
|
# Find tangent and return.
|
||||||
return (pt1 - pt0) * usq3 + (pt2 - pt1) * ut6 + (pt3 - pt2) * tsq3
|
return (pt1 - pt0) * usq3 + (pt2 - pt1) * ut6 + (pt3 - pt2) * tsq3
|
||||||
|
|
||||||
def create_axis_representation(self, representation):
|
def create_curve_axis_representation(self, representation):
|
||||||
return self.file.createIfcShapeRepresentation(
|
return self.file.createIfcShapeRepresentation(
|
||||||
self.ifc_rep_context[representation['context']][representation['subcontext']][
|
self.ifc_rep_context[representation['context']][representation['subcontext']][
|
||||||
representation['target_view']]['ifc'],
|
representation['target_view']]['ifc'],
|
||||||
representation['subcontext'], 'Curve3D',
|
representation['subcontext'], 'Curve3D',
|
||||||
[self.create_curve(representation['raw'])])
|
[self.create_curve(representation['raw'])])
|
||||||
|
|
||||||
|
def create_structural_reference_representation(self, representation):
|
||||||
|
return self.file.createIfcTopologyRepresentation(
|
||||||
|
self.ifc_rep_context[representation['context']][representation['subcontext']][
|
||||||
|
representation['target_view']]['ifc'],
|
||||||
|
representation['subcontext'], 'Edge',
|
||||||
|
[self.create_edge(representation['raw'])])
|
||||||
|
|
||||||
def create_curve_representation(self, representation):
|
def create_curve_representation(self, representation):
|
||||||
# TODO: support unclosed surfaces
|
# TODO: support unclosed surfaces
|
||||||
swept_area = self.file.createIfcArbitraryClosedProfileDef('AREA', None,
|
swept_area = self.file.createIfcArbitraryClosedProfileDef('AREA', None,
|
||||||
@@ -1795,6 +1807,21 @@ class IfcExporter():
|
|||||||
representation['subcontext'], 'AdvancedSweptSolid',
|
representation['subcontext'], 'AdvancedSweptSolid',
|
||||||
swept_area_solids)
|
swept_area_solids)
|
||||||
|
|
||||||
|
def create_vertex_point(self, point):
|
||||||
|
return self.file.createIfcVertexPoint(
|
||||||
|
self.create_cartesian_point(point.x, point.y, point.z))
|
||||||
|
|
||||||
|
def create_edge(self, curve):
|
||||||
|
if curve.splines[0].bezier_points:
|
||||||
|
points = curve.splines[0].bezier_points
|
||||||
|
elif curve.splines[0].points:
|
||||||
|
points = curve.splines[0].points
|
||||||
|
if not points:
|
||||||
|
return
|
||||||
|
return self.file.createIfcEdge(
|
||||||
|
self.create_vertex_point(points[0].co),
|
||||||
|
self.create_vertex_point(points[1].co))
|
||||||
|
|
||||||
def create_curve(self, curve):
|
def create_curve(self, curve):
|
||||||
# TODO: support interpolated curves, not just polylines
|
# TODO: support interpolated curves, not just polylines
|
||||||
points = []
|
points = []
|
||||||
|
|||||||
Reference in New Issue
Block a user