mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 22:31:55 +00:00
Allow export of objects contained inside IfcSpace and other spatial elements
This commit is contained in:
@@ -145,8 +145,6 @@ class IfcParser():
|
|||||||
self.spatial_structure_elements = self.get_spatial_structure_elements()
|
self.spatial_structure_elements = self.get_spatial_structure_elements()
|
||||||
self.structural_analysis_models = self.get_structural_analysis_models()
|
self.structural_analysis_models = self.get_structural_analysis_models()
|
||||||
|
|
||||||
self.collection_name_filter = []
|
|
||||||
|
|
||||||
self.project = self.get_project()
|
self.project = self.get_project()
|
||||||
self.libraries = self.get_libraries()
|
self.libraries = self.get_libraries()
|
||||||
self.door_attributes = self.get_door_attributes()
|
self.door_attributes = self.get_door_attributes()
|
||||||
@@ -157,8 +155,7 @@ class IfcParser():
|
|||||||
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.library_information = self.get_library_information()
|
self.library_information = self.get_library_information()
|
||||||
self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree(
|
self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree(self.project)
|
||||||
self.project['raw'].children, self.collection_name_filter)
|
|
||||||
|
|
||||||
def get_units(self):
|
def get_units(self):
|
||||||
return {
|
return {
|
||||||
@@ -397,7 +394,7 @@ class IfcParser():
|
|||||||
product['attributes'].update(attribute_override)
|
product['attributes'].update(attribute_override)
|
||||||
product.update(metadata_override)
|
product.update(metadata_override)
|
||||||
|
|
||||||
type_product = obj.BIMObjectProperties.type_product
|
type_product = obj.BIMObjectProperties.relating_type
|
||||||
if type_product \
|
if type_product \
|
||||||
and self.is_a_type(self.get_ifc_class(type_product.name)):
|
and self.is_a_type(self.get_ifc_class(type_product.name)):
|
||||||
reference = self.get_type_product_reference(type_product.name)
|
reference = self.get_type_product_reference(type_product.name)
|
||||||
@@ -408,8 +405,7 @@ class IfcParser():
|
|||||||
product['boundary_condition_attributes'] = {a.name: a.string_value
|
product['boundary_condition_attributes'] = {a.name: a.string_value
|
||||||
for a in obj.BIMObjectProperties.boundary_condition.attributes}
|
for a in obj.BIMObjectProperties.boundary_condition.attributes}
|
||||||
|
|
||||||
for collection in product['raw'].users_collection:
|
self.get_product_relating_structure(product, obj)
|
||||||
self.parse_product_collection(product, collection)
|
|
||||||
|
|
||||||
if 'IfcRelNests' in obj.constraints:
|
if 'IfcRelNests' in obj.constraints:
|
||||||
# TODO: I think get_product_index_from_raw_name should not be used
|
# TODO: I think get_product_index_from_raw_name should not be used
|
||||||
@@ -494,6 +490,16 @@ class IfcParser():
|
|||||||
|
|
||||||
return product
|
return product
|
||||||
|
|
||||||
|
def get_product_relating_structure(self, product, obj):
|
||||||
|
relating_structure = obj.BIMObjectProperties.relating_structure
|
||||||
|
if relating_structure:
|
||||||
|
reference = self.get_spatial_structure_element_reference(relating_structure.name)
|
||||||
|
self.rel_contained_in_spatial_structure.setdefault(reference, []).append(self.product_index)
|
||||||
|
product['relating_structure'] = reference
|
||||||
|
return
|
||||||
|
for collection in product['raw'].users_collection:
|
||||||
|
self.parse_product_collection(product, collection)
|
||||||
|
|
||||||
def parse_product_collection(self, product, collection):
|
def parse_product_collection(self, product, collection):
|
||||||
if collection is None:
|
if collection is None:
|
||||||
return
|
return
|
||||||
@@ -502,7 +508,6 @@ class IfcParser():
|
|||||||
reference = self.get_spatial_structure_element_reference(collection.name)
|
reference = self.get_spatial_structure_element_reference(collection.name)
|
||||||
self.rel_contained_in_spatial_structure.setdefault(reference, []).append(self.product_index)
|
self.rel_contained_in_spatial_structure.setdefault(reference, []).append(self.product_index)
|
||||||
product['relating_structure'] = reference
|
product['relating_structure'] = reference
|
||||||
self.collection_name_filter.append(collection.name)
|
|
||||||
elif self.is_a_structural_analysis_model(class_name):
|
elif self.is_a_structural_analysis_model(class_name):
|
||||||
reference = self.get_structural_analysis_model_reference(collection.name)
|
reference = self.get_structural_analysis_model_reference(collection.name)
|
||||||
self.rel_assigns_to_group.setdefault(reference, []).append(self.product_index)
|
self.rel_assigns_to_group.setdefault(reference, []).append(self.product_index)
|
||||||
@@ -523,7 +528,7 @@ class IfcParser():
|
|||||||
for obj in objects_to_sort:
|
for obj in objects_to_sort:
|
||||||
if obj.name[0:3] != 'Ifc':
|
if obj.name[0:3] != 'Ifc':
|
||||||
continue
|
continue
|
||||||
elif obj.users_collection and obj.users_collection[0].name == obj.name:
|
elif self.is_a_spatial_structure_element(self.get_ifc_class(obj.name)):
|
||||||
self.selected_spatial_structure_elements.append({'raw': obj, 'metadata': metadata})
|
self.selected_spatial_structure_elements.append({'raw': obj, 'metadata': metadata})
|
||||||
elif obj.instance_type == 'COLLECTION':
|
elif obj.instance_type == 'COLLECTION':
|
||||||
self.categorise_selected_objects(
|
self.categorise_selected_objects(
|
||||||
@@ -725,19 +730,16 @@ class IfcParser():
|
|||||||
|
|
||||||
def get_spatial_structure_elements(self):
|
def get_spatial_structure_elements(self):
|
||||||
elements = []
|
elements = []
|
||||||
for collection in bpy.data.collections:
|
for selected_element in self.selected_spatial_structure_elements:
|
||||||
if self.is_a_spatial_structure_element(self.get_ifc_class(collection.name)):
|
obj = selected_element['raw']
|
||||||
raw = bpy.data.objects.get(collection.name)
|
element = {
|
||||||
if not raw:
|
'ifc': None,
|
||||||
raw = collection
|
'raw': obj,
|
||||||
element = {
|
'class': self.get_ifc_class(obj.name),
|
||||||
'ifc': None,
|
'attributes': self.get_object_attributes(obj)
|
||||||
'raw': raw,
|
}
|
||||||
'class': self.get_ifc_class(raw.name),
|
self.append_product_attributes(element, obj)
|
||||||
'attributes': self.get_object_attributes(raw)
|
elements.append(element)
|
||||||
}
|
|
||||||
self.append_product_attributes(element, raw)
|
|
||||||
elements.append(element)
|
|
||||||
return elements
|
return elements
|
||||||
|
|
||||||
def get_structural_analysis_models(self):
|
def get_structural_analysis_models(self):
|
||||||
@@ -998,22 +1000,29 @@ class IfcParser():
|
|||||||
names.append(mesh_name)
|
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, parent):
|
||||||
collection_tree = []
|
children = []
|
||||||
|
if parent['raw'].name not in bpy.data.collections:
|
||||||
for collection in collections:
|
return children
|
||||||
if not self.is_a_spatial_structure_element(self.get_ifc_class(collection.name)):
|
for reference, element in enumerate(self.spatial_structure_elements):
|
||||||
continue
|
if ( \
|
||||||
children = self.get_spatial_structure_elements_tree(
|
# A convention is established that spatial elements may be
|
||||||
collection.children, name_filter)
|
# an object placed in a collection of the same name
|
||||||
if collection.name in name_filter \
|
element['raw'].name == element['raw'].users_collection[0].name \
|
||||||
or children:
|
and element['raw'].users_collection[0].name in [c.name \
|
||||||
collection_tree.append({
|
for c in bpy.data.collections[parent['raw'].name].children] \
|
||||||
'reference': self.get_spatial_structure_element_reference(collection.name),
|
) or ( \
|
||||||
'children': children
|
# We allow finer grain spatial elements such as IfcSpace to
|
||||||
|
# break the convention to prevent collection overload in Blender
|
||||||
|
element['raw'].name != element['raw'].users_collection[0].name \
|
||||||
|
and element['raw'].users_collection[0].name in [o.name \
|
||||||
|
for o in bpy.data.collections[parent['raw'].name].objects] \
|
||||||
|
):
|
||||||
|
children.append({
|
||||||
|
'reference': reference,
|
||||||
|
'children': self.get_spatial_structure_elements_tree(element)
|
||||||
})
|
})
|
||||||
|
return children
|
||||||
return collection_tree
|
|
||||||
|
|
||||||
def get_spatial_structure_element_reference(self, name):
|
def get_spatial_structure_element_reference(self, name):
|
||||||
return ['{}/{}'.format(e['class'], e['attributes']['Name'])
|
return ['{}/{}'.format(e['class'], e['attributes']['Name'])
|
||||||
@@ -1038,12 +1047,14 @@ class IfcParser():
|
|||||||
'Name "{}" does not follow the format of "IfcClass/Name"'.format(name))
|
'Name "{}" does not follow the format of "IfcClass/Name"'.format(name))
|
||||||
|
|
||||||
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
|
return class_name in [
|
||||||
return class_name[0:3] == 'Ifc' \
|
'IfcBuilding',
|
||||||
and not self.is_a_project(class_name) \
|
'IfcBuildingStorey',
|
||||||
and not self.is_a_library(class_name) \
|
'IfcExternalSpatialElement',
|
||||||
and not self.is_a_rel_aggregates(class_name) \
|
'IfcSite',
|
||||||
and not self.is_a_structural_analysis_model(class_name)
|
'IfcSpace',
|
||||||
|
'IfcSpatialZone'
|
||||||
|
]
|
||||||
|
|
||||||
def is_a_rel_aggregates(self, class_name):
|
def is_a_rel_aggregates(self, class_name):
|
||||||
return class_name == 'IfcRelAggregates'
|
return class_name == 'IfcRelAggregates'
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ class IfcImporter():
|
|||||||
return
|
return
|
||||||
related_type = element.IsTypedBy[0].RelatingType
|
related_type = element.IsTypedBy[0].RelatingType
|
||||||
if related_type:
|
if related_type:
|
||||||
obj.BIMObjectProperties.type_product = self.type_products[related_type.GlobalId]
|
obj.BIMObjectProperties.relating_type = self.type_products[related_type.GlobalId]
|
||||||
|
|
||||||
def load_diff(self):
|
def load_diff(self):
|
||||||
if not self.ifc_import_settings.diff_file:
|
if not self.ifc_import_settings.diff_file:
|
||||||
|
|||||||
@@ -479,7 +479,8 @@ class BoundaryCondition(PropertyGroup):
|
|||||||
class BIMObjectProperties(PropertyGroup):
|
class BIMObjectProperties(PropertyGroup):
|
||||||
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
||||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||||
type_product: PointerProperty(name='Type Product', type=bpy.types.Object)
|
relating_type: PointerProperty(name='Type Product', type=bpy.types.Object)
|
||||||
|
relating_structure: PointerProperty(name='Spatial Container', type=bpy.types.Object)
|
||||||
psets: CollectionProperty(name="Psets", type=Pset)
|
psets: CollectionProperty(name="Psets", type=Pset)
|
||||||
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
|
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
|
||||||
documents: CollectionProperty(name="Documents", type=Document)
|
documents: CollectionProperty(name="Documents", type=Document)
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ class BIM_PT_object(Panel):
|
|||||||
row.prop(props, 'attributes')
|
row.prop(props, 'attributes')
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, 'type_product')
|
row.prop(props, 'relating_type')
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(props, 'relating_structure')
|
||||||
|
|
||||||
layout.label(text="Property Sets:")
|
layout.label(text="Property Sets:")
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|||||||
Reference in New Issue
Block a user