mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +00:00
Support IfcProjectLibrary as related to IfcProject
This commit is contained in:
@@ -73,7 +73,6 @@ class IfcParser():
|
|||||||
self.type_map = json.load(f)
|
self.type_map = json.load(f)
|
||||||
|
|
||||||
self.selected_products = []
|
self.selected_products = []
|
||||||
self.selected_types = []
|
|
||||||
|
|
||||||
self.product_index = 0
|
self.product_index = 0
|
||||||
|
|
||||||
@@ -88,25 +87,27 @@ class IfcParser():
|
|||||||
self.rel_aggregates = {}
|
self.rel_aggregates = {}
|
||||||
self.representations = []
|
self.representations = []
|
||||||
self.type_products = []
|
self.type_products = []
|
||||||
self.context = {}
|
self.project = {}
|
||||||
|
self.libraries = []
|
||||||
self.products = []
|
self.products = []
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
self.sort_into_products_and_types(bpy.context.selected_objects)
|
self.convert_selected_objects_into_products(bpy.context.selected_objects)
|
||||||
self.psets = self.get_psets()
|
self.psets = self.get_psets()
|
||||||
self.spatial_structure_elements = self.get_spatial_structure_elements()
|
|
||||||
self.representations = self.get_representations()
|
self.representations = self.get_representations()
|
||||||
self.qtos = self.get_qtos()
|
self.qtos = self.get_qtos()
|
||||||
self.type_products = self.get_type_products()
|
self.spatial_structure_elements = self.get_spatial_structure_elements()
|
||||||
|
|
||||||
self.collection_name_filter = []
|
self.collection_name_filter = []
|
||||||
self.get_products()
|
self.get_products()
|
||||||
|
|
||||||
self.context = self.get_context()
|
self.project = self.get_project()
|
||||||
|
self.libraries = self.get_libraries()
|
||||||
|
self.type_products = self.get_type_products()
|
||||||
self.map_conversion = self.get_map_conversion()
|
self.map_conversion = self.get_map_conversion()
|
||||||
self.target_crs = self.get_target_crs()
|
self.target_crs = self.get_target_crs()
|
||||||
self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree(
|
self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree(
|
||||||
self.context['raw'].children, self.collection_name_filter)
|
self.project['raw'].children, self.collection_name_filter)
|
||||||
|
|
||||||
def get_object_attributes(self, object):
|
def get_object_attributes(self, object):
|
||||||
attributes = { 'Name': self.get_ifc_name(object.name) }
|
attributes = { 'Name': self.get_ifc_name(object.name) }
|
||||||
@@ -116,20 +117,20 @@ class IfcParser():
|
|||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
def get_products(self):
|
def get_products(self):
|
||||||
for selected in self.selected_products:
|
for product in self.selected_products:
|
||||||
object = selected['object']
|
object = product['raw']
|
||||||
self.add_product(self.get_product(selected))
|
self.add_product(self.get_product(product))
|
||||||
self.resolve_array_modifier(selected)
|
self.resolve_array_modifier(product)
|
||||||
|
|
||||||
def resolve_array_modifier(self, selected):
|
def resolve_array_modifier(self, product):
|
||||||
object = selected['object']
|
object = product['raw']
|
||||||
instance_objects = [(object, object.location)]
|
instance_objects = [(object, object.location)]
|
||||||
for instance in self.get_instances(object):
|
for instance in self.get_instances(object):
|
||||||
created_instances = []
|
created_instances = []
|
||||||
for n in range(instance.count-1):
|
for n in range(instance.count-1):
|
||||||
for o in instance_objects:
|
for o in instance_objects:
|
||||||
location = o[1] + ((n+1) * instance.offset)
|
location = o[1] + ((n+1) * instance.offset)
|
||||||
self.add_product(self.get_product({ 'object': o[0], 'metadata': selected['metadata'] },
|
self.add_product(self.get_product({ 'raw': o[0], 'metadata': product['metadata'] },
|
||||||
{'location': location}, {'GlobalId': ifcopenshell.guid.new()}))
|
{'location': location}, {'GlobalId': ifcopenshell.guid.new()}))
|
||||||
created_instances.append((o[0], location))
|
created_instances.append((o[0], location))
|
||||||
instance_objects.extend(created_instances)
|
instance_objects.extend(created_instances)
|
||||||
@@ -138,8 +139,8 @@ class IfcParser():
|
|||||||
self.products.append(product)
|
self.products.append(product)
|
||||||
self.product_index += 1
|
self.product_index += 1
|
||||||
|
|
||||||
def get_product(self, selected, metadata_override={}, attribute_override={}):
|
def get_product(self, selected_product, metadata_override={}, attribute_override={}):
|
||||||
object = selected['object']
|
object = selected_product['raw']
|
||||||
product = {
|
product = {
|
||||||
'ifc': None,
|
'ifc': None,
|
||||||
'raw': object,
|
'raw': object,
|
||||||
@@ -162,8 +163,8 @@ class IfcParser():
|
|||||||
and self.is_a_rel_aggregates(self.get_ifc_class(object.instance_collection.name)):
|
and self.is_a_rel_aggregates(self.get_ifc_class(object.instance_collection.name)):
|
||||||
self.rel_aggregates[self.product_index] = object.name
|
self.rel_aggregates[self.product_index] = object.name
|
||||||
|
|
||||||
if 'rel_aggregates_relating_object' in selected['metadata']:
|
if 'rel_aggregates_relating_object' in selected_product['metadata']:
|
||||||
relating_object = selected['metadata']['rel_aggregates_relating_object']
|
relating_object = selected_product['metadata']['rel_aggregates_relating_object']
|
||||||
product['location'] = relating_object.matrix_world @ product['location']
|
product['location'] = relating_object.matrix_world @ product['location']
|
||||||
product['up_axis'] = (relating_object.matrix_world.to_quaternion() @ object.matrix_world.to_quaternion()) @ Vector((0, 0, 1))
|
product['up_axis'] = (relating_object.matrix_world.to_quaternion() @ object.matrix_world.to_quaternion()) @ Vector((0, 0, 1))
|
||||||
product['forward_axis'] = (relating_object.matrix_world.to_quaternion() @ object.matrix_world.to_quaternion()) @ Vector((1, 0, 0))
|
product['forward_axis'] = (relating_object.matrix_world.to_quaternion() @ object.matrix_world.to_quaternion()) @ Vector((1, 0, 0))
|
||||||
@@ -211,16 +212,14 @@ class IfcParser():
|
|||||||
instances.append(array)
|
instances.append(array)
|
||||||
return instances
|
return instances
|
||||||
|
|
||||||
def sort_into_products_and_types(self, objects_to_sort, metadata = None):
|
def convert_selected_objects_into_products(self, objects_to_sort, metadata = None):
|
||||||
if not metadata:
|
if not metadata:
|
||||||
metadata = {}
|
metadata = {}
|
||||||
for object in objects_to_sort:
|
for object in objects_to_sort:
|
||||||
if self.is_object_in_types_collection(object):
|
if not self.is_a_library(self.get_ifc_class(object.users_collection[0].name)):
|
||||||
self.selected_types.append({ 'object': object, 'metadata': metadata })
|
self.selected_products.append({ 'raw': object, 'metadata': metadata })
|
||||||
else:
|
|
||||||
self.selected_products.append({ 'object': object, 'metadata': metadata })
|
|
||||||
if object.instance_type == 'COLLECTION':
|
if object.instance_type == 'COLLECTION':
|
||||||
self.sort_into_products_and_types(object.instance_collection.objects,
|
self.convert_selected_objects_into_products(object.instance_collection.objects,
|
||||||
{'rel_aggregates_relating_object': object})
|
{'rel_aggregates_relating_object': object})
|
||||||
|
|
||||||
def get_psets(self):
|
def get_psets(self):
|
||||||
@@ -236,15 +235,9 @@ class IfcParser():
|
|||||||
})
|
})
|
||||||
return psets
|
return psets
|
||||||
|
|
||||||
def is_object_in_types_collection(self, object):
|
def get_project(self):
|
||||||
for collection in object.users_collection:
|
|
||||||
if self.is_a_types_collection(self.get_ifc_class(collection.name)):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_context(self):
|
|
||||||
for collection in bpy.data.collections:
|
for collection in bpy.data.collections:
|
||||||
if self.is_a_context(self.get_ifc_class(collection.name)):
|
if self.is_a_project(self.get_ifc_class(collection.name)):
|
||||||
return {
|
return {
|
||||||
'ifc': None,
|
'ifc': None,
|
||||||
'raw': collection,
|
'raw': collection,
|
||||||
@@ -252,6 +245,19 @@ class IfcParser():
|
|||||||
'attributes': { 'Name': self.get_ifc_name(collection.name) }
|
'attributes': { 'Name': self.get_ifc_name(collection.name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_libraries(self):
|
||||||
|
results = []
|
||||||
|
for collection in self.project['raw'].children:
|
||||||
|
if not self.is_a_library(self.get_ifc_class(collection.name)):
|
||||||
|
continue
|
||||||
|
results.append({
|
||||||
|
'ifc': None,
|
||||||
|
'raw': collection,
|
||||||
|
'class': self.get_ifc_class(collection.name),
|
||||||
|
'attributes': { 'Name': self.get_ifc_name(collection.name) }
|
||||||
|
})
|
||||||
|
return results
|
||||||
|
|
||||||
def get_map_conversion(self):
|
def get_map_conversion(self):
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
if 'HasMapConversion' not in scene:
|
if 'HasMapConversion' not in scene:
|
||||||
@@ -301,8 +307,8 @@ class IfcParser():
|
|||||||
results = []
|
results = []
|
||||||
if not self.ifc_export_settings.has_representations:
|
if not self.ifc_export_settings.has_representations:
|
||||||
return results
|
return results
|
||||||
for selected in self.selected_products + self.selected_types:
|
for product in self.selected_products + self.type_products:
|
||||||
object = selected['object']
|
object = product['raw']
|
||||||
if not object.data:
|
if not object.data:
|
||||||
continue
|
continue
|
||||||
results.append({
|
results.append({
|
||||||
@@ -317,8 +323,8 @@ class IfcParser():
|
|||||||
if not self.ifc_export_settings.has_quantities:
|
if not self.ifc_export_settings.has_quantities:
|
||||||
return {}
|
return {}
|
||||||
results = {}
|
results = {}
|
||||||
for selected in self.selected_products + self.selected_types:
|
for product in self.selected_products + self.type_products:
|
||||||
object = selected['object']
|
object = product['raw']
|
||||||
if not object.data:
|
if not object.data:
|
||||||
continue
|
continue
|
||||||
for property in object.keys():
|
for property in object.keys():
|
||||||
@@ -336,18 +342,25 @@ class IfcParser():
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def get_type_products(self):
|
def get_type_products(self):
|
||||||
if not self.selected_types:
|
results = []
|
||||||
return []
|
for library in self.libraries:
|
||||||
return [{
|
for object in library['raw'].objects:
|
||||||
'ifc': None,
|
if not self.is_a_type(self.get_ifc_class(object.name)):
|
||||||
'raw': selected['object'],
|
continue
|
||||||
'location': selected['object'].location,
|
try:
|
||||||
'up_axis': selected['object'].matrix_world.to_quaternion() @ Vector((0, 0, 1)),
|
results.append({
|
||||||
'forward_axis': selected['object'].matrix_world.to_quaternion() @ Vector((1, 0, 0)),
|
'ifc': None,
|
||||||
'class': self.get_ifc_class(selected['object'].name),
|
'raw': object,
|
||||||
'representation': self.get_representation_reference_from_object(selected['object']),
|
'location': object.location,
|
||||||
'attributes': self.get_object_attributes(selected['object'])
|
'up_axis': object.matrix_world.to_quaternion() @ Vector((0, 0, 1)),
|
||||||
} for selected in self.selected_types ]
|
'forward_axis': object.matrix_world.to_quaternion() @ Vector((1, 0, 0)),
|
||||||
|
'class': self.get_ifc_class(object.name),
|
||||||
|
'representation': self.get_representation_reference_from_object(object),
|
||||||
|
'attributes': self.get_object_attributes(object)
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
print('The type product "{}" could not be parsed: {}'.format(object.name, e.args))
|
||||||
|
return results
|
||||||
|
|
||||||
def get_representation_reference_from_object(self, object):
|
def get_representation_reference_from_object(self, object):
|
||||||
if not self.ifc_export_settings.has_representations \
|
if not self.ifc_export_settings.has_representations \
|
||||||
@@ -393,22 +406,22 @@ class IfcParser():
|
|||||||
def is_a_spatial_structure_element(self, class_name):
|
def is_a_spatial_structure_element(self, class_name):
|
||||||
# We assume that any collection we can't identify is a spatial structure
|
# We assume that any collection we can't identify is a spatial structure
|
||||||
return class_name[0:3] == 'Ifc' \
|
return class_name[0:3] == 'Ifc' \
|
||||||
and not self.is_a_context(class_name) \
|
and not self.is_a_project(class_name) \
|
||||||
and not self.is_a_types_collection(class_name) \
|
and not self.is_a_library(class_name) \
|
||||||
and not self.is_a_rel_aggregates(class_name)
|
and not self.is_a_rel_aggregates(class_name)
|
||||||
|
|
||||||
def is_a_rel_aggregates(self, class_name):
|
def is_a_rel_aggregates(self, class_name):
|
||||||
return class_name == 'IfcRelAggregates'
|
return class_name == 'IfcRelAggregates'
|
||||||
|
|
||||||
def is_a_context(self, class_name):
|
def is_a_project(self, class_name):
|
||||||
return class_name in ['IfcProject', 'IfcProjectLibrary']
|
return class_name == 'IfcProject'
|
||||||
|
|
||||||
|
def is_a_library(self, class_name):
|
||||||
|
return class_name == 'IfcProjectLibrary'
|
||||||
|
|
||||||
def is_a_type(self, class_name):
|
def is_a_type(self, class_name):
|
||||||
return class_name[0:3] == 'Ifc' and class_name[-4:] == 'Type'
|
return class_name[0:3] == 'Ifc' and class_name[-4:] == 'Type'
|
||||||
|
|
||||||
def is_a_types_collection(self, class_name):
|
|
||||||
return class_name == 'IfcTypeProduct'
|
|
||||||
|
|
||||||
class SIUnitHelper:
|
class SIUnitHelper:
|
||||||
prefixes = ["EXA", "PETA", "TERA", "GIGA", "MEGA", "KILO", "HECTO",
|
prefixes = ["EXA", "PETA", "TERA", "GIGA", "MEGA", "KILO", "HECTO",
|
||||||
"DECA", "DECI", "CENTI", "MILLI", "MICRO", "NANO", "PICO", "FEMTO",
|
"DECA", "DECI", "CENTI", "MILLI", "MICRO", "NANO", "PICO", "FEMTO",
|
||||||
@@ -445,7 +458,8 @@ class IfcExporter():
|
|||||||
self.ifc_parser.parse()
|
self.ifc_parser.parse()
|
||||||
self.create_psets()
|
self.create_psets()
|
||||||
self.create_rep_context()
|
self.create_rep_context()
|
||||||
self.create_context()
|
self.create_project()
|
||||||
|
self.create_libraries()
|
||||||
self.create_map_conversion()
|
self.create_map_conversion()
|
||||||
self.create_representations()
|
self.create_representations()
|
||||||
self.create_type_products()
|
self.create_type_products()
|
||||||
@@ -510,15 +524,22 @@ class IfcExporter():
|
|||||||
None, None, None, None,
|
None, None, None, None,
|
||||||
self.ifc_rep_context, None, "MODEL_VIEW", None)
|
self.ifc_rep_context, None, "MODEL_VIEW", None)
|
||||||
|
|
||||||
def create_context(self):
|
def create_project(self):
|
||||||
context = self.ifc_parser.context
|
self.ifc_parser.project['attributes'].update({
|
||||||
attributes = context['attributes']
|
|
||||||
attributes.update({
|
|
||||||
'GlobalId': ifcopenshell.guid.new(),
|
'GlobalId': ifcopenshell.guid.new(),
|
||||||
'RepresentationContexts': [self.ifc_rep_context],
|
'RepresentationContexts': [self.ifc_rep_context],
|
||||||
'UnitsInContext': self.file.by_type("IfcUnitAssignment")[0]
|
'UnitsInContext': self.file.by_type("IfcUnitAssignment")[0]
|
||||||
})
|
})
|
||||||
self.ifc_parser.context['ifc'] = self.file.create_entity(self.ifc_parser.context['class'], **attributes)
|
self.ifc_parser.project['ifc'] = self.file.create_entity(
|
||||||
|
self.ifc_parser.project['class'], **self.ifc_parser.project['attributes'])
|
||||||
|
|
||||||
|
def create_libraries(self):
|
||||||
|
for library in self.ifc_parser.libraries:
|
||||||
|
library['ifc'] = self.file.create_entity(library['class'], **library['attributes'])
|
||||||
|
self.file.createIfcRelDeclares(
|
||||||
|
ifcopenshell.guid.new(), self.owner_history,
|
||||||
|
library['attributes']['Name'], None,
|
||||||
|
self.ifc_parser.project['ifc'], [l['ifc'] for l in self.ifc_parser.libraries])
|
||||||
|
|
||||||
def create_map_conversion(self):
|
def create_map_conversion(self):
|
||||||
if not self.ifc_parser.map_conversion:
|
if not self.ifc_parser.map_conversion:
|
||||||
@@ -562,7 +583,7 @@ class IfcExporter():
|
|||||||
|
|
||||||
def create_spatial_structure_elements(self, element_tree, relating_object=None):
|
def create_spatial_structure_elements(self, element_tree, relating_object=None):
|
||||||
if relating_object == None:
|
if relating_object == None:
|
||||||
relating_object = self.ifc_parser.context['ifc']
|
relating_object = self.ifc_parser.project['ifc']
|
||||||
placement_rel_to = None
|
placement_rel_to = None
|
||||||
else:
|
else:
|
||||||
placement_rel_to = relating_object.ObjectPlacement
|
placement_rel_to = relating_object.ObjectPlacement
|
||||||
|
|||||||
Reference in New Issue
Block a user