mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 19:49:58 +00:00
WIP code cleanup and deprecate legacy product import. Finally! See #1222.
This commit is contained in:
@@ -190,10 +190,6 @@ if bpy is not None:
|
|||||||
prop.StrProperty,
|
prop.StrProperty,
|
||||||
prop.Attribute,
|
prop.Attribute,
|
||||||
prop.Variable,
|
prop.Variable,
|
||||||
prop.Role,
|
|
||||||
prop.Address,
|
|
||||||
prop.Person,
|
|
||||||
prop.Organisation,
|
|
||||||
prop.Classification,
|
prop.Classification,
|
||||||
prop.ClassificationReference,
|
prop.ClassificationReference,
|
||||||
prop.ClassificationView,
|
prop.ClassificationView,
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class MaterialCreator:
|
|||||||
item_id = self.mesh.BIMMeshProperties.ifc_item_ids.add()
|
item_id = self.mesh.BIMMeshProperties.ifc_item_ids.add()
|
||||||
item_id.name = str(item.id())
|
item_id.name = str(item.id())
|
||||||
|
|
||||||
styled_item = item.StyledByItem[0] # Cardinality is S[0:1]
|
styled_item = item.StyledByItem[0] # Cardinality is S[0:1]
|
||||||
style_name = self.get_surface_style_name(styled_item)
|
style_name = self.get_surface_style_name(styled_item)
|
||||||
|
|
||||||
if not style_name:
|
if not style_name:
|
||||||
@@ -130,7 +130,9 @@ class MaterialCreator:
|
|||||||
material_to_slot[i] = slot_index
|
material_to_slot[i] = slot_index
|
||||||
|
|
||||||
if len(self.mesh.polygons) == len(self.mesh["ios_material_ids"]):
|
if len(self.mesh.polygons) == len(self.mesh["ios_material_ids"]):
|
||||||
material_index = [(material_to_slot[mat_id] if mat_id != -1 else 0) for mat_id in self.mesh["ios_material_ids"]]
|
material_index = [
|
||||||
|
(material_to_slot[mat_id] if mat_id != -1 else 0) for mat_id in self.mesh["ios_material_ids"]
|
||||||
|
]
|
||||||
self.mesh.polygons.foreach_set("material_index", material_index)
|
self.mesh.polygons.foreach_set("material_index", material_index)
|
||||||
|
|
||||||
def canonicalise_material_name(self, name):
|
def canonicalise_material_name(self, name):
|
||||||
@@ -225,7 +227,7 @@ class MaterialCreator:
|
|||||||
if style.Name:
|
if style.Name:
|
||||||
return style.Name
|
return style.Name
|
||||||
return str(style.id())
|
return str(style.id())
|
||||||
return None # We only support surface styles right now
|
return None # We only support surface styles right now
|
||||||
|
|
||||||
def parse_styled_item(self, styled_item, material):
|
def parse_styled_item(self, styled_item, material):
|
||||||
styles = self.get_styled_item_styles(styled_item)
|
styles = self.get_styled_item_styles(styled_item)
|
||||||
@@ -378,12 +380,8 @@ class IfcImporter:
|
|||||||
if self.ifc_import_settings.should_import_native:
|
if self.ifc_import_settings.should_import_native:
|
||||||
self.create_native_products()
|
self.create_native_products()
|
||||||
self.profile_code("Creating native products")
|
self.profile_code("Creating native products")
|
||||||
# TODO: Deprecate after bug #682 is fixed and the new importer is stable
|
self.create_products()
|
||||||
if self.ifc_import_settings.should_use_legacy:
|
self.profile_code("Creating meshified products")
|
||||||
self.create_products_legacy()
|
|
||||||
else:
|
|
||||||
self.create_products()
|
|
||||||
self.profile_code("Creating meshified products")
|
|
||||||
self.relate_openings()
|
self.relate_openings()
|
||||||
self.profile_code("Relating openings")
|
self.profile_code("Relating openings")
|
||||||
self.place_objects_in_spatial_tree()
|
self.place_objects_in_spatial_tree()
|
||||||
@@ -756,11 +754,6 @@ class IfcImporter:
|
|||||||
):
|
):
|
||||||
return representation_map
|
return representation_map
|
||||||
|
|
||||||
def create_products_legacy(self):
|
|
||||||
elements = self.file.by_type("IfcElement") + self.file.by_type("IfcSpace")
|
|
||||||
for element in elements:
|
|
||||||
self.create_product_legacy(element)
|
|
||||||
|
|
||||||
def create_native_products(self):
|
def create_native_products(self):
|
||||||
if not self.native_elements:
|
if not self.native_elements:
|
||||||
return
|
return
|
||||||
@@ -1228,7 +1221,7 @@ class IfcImporter:
|
|||||||
obj = self.added_data[product.GlobalId]
|
obj = self.added_data[product.GlobalId]
|
||||||
obj.data.BIMMeshProperties.presentation_layer_index = layer_index
|
obj.data.BIMMeshProperties.presentation_layer_index = layer_index
|
||||||
except:
|
except:
|
||||||
pass # Occurs for example in opening elements or exclusions
|
pass # Occurs for example in opening elements or exclusions
|
||||||
|
|
||||||
def clean_mesh(self):
|
def clean_mesh(self):
|
||||||
obj = None
|
obj = None
|
||||||
@@ -1247,34 +1240,6 @@ class IfcImporter:
|
|||||||
bpy.ops.mesh.normals_make_consistent(context_override)
|
bpy.ops.mesh.normals_make_consistent(context_override)
|
||||||
bpy.ops.object.editmode_toggle(context_override)
|
bpy.ops.object.editmode_toggle(context_override)
|
||||||
|
|
||||||
def add_pset(self, pset, props):
|
|
||||||
new_pset = props.psets.add()
|
|
||||||
new_pset.name = pset.Name
|
|
||||||
pset_template = schema.ifc.psetqto.get_by_name(new_pset.name)
|
|
||||||
if pset_template:
|
|
||||||
for prop_name in (p.Name for p in pset_template.HasPropertyTemplates):
|
|
||||||
prop = new_pset.properties.add()
|
|
||||||
prop.name = prop_name
|
|
||||||
try:
|
|
||||||
if hasattr(pset, "HasProperties"):
|
|
||||||
props = pset.HasProperties
|
|
||||||
elif hasattr(pset, "Properties"):
|
|
||||||
props = pset.Properties
|
|
||||||
except:
|
|
||||||
return # I've seen ArchiCAD produce invalid IFCs with empty data
|
|
||||||
# Invalid IFC, but some vendors like Solidworks do this so we accomodate it
|
|
||||||
if not props:
|
|
||||||
return
|
|
||||||
for prop in props:
|
|
||||||
if prop.is_a("IfcPropertySingleValue") and prop.NominalValue:
|
|
||||||
index = new_pset.properties.find(prop.Name)
|
|
||||||
if index >= 0:
|
|
||||||
new_pset.properties[index].string_value = str(prop.NominalValue.wrappedValue)
|
|
||||||
else:
|
|
||||||
new_prop = new_pset.properties.add()
|
|
||||||
new_prop.name = prop.Name
|
|
||||||
new_prop.string_value = str(prop.NominalValue.wrappedValue)
|
|
||||||
|
|
||||||
def add_opening_relation(self, element, obj):
|
def add_opening_relation(self, element, obj):
|
||||||
if not element.is_a("IfcOpeningElement"):
|
if not element.is_a("IfcOpeningElement"):
|
||||||
return
|
return
|
||||||
@@ -1592,46 +1557,6 @@ class IfcImporter:
|
|||||||
objects_to_purge.append(obj)
|
objects_to_purge.append(obj)
|
||||||
bpy.ops.object.delete({"selected_objects": objects_to_purge})
|
bpy.ops.object.delete({"selected_objects": objects_to_purge})
|
||||||
|
|
||||||
def create_product_legacy(self, element):
|
|
||||||
if (
|
|
||||||
self.diff
|
|
||||||
and element.GlobalId not in self.diff["added"]
|
|
||||||
and element.GlobalId not in self.diff["changed"].keys()
|
|
||||||
):
|
|
||||||
return
|
|
||||||
|
|
||||||
self.ifc_import_settings.logger.info("Creating object %s", element)
|
|
||||||
self.time = time.time()
|
|
||||||
if element.is_a("IfcOpeningElement"):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
representation_id = self.get_representation_id(element)
|
|
||||||
|
|
||||||
mesh_name = "mesh-{}".format(representation_id)
|
|
||||||
mesh = self.meshes.get(mesh_name)
|
|
||||||
if mesh is None or representation_id is None:
|
|
||||||
shape = ifcopenshell.geom.create_shape(self.settings, element)
|
|
||||||
self.ifc_import_settings.logger.info("Shape was generated in %.2f", time.time() - self.time)
|
|
||||||
self.time = time.time()
|
|
||||||
|
|
||||||
mesh = self.create_mesh(element, shape)
|
|
||||||
self.meshes[mesh_name] = mesh
|
|
||||||
self.mesh_shapes[mesh_name] = shape
|
|
||||||
else:
|
|
||||||
self.ifc_import_settings.logger.info("Mesh reused.")
|
|
||||||
except:
|
|
||||||
self.ifc_import_settings.logger.error("Failed to generate shape for %s", element)
|
|
||||||
return
|
|
||||||
|
|
||||||
obj = bpy.data.objects.new(self.get_name(element), mesh)
|
|
||||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
|
||||||
self.material_creator.create(element, obj, mesh)
|
|
||||||
obj.matrix_world = self.get_element_matrix(element, mesh_name)
|
|
||||||
self.add_element_classifications(element, obj)
|
|
||||||
self.add_element_document_relations(element, obj)
|
|
||||||
self.added_data[element.GlobalId] = obj
|
|
||||||
|
|
||||||
def add_element_document_relations(self, element, obj):
|
def add_element_document_relations(self, element, obj):
|
||||||
for association in element.HasAssociations:
|
for association in element.HasAssociations:
|
||||||
if association.is_a("IfcRelAssociatesDocument"):
|
if association.is_a("IfcRelAssociatesDocument"):
|
||||||
@@ -1672,7 +1597,7 @@ class IfcImporter:
|
|||||||
return self.place_object_in_spatial_tree(container, obj)
|
return self.place_object_in_spatial_tree(container, obj)
|
||||||
elif element.is_a("IfcGrid"):
|
elif element.is_a("IfcGrid"):
|
||||||
grid_collection = bpy.data.collections.get(obj.name)
|
grid_collection = bpy.data.collections.get(obj.name)
|
||||||
if grid_collection: # Just in case we ran into invalid grids from Revit
|
if grid_collection: # Just in case we ran into invalid grids from Revit
|
||||||
self.spatial_structure_elements[container.GlobalId]["blender"].children.link(grid_collection)
|
self.spatial_structure_elements[container.GlobalId]["blender"].children.link(grid_collection)
|
||||||
grid_collection.objects.link(obj)
|
grid_collection.objects.link(obj)
|
||||||
else:
|
else:
|
||||||
@@ -2009,7 +1934,6 @@ class IfcImportSettings:
|
|||||||
self.should_use_cpu_multiprocessing = False
|
self.should_use_cpu_multiprocessing = False
|
||||||
self.should_import_with_profiling = False
|
self.should_import_with_profiling = False
|
||||||
self.should_import_native = False
|
self.should_import_native = False
|
||||||
self.should_use_legacy = False
|
|
||||||
self.should_merge_aggregates = False
|
self.should_merge_aggregates = False
|
||||||
self.should_merge_by_class = False
|
self.should_merge_by_class = False
|
||||||
self.should_merge_by_material = False
|
self.should_merge_by_material = False
|
||||||
@@ -2039,7 +1963,6 @@ class IfcImportSettings:
|
|||||||
settings.should_import_with_profiling = scene_bim.import_should_import_with_profiling
|
settings.should_import_with_profiling = scene_bim.import_should_import_with_profiling
|
||||||
settings.should_import_native = scene_bim.import_should_import_native
|
settings.should_import_native = scene_bim.import_should_import_native
|
||||||
settings.should_roundtrip_native = scene_bim.import_export_should_roundtrip_native
|
settings.should_roundtrip_native = scene_bim.import_export_should_roundtrip_native
|
||||||
settings.should_use_legacy = scene_bim.import_should_use_legacy
|
|
||||||
settings.should_import_aggregates = scene_bim.import_should_import_aggregates
|
settings.should_import_aggregates = scene_bim.import_should_import_aggregates
|
||||||
settings.should_merge_aggregates = scene_bim.import_should_merge_aggregates
|
settings.should_merge_aggregates = scene_bim.import_should_merge_aggregates
|
||||||
settings.should_merge_by_class = scene_bim.import_should_merge_by_class
|
settings.should_merge_by_class = scene_bim.import_should_merge_by_class
|
||||||
|
|||||||
@@ -946,86 +946,6 @@ class PropertyTemplate(PropertyGroup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Address(PropertyGroup):
|
|
||||||
name: StringProperty(name="Name", default="IfcPostalAddress") # Stores IfcPostalAddress or IfcTelecomAddress
|
|
||||||
purpose: EnumProperty(
|
|
||||||
items=[
|
|
||||||
("None", "None", ""),
|
|
||||||
("OFFICE", "OFFICE", "An office address."),
|
|
||||||
("SITE", "SITE", "A site address."),
|
|
||||||
("HOME", "HOME", "A home address."),
|
|
||||||
("DISTRIBUTIONPOINT", "DISTRIBUTIONPOINT", "A postal distribution point address."),
|
|
||||||
("USERDEFINED", "USERDEFINED", "A user defined address type to be provided."),
|
|
||||||
],
|
|
||||||
name="Purpose",
|
|
||||||
)
|
|
||||||
description: StringProperty(name="Description")
|
|
||||||
user_defined_purpose: StringProperty(name="Custom Purpose")
|
|
||||||
|
|
||||||
internal_location: StringProperty(name="Internal Location")
|
|
||||||
address_lines: StringProperty(name="Address")
|
|
||||||
postal_box: StringProperty(name="Postal Box")
|
|
||||||
town: StringProperty(name="Town")
|
|
||||||
region: StringProperty(name="Region")
|
|
||||||
postal_code: StringProperty(name="Postal Code")
|
|
||||||
country: StringProperty(name="Country")
|
|
||||||
|
|
||||||
telephone_numbers: StringProperty(name="Telephone Numbers")
|
|
||||||
facsimile_numbers: StringProperty(name="Facsimile Numbers")
|
|
||||||
pager_number: StringProperty(name="Pager Number")
|
|
||||||
electronic_mail_addresses: StringProperty(name="Emails")
|
|
||||||
www_home_page_url: StringProperty(name="Websites")
|
|
||||||
messaging_ids: StringProperty(name="IMs")
|
|
||||||
|
|
||||||
|
|
||||||
class Role(PropertyGroup):
|
|
||||||
name: EnumProperty(
|
|
||||||
items=[
|
|
||||||
("SUPPLIER", "SUPPLIER", ""),
|
|
||||||
("MANUFACTURER", "MANUFACTURER", ""),
|
|
||||||
("CONTRACTOR", "CONTRACTOR", ""),
|
|
||||||
("SUBCONTRACTOR", "SUBCONTRACTOR", ""),
|
|
||||||
("ARCHITECT", "ARCHITECT", ""),
|
|
||||||
("STRUCTURALENGINEER", "STRUCTURALENGINEER", ""),
|
|
||||||
("COSTENGINEER", "COSTENGINEER", ""),
|
|
||||||
("CLIENT", "CLIENT", ""),
|
|
||||||
("BUILDINGOWNER", "BUILDINGOWNER", ""),
|
|
||||||
("BUILDINGOPERATOR", "BUILDINGOPERATOR", ""),
|
|
||||||
("MECHANICALENGINEER", "MECHANICALENGINEER", ""),
|
|
||||||
("ELECTRICALENGINEER", "ELECTRICALENGINEER", ""),
|
|
||||||
("PROJECTMANAGER", "PROJECTMANAGER", ""),
|
|
||||||
("FACILITIESMANAGER", "FACILITIESMANAGER", ""),
|
|
||||||
("CIVILENGINEER", "CIVILENGINEER", ""),
|
|
||||||
("COMMISSIONINGENGINEER", "COMMISSIONINGENGINEER", ""),
|
|
||||||
("ENGINEER", "ENGINEER", ""),
|
|
||||||
("OWNER", "OWNER", ""),
|
|
||||||
("CONSULTANT", "CONSULTANT", ""),
|
|
||||||
("CONSTRUCTIONMANAGER", "CONSTRUCTIONMANAGER", ""),
|
|
||||||
("FIELDCONSTRUCTIONMANAGER", "FIELDCONSTRUCTIONMANAGER", ""),
|
|
||||||
("RESELLER", "RESELLER", ""),
|
|
||||||
("USERDEFINED", "USERDEFINED", ""),
|
|
||||||
],
|
|
||||||
name="Name",
|
|
||||||
)
|
|
||||||
user_defined_role: StringProperty(name="Custom Role")
|
|
||||||
description: StringProperty(name="Description")
|
|
||||||
|
|
||||||
|
|
||||||
class Organisation(PropertyGroup):
|
|
||||||
identification: StringProperty(name="Identification")
|
|
||||||
name: StringProperty(name="Name")
|
|
||||||
description: StringProperty(name="Description")
|
|
||||||
|
|
||||||
|
|
||||||
class Person(PropertyGroup):
|
|
||||||
name: StringProperty(name="Identification")
|
|
||||||
family_name: StringProperty(name="Family Name")
|
|
||||||
given_name: StringProperty(name="Given Name")
|
|
||||||
middle_names: StringProperty(name="Middle Names")
|
|
||||||
prefix_titles: StringProperty(name="Prefixes")
|
|
||||||
suffix_titles: StringProperty(name="Suffixes")
|
|
||||||
|
|
||||||
|
|
||||||
class Classification(PropertyGroup):
|
class Classification(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
source: StringProperty(name="Source")
|
source: StringProperty(name="Source")
|
||||||
@@ -1125,7 +1045,6 @@ class BIMProperties(PropertyGroup):
|
|||||||
import_should_import_opening_elements: BoolProperty(name="Import Opening Elements", default=False)
|
import_should_import_opening_elements: BoolProperty(name="Import Opening Elements", default=False)
|
||||||
import_should_import_spaces: BoolProperty(name="Import Spaces", default=False)
|
import_should_import_spaces: BoolProperty(name="Import Spaces", default=False)
|
||||||
import_should_auto_set_workarounds: BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
|
import_should_auto_set_workarounds: BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
|
||||||
import_should_use_legacy: BoolProperty(name="Import with Legacy Importer", default=False)
|
|
||||||
import_should_import_native: BoolProperty(name="Import Native Representations", default=False)
|
import_should_import_native: BoolProperty(name="Import Native Representations", default=False)
|
||||||
import_export_should_roundtrip_native: BoolProperty(name="Roundtrip Native Representations", default=True)
|
import_export_should_roundtrip_native: BoolProperty(name="Roundtrip Native Representations", default=True)
|
||||||
import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=True)
|
import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=True)
|
||||||
@@ -1142,14 +1061,7 @@ class BIMProperties(PropertyGroup):
|
|||||||
import_should_offset_model: BoolProperty(name="Import and Offset Model", default=False)
|
import_should_offset_model: BoolProperty(name="Import and Offset Model", default=False)
|
||||||
import_model_offset_coordinates: StringProperty(name="Model Offset Coordinates", default="0,0,0")
|
import_model_offset_coordinates: StringProperty(name="Model Offset Coordinates", default="0,0,0")
|
||||||
|
|
||||||
person: PointerProperty(type=Person)
|
# TODO: move into owner module
|
||||||
active_person_id: IntProperty(name="Active Person Id")
|
|
||||||
organisation: PointerProperty(type=Organisation)
|
|
||||||
active_organisation_id: IntProperty(name="Active Organisation Id")
|
|
||||||
role: PointerProperty(type=Role)
|
|
||||||
active_role_id: IntProperty(name="Active Role Id")
|
|
||||||
address: PointerProperty(type=Address)
|
|
||||||
active_address_id: IntProperty(name="Active Address Id")
|
|
||||||
user_person: EnumProperty(items=getPersons, name="Person")
|
user_person: EnumProperty(items=getPersons, name="Person")
|
||||||
user_organisation: EnumProperty(items=getOrganisations, name="Organisation")
|
user_organisation: EnumProperty(items=getOrganisations, name="Organisation")
|
||||||
|
|
||||||
@@ -1319,8 +1231,6 @@ class BIMObjectProperties(PropertyGroup):
|
|||||||
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
||||||
boundary_condition: PointerProperty(name="Boundary Condition", type=BoundaryCondition)
|
boundary_condition: PointerProperty(name="Boundary Condition", type=BoundaryCondition)
|
||||||
structural_member_connection: PointerProperty(name="Structural Member Connection", type=bpy.types.Object)
|
structural_member_connection: PointerProperty(name="Structural Member Connection", type=bpy.types.Object)
|
||||||
# Address applies to IfcSite's SiteAddress and IfcBuilding's BuildingAddress
|
|
||||||
address: PointerProperty(name="Address", type=Address)
|
|
||||||
|
|
||||||
|
|
||||||
class BIMMaterialProperties(PropertyGroup):
|
class BIMMaterialProperties(PropertyGroup):
|
||||||
|
|||||||
@@ -963,8 +963,6 @@ class BIM_PT_mvd(Panel):
|
|||||||
|
|
||||||
layout.label(text="Experimental Modes:")
|
layout.label(text="Experimental Modes:")
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_use_legacy")
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(bim_properties, "import_should_import_native")
|
row.prop(bim_properties, "import_should_import_native")
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|||||||
Reference in New Issue
Block a user