Add support for multiple representations such as body and axis

This commit is contained in:
Dion Moult
2019-09-16 16:28:26 +10:00
parent 6d36ee3f53
commit 7516177304
+102 -40
View File
@@ -203,7 +203,7 @@ class IfcParser():
'class': self.get_ifc_class(object.name),
'relating_structure': None,
'relating_qtos_key': None,
'representation': self.get_object_representation_name(object),
'representations': self.get_object_representation_names(object),
'attributes': self.get_object_attributes(object)
}
product['attributes'].update(attribute_override)
@@ -443,14 +443,46 @@ class IfcParser():
if not object.data \
or object.data.name in results:
continue
results[object.data.name] = {
'ifc': None,
'raw': object.data,
'is_wireframe': True if 'IsWireframe' in object.data else False,
'attributes': { 'Name': object.data.name }
}
if self.is_mesh_context_sensitive(object.data.name):
context = self.get_ifc_context(object.data.name)
name = self.get_ifc_representation_name(object.data.name)
for subcontext in self.ifc_export_settings.subcontexts:
mesh = bpy.data.meshes['/'.join([context, subcontext, name])]
if not mesh:
continue
results[mesh.name] = self.get_representation(
mesh, context, subcontext)
else:
context = 'Model'
subcontext = 'Body'
results[object.data.name] = self.get_representation(
object.data, context, subcontext)
return results
def get_representation(self, mesh, context, subcontext):
return {
'ifc': None,
'raw': mesh,
'context': context,
'subcontext': subcontext,
'is_wireframe': True if 'IsWireframe' in mesh else False,
'attributes': { 'Name': mesh.name }
}
def is_mesh_context_sensitive(self, name):
return '/' in name
def get_ifc_context(self, name):
if self.is_mesh_context_sensitive(name):
return name.split('/')[0]
return 'Model'
def get_ifc_representation_name(self, name):
if self.is_mesh_context_sensitive(name):
return name.split('/')[2]
return name
def get_materials(self):
results = {}
if not self.ifc_export_settings.has_representations:
@@ -508,7 +540,7 @@ class IfcParser():
'psets': ['{}/{}'.format(key, object[key]) for key in
object.keys() if key[0:5] == 'Pset_'],
'class': self.get_ifc_class(object.name),
'representation': self.get_object_representation_name(object),
'representations': self.get_object_representation_names(object),
'attributes': self.get_object_attributes(object)
}
results.append(type)
@@ -530,10 +562,21 @@ class IfcParser():
print('The type product "{}" could not be parsed: {}'.format(object.name, e.args))
return results
def get_object_representation_name(self, object):
if object.data:
return object.data.name
return None
def get_object_representation_names(self, object):
names = []
if not object.data:
return names
if not self.is_mesh_context_sensitive(object.data.name):
return [object.data.name]
for subcontext in self.ifc_export_settings.subcontexts:
mesh = bpy.data.meshes['/'.join([
self.get_ifc_context(object.data.name),
subcontext,
self.get_ifc_representation_name(object.data.name)])]
if not mesh:
continue
names.append(mesh.name)
return names
def get_spatial_structure_elements_tree(self, collections, name_filter):
collection_tree = []
@@ -747,17 +790,24 @@ class IfcExporter():
return str(value)
def create_rep_context(self):
self.ifc_rep_context = self.file.createIfcGeometricRepresentationContext(
None, "Model", 3, 1.0E-05, self.origin)
self.ifc_rep_subcontext = self.file.createIfcGeometricRepresentationSubContext(
"Body", "Model",
None, None, None, None,
self.ifc_rep_context, None, "MODEL_VIEW", None)
self.ifc_rep_context = {}
self.ifc_rep_context['Model'] = {
'ifc': self.file.createIfcGeometricRepresentationContext(
None, 'Model', 3, 1.0E-05, self.origin)}
# TODO Make optional
self.ifc_rep_context['Plan'] = {
'ifc': self.file.createIfcGeometricRepresentationContext(
None, 'Plan', 2, 1.0E-05, self.origin)}
for subcontext in self.ifc_export_settings.subcontexts:
self.ifc_rep_context['Model'][subcontext] = {
'ifc': self.file.createIfcGeometricRepresentationSubContext(
subcontext, 'Model',
None, None, None, None,
self.ifc_rep_context['Model']['ifc'], None, 'MODEL_VIEW', None)}
def create_project(self):
self.ifc_parser.project['attributes'].update({
'RepresentationContexts': [self.ifc_rep_context],
'RepresentationContexts': [c['ifc'] for c in self.ifc_rep_context.values()],
'UnitsInContext': self.file.by_type("IfcUnitAssignment")[0]
})
self.ifc_parser.project['ifc'] = self.file.create_entity(
@@ -775,7 +825,8 @@ class IfcExporter():
if not self.ifc_parser.map_conversion:
return
self.create_target_crs()
self.ifc_parser.map_conversion['attributes']['SourceCRS'] = self.ifc_rep_context
# TODO should this be hardcoded?
self.ifc_parser.map_conversion['attributes']['SourceCRS'] = self.ifc_rep_context['Model']['ifc']
self.ifc_parser.map_conversion['attributes']['TargetCRS'] = self.ifc_parser.target_crs['ifc']
self.ifc_parser.map_conversion['ifc'] = self.file.create_entity('IfcMapConversion',
**self.ifc_parser.map_conversion['attributes'])
@@ -792,10 +843,12 @@ class IfcExporter():
for product in self.ifc_parser.type_products:
placement = self.create_ifc_axis_2_placement_3d(product['location'], product['up_axis'], product['forward_axis'])
if product['representation']:
representation = self.ifc_parser.representations[product['representation']]['ifc']
representation_map = self.file.createIfcRepresentationMap(placement, representation)
product['attributes']['RepresentationMaps'] = [representation_map]
if product['representations']:
maps = []
for representation in product['representations']:
maps.append(self.file.createIfcRepresentationMap(
placement, self.ifc_parser.representations[representation]['ifc']))
product['attributes']['RepresentationMaps'] = maps
if product['psets']:
product['attributes'].update({ 'HasPropertySets':
@@ -854,7 +907,7 @@ class IfcExporter():
surface_style = self.file.createIfcSurfaceStyle(None, 'BOTH', styles)
styled_item = self.file.createIfcStyledItem(None, [surface_style], None)
styled_representation = self.file.createIfcStyledRepresentation(
self.ifc_rep_subcontext, None, None, [styled_item])
self.ifc_rep_context['Model']['Body']['ifc'], None, None, [styled_item])
material['ifc'] = self.file.createIfcMaterial(material['raw'].name, None, None)
self.file.createIfcMaterialDefinitionRepresentation(
material['raw'].name, None, [styled_representation], material['ifc'])
@@ -913,16 +966,10 @@ class IfcExporter():
product['up_axis'],
product['forward_axis']))
try:
shape = self.file.createIfcProductDefinitionShape(None, None,
[self.ifc_parser.representations[product['representation']]['ifc']])
except:
shape = None
product['attributes'].update({
'OwnerHistory': self.owner_history, # TODO: unhardcode
'ObjectPlacement': placement,
'Representation': shape
'Representation': self.get_product_shape(product)
})
try:
@@ -930,6 +977,14 @@ class IfcExporter():
except RuntimeError as e:
print('The product "{}/{}" could not be created: {}'.format(product['class'], product['attributes']['Name'], e.args))
def get_product_shape(self, product):
try:
shape = self.file.createIfcProductDefinitionShape(None, None,
[self.ifc_parser.representations[p]['ifc'] for p in product['representations']])
except:
shape = None
return shape
def calculate_quantities(self, qto_name, object):
quantities = []
for index, vg in enumerate(object.vertex_groups):
@@ -965,20 +1020,25 @@ class IfcExporter():
self.ifc_vertices = []
self.ifc_edges = []
self.ifc_faces = []
if representation['is_wireframe']:
return self.create_wireframe_representation(representation['raw'])
return self.create_solid_representation(representation['raw'])
if representation['context'] == 'Plan' \
or representation['subcontext'] == 'Axis' \
or representation['is_wireframe']:
return self.create_wireframe_representation(representation)
return self.create_solid_representation(representation)
def create_wireframe_representation(self, mesh):
def create_wireframe_representation(self, representation):
mesh = representation['raw']
self.create_vertices(mesh.vertices)
for edge in mesh.edges:
self.ifc_edges.append(self.file.createIfcPolyline([
self.ifc_vertices[v] for v in edge.vertices]))
return self.file.createIfcShapeRepresentation(
self.ifc_rep_subcontext, 'Body', 'Curve',
self.ifc_rep_context[representation['context']][representation['subcontext']]['ifc'],
representation['subcontext'], 'Curve',
self.ifc_edges)
def create_solid_representation(self, mesh):
def create_solid_representation(self, representation):
mesh = representation['raw']
self.create_vertices(mesh.vertices)
for polygon in mesh.polygons:
self.ifc_faces.append(self.file.createIfcFace([
@@ -986,7 +1046,8 @@ class IfcExporter():
self.file.createIfcPolyLoop([self.ifc_vertices[vertice] for vertice in polygon.vertices]),
True)]))
return self.file.createIfcShapeRepresentation(
self.ifc_rep_subcontext, 'Body', 'Brep',
self.ifc_rep_context[representation['context']][representation['subcontext']]['ifc'],
representation['subcontext'], 'Brep',
[self.file.createIfcFacetedBrep(self.file.createIfcClosedShell(self.ifc_faces))])
def create_vertices(self, vertices):
@@ -1054,6 +1115,7 @@ class IfcExportSettings:
def __init__(self):
self.has_representations = True
self.has_quantities = True
self.subcontexts = ['Body', 'Axis']
print('# Starting export')
start = time.time()