mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 10:23:41 +00:00
WIP merge MVDs into geometry workarounds UI. Cleaner, more usable import / export UI. Remove obsoleted MVD options. See #1222.
This commit is contained in:
@@ -188,7 +188,6 @@ if bpy is not None:
|
|||||||
ui.BIM_PT_library,
|
ui.BIM_PT_library,
|
||||||
ui.BIM_PT_presentation_layers,
|
ui.BIM_PT_presentation_layers,
|
||||||
ui.BIM_PT_patch,
|
ui.BIM_PT_patch,
|
||||||
ui.BIM_PT_mvd,
|
|
||||||
ui.BIM_PT_presentation_layer_data,
|
ui.BIM_PT_presentation_layer_data,
|
||||||
ui.BIM_PT_object_structural,
|
ui.BIM_PT_object_structural,
|
||||||
ui.BIM_PT_camera,
|
ui.BIM_PT_camera,
|
||||||
|
|||||||
@@ -93,6 +93,4 @@ class IfcExportSettings:
|
|||||||
settings = IfcExportSettings()
|
settings = IfcExportSettings()
|
||||||
settings.output_file = output_file
|
settings.output_file = output_file
|
||||||
settings.logger = logger
|
settings.logger = logger
|
||||||
settings.json_version = scene_bim.export_json_version
|
|
||||||
settings.json_compact = scene_bim.export_json_compact
|
|
||||||
return settings
|
return settings
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ class MaterialCreator:
|
|||||||
hasattr(element, "RepresentationMaps") and not element.RepresentationMaps
|
hasattr(element, "RepresentationMaps") and not element.RepresentationMaps
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
if not self.mesh:
|
if not self.mesh or self.mesh.name in self.parsed_meshes:
|
||||||
return
|
|
||||||
if self.mesh.name in self.parsed_meshes:
|
|
||||||
return
|
return
|
||||||
self.parsed_meshes.add(self.mesh.name)
|
self.parsed_meshes.add(self.mesh.name)
|
||||||
if self.parse_representations(element):
|
if self.parse_representations(element):
|
||||||
@@ -97,10 +95,9 @@ class MaterialCreator:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
style = bpy.data.materials.get(style_name)
|
style = bpy.data.materials.get(style_name)
|
||||||
|
|
||||||
if not style:
|
if not style:
|
||||||
style = bpy.data.materials.new(style_name)
|
style = bpy.data.materials.new(style_name)
|
||||||
self.parse_styled_item(styled_item, style)
|
self.parse_styled_item(styled_item, style)
|
||||||
|
|
||||||
self.assign_style_to_mesh(style)
|
self.assign_style_to_mesh(style)
|
||||||
item_id.slot_index = len(self.mesh.materials) - 1
|
item_id.slot_index = len(self.mesh.materials) - 1
|
||||||
@@ -312,8 +309,6 @@ class IfcImporter:
|
|||||||
self.material_creator = MaterialCreator(ifc_import_settings, self)
|
self.material_creator = MaterialCreator(ifc_import_settings, self)
|
||||||
|
|
||||||
def profile_code(self, message):
|
def profile_code(self, message):
|
||||||
if not self.ifc_import_settings.should_import_with_profiling:
|
|
||||||
return
|
|
||||||
if not self.time:
|
if not self.time:
|
||||||
self.time = time.time()
|
self.time = time.time()
|
||||||
print("{} :: {:.2f}".format(message, time.time() - self.time))
|
print("{} :: {:.2f}".format(message, time.time() - self.time))
|
||||||
@@ -352,14 +347,14 @@ class IfcImporter:
|
|||||||
self.profile_code("Create opening collection")
|
self.profile_code("Create opening collection")
|
||||||
self.process_element_filter()
|
self.process_element_filter()
|
||||||
self.profile_code("Process element filter")
|
self.profile_code("Process element filter")
|
||||||
if self.ifc_import_settings.should_import_native:
|
# TODO: Deprecate
|
||||||
self.parse_native_elements()
|
#self.parse_native_elements()
|
||||||
self.profile_code("Parsing native elements")
|
#self.profile_code("Parsing native elements")
|
||||||
self.create_grids()
|
self.create_grids()
|
||||||
self.profile_code("Creating grids")
|
self.profile_code("Creating grids")
|
||||||
if self.ifc_import_settings.should_import_native:
|
# TODO: Deprecate
|
||||||
self.create_native_products()
|
#self.create_native_products()
|
||||||
self.profile_code("Creating native products")
|
#self.profile_code("Creating native products")
|
||||||
self.create_products()
|
self.create_products()
|
||||||
self.profile_code("Creating meshified products")
|
self.profile_code("Creating meshified products")
|
||||||
self.relate_openings()
|
self.relate_openings()
|
||||||
@@ -1574,20 +1569,24 @@ class IfcImportSettings:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.logger = None
|
self.logger = None
|
||||||
self.input_file = None
|
self.input_file = None
|
||||||
self.should_auto_set_workarounds = True
|
|
||||||
self.should_ignore_site_coordinates = False
|
|
||||||
self.should_ignore_building_coordinates = False
|
|
||||||
self.should_merge_materials_by_colour = False
|
|
||||||
self.should_import_type_representations = False
|
|
||||||
self.should_import_curves = False
|
|
||||||
self.should_import_spaces = False
|
|
||||||
self.should_use_cpu_multiprocessing = False
|
|
||||||
self.should_import_with_profiling = False
|
|
||||||
self.should_import_native = False
|
|
||||||
self.should_merge_by_class = False
|
|
||||||
self.should_merge_by_material = False
|
|
||||||
self.should_clean_mesh = True
|
|
||||||
self.diff_file = None
|
self.diff_file = None
|
||||||
|
self.should_import_type_representations: False
|
||||||
|
self.should_import_curves: False
|
||||||
|
self.should_import_spaces: False
|
||||||
|
self.should_auto_set_workarounds: True
|
||||||
|
self.should_use_cpu_multiprocessing: True
|
||||||
|
self.should_merge_by_class: False
|
||||||
|
self.should_merge_by_material: False
|
||||||
|
self.should_merge_materials_by_colour: False
|
||||||
|
self.should_clean_mesh: True
|
||||||
|
self.deflection_tolerance: 0.001
|
||||||
|
self.angular_tolerance: 0.5
|
||||||
|
self.should_allow_non_element_aggregates: False
|
||||||
|
self.should_offset_model: False
|
||||||
|
self.model_offset_coordinates: (0, 0, 0)
|
||||||
|
self.ifc_import_filter: "NONE"
|
||||||
|
self.ifc_selector: ""
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory(context, input_file, logger):
|
def factory(context, input_file, logger):
|
||||||
@@ -1597,27 +1596,4 @@ class IfcImportSettings:
|
|||||||
settings.input_file = input_file
|
settings.input_file = input_file
|
||||||
settings.logger = logger
|
settings.logger = logger
|
||||||
settings.diff_file = scene_diff.diff_json_file
|
settings.diff_file = scene_diff.diff_json_file
|
||||||
settings.ifc_import_filter = scene_bim.ifc_import_filter
|
|
||||||
settings.ifc_selector = scene_bim.ifc_selector
|
|
||||||
settings.should_import_type_representations = scene_bim.import_should_import_type_representations
|
|
||||||
settings.should_import_curves = scene_bim.import_should_import_curves
|
|
||||||
settings.should_import_spaces = scene_bim.import_should_import_spaces
|
|
||||||
settings.should_auto_set_workarounds = scene_bim.import_should_auto_set_workarounds
|
|
||||||
settings.should_use_cpu_multiprocessing = scene_bim.import_should_use_cpu_multiprocessing
|
|
||||||
settings.should_import_with_profiling = scene_bim.import_should_import_with_profiling
|
|
||||||
settings.should_import_native = scene_bim.import_should_import_native
|
|
||||||
settings.should_roundtrip_native = scene_bim.import_export_should_roundtrip_native
|
|
||||||
settings.should_merge_by_class = scene_bim.import_should_merge_by_class
|
|
||||||
settings.should_merge_by_material = scene_bim.import_should_merge_by_material
|
|
||||||
settings.should_merge_materials_by_colour = scene_bim.import_should_merge_materials_by_colour
|
|
||||||
settings.should_clean_mesh = scene_bim.import_should_clean_mesh
|
|
||||||
settings.should_allow_non_element_aggregates = scene_bim.import_should_allow_non_element_aggregates
|
|
||||||
settings.should_offset_model = scene_bim.import_should_offset_model
|
|
||||||
settings.model_offset_coordinates = (
|
|
||||||
[float(o) for o in scene_bim.import_model_offset_coordinates.split(",")]
|
|
||||||
if scene_bim.import_model_offset_coordinates
|
|
||||||
else (0, 0, 0)
|
|
||||||
)
|
|
||||||
settings.deflection_tolerance = scene_bim.import_deflection_tolerance
|
|
||||||
settings.angular_tolerance = scene_bim.import_angular_tolerance
|
|
||||||
return settings
|
return settings
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ def register():
|
|||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
del bpy.types.Scene.BIMConstraintProperties
|
del bpy.types.Scene.BIMConstraintProperties
|
||||||
del bpy.types.Scene.BIMObjectConstraintProperties
|
del bpy.types.Object.BIMObjectConstraintProperties
|
||||||
|
|||||||
@@ -33,4 +33,4 @@ def register():
|
|||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
del bpy.types.Scene.BIMDocumentProperties
|
del bpy.types.Scene.BIMDocumentProperties
|
||||||
del bpy.types.Scene.BIMObjectDocumentProperties
|
del bpy.types.Object.BIMObjectDocumentProperties
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from . import ui, operator
|
from . import ui, prop, operator
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.EditObjectPlacement,
|
operator.EditObjectPlacement,
|
||||||
@@ -9,14 +9,18 @@ classes = (
|
|||||||
operator.UpdateMeshRepresentation,
|
operator.UpdateMeshRepresentation,
|
||||||
operator.UpdateParametricRepresentation,
|
operator.UpdateParametricRepresentation,
|
||||||
operator.GetRepresentationIfcParameters,
|
operator.GetRepresentationIfcParameters,
|
||||||
|
prop.BIMGeometryProperties,
|
||||||
ui.BIM_PT_representations,
|
ui.BIM_PT_representations,
|
||||||
ui.BIM_PT_mesh,
|
ui.BIM_PT_mesh,
|
||||||
|
ui.BIM_PT_workarounds,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
bpy.types.Scene.BIMGeometryProperties = bpy.props.PointerProperty(type=prop.BIMGeometryProperties)
|
||||||
bpy.types.OBJECT_PT_transform.append(ui.BIM_PT_transform)
|
bpy.types.OBJECT_PT_transform.append(ui.BIM_PT_transform)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.types.OBJECT_PT_transform.remove(ui.BIM_PT_transform)
|
bpy.types.OBJECT_PT_transform.remove(ui.BIM_PT_transform)
|
||||||
|
del bpy.types.Scene.BIMGeometryProperties
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
|
||||||
|
|
||||||
@@ -7,10 +9,12 @@ class Usecase:
|
|||||||
self.file = file
|
self.file = file
|
||||||
self.settings = {
|
self.settings = {
|
||||||
"context": None, # IfcGeometricRepresentationContext
|
"context": None, # IfcGeometricRepresentationContext
|
||||||
|
"blender_object": None, # This is (currently) a Blender object, hence this depends on Blender now
|
||||||
"geometry": None, # This is (currently) a Blender data object, hence this depends on Blender now
|
"geometry": None, # This is (currently) a Blender data object, hence this depends on Blender now
|
||||||
"total_items": 1, # How many representation items to create
|
"total_items": 1, # How many representation items to create
|
||||||
"unit_scale": None, # A scale factor to apply for all vectors in case the unit is different
|
"unit_scale": None, # A scale factor to apply for all vectors in case the unit is different
|
||||||
"should_force_faceted_brep": False, # If we should force faceted breps for meshes
|
"should_force_faceted_brep": False, # If we should force faceted breps for meshes
|
||||||
|
"should_force_triangulation": False, # If we should force triangulation for meshes
|
||||||
"is_wireframe": False, # If the geometry is a wireframe
|
"is_wireframe": False, # If the geometry is a wireframe
|
||||||
"is_curve": False, # If the geometry is a Blender curve
|
"is_curve": False, # If the geometry is a Blender curve
|
||||||
"is_point_cloud": False, # If the geometry is a point cloud
|
"is_point_cloud": False, # If the geometry is a point cloud
|
||||||
@@ -20,6 +24,7 @@ class Usecase:
|
|||||||
self.settings[key] = value
|
self.settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
|
self.evaluate_geometry()
|
||||||
if self.settings["unit_scale"] is None:
|
if self.settings["unit_scale"] is None:
|
||||||
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||||
if self.settings["context"].ContextType == "Model":
|
if self.settings["context"].ContextType == "Model":
|
||||||
@@ -28,6 +33,34 @@ class Usecase:
|
|||||||
return self.create_plan_representation()
|
return self.create_plan_representation()
|
||||||
return self.create_variable_representation()
|
return self.create_variable_representation()
|
||||||
|
|
||||||
|
def evaluate_geometry(self):
|
||||||
|
self.boolean_modifiers = []
|
||||||
|
for modifier in self.settings["blender_object"].modifiers:
|
||||||
|
if not modifier.type == "BOOLEAN":
|
||||||
|
continue
|
||||||
|
modifier_data = {}
|
||||||
|
for name in ["operation", "operand_type", "object", "solver", "use_self"]:
|
||||||
|
modifier_data[name] = getattr(modifier, name)
|
||||||
|
self.boolean_modifiers.append(modifier_data)
|
||||||
|
self.settings["blender_object"].modifiers.remove(modifier)
|
||||||
|
|
||||||
|
if self.settings["should_force_triangulation"]:
|
||||||
|
mesh = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_mesh(mesh)
|
||||||
|
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
||||||
|
del bm
|
||||||
|
self.settings["geometry"] = mesh
|
||||||
|
else:
|
||||||
|
self.settings["geometry"] = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||||
|
|
||||||
|
for modifier in self.boolean_modifiers:
|
||||||
|
new = self.settings["blender_object"].modifiers.new("IfcOpeningElement", "BOOLEAN")
|
||||||
|
for key, value in modifier.items():
|
||||||
|
setattr(new, key, value)
|
||||||
|
|
||||||
def create_model_representation(self):
|
def create_model_representation(self):
|
||||||
if self.settings["context"].is_a() == "IfcGeometricRepresentationContext":
|
if self.settings["context"].is_a() == "IfcGeometricRepresentationContext":
|
||||||
return self.create_variable_representation()
|
return self.create_variable_representation()
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ class Usecase:
|
|||||||
ifcopenshell.util.element.replace_attribute(
|
ifcopenshell.util.element.replace_attribute(
|
||||||
inverse, self.settings["product"].ObjectPlacement, placement
|
inverse, self.settings["product"].ObjectPlacement, placement
|
||||||
)
|
)
|
||||||
self.file.remove(self.settings["product"].ObjectPlacement)
|
old = self.settings["product"].ObjectPlacement
|
||||||
|
self.settings["product"].ObjectPlacement = None
|
||||||
|
if not self.file.get_inverse(old):
|
||||||
|
ifcopenshell.util.element.remove_deep(self.file, old)
|
||||||
self.settings["product"].ObjectPlacement = placement
|
self.settings["product"].ObjectPlacement = placement
|
||||||
|
|
||||||
for settings in dependent_objects:
|
for settings in dependent_objects:
|
||||||
|
|||||||
@@ -76,8 +76,11 @@ class AddRepresentation(bpy.types.Operator):
|
|||||||
self.file,
|
self.file,
|
||||||
{
|
{
|
||||||
"context": self.file.by_id(context_id),
|
"context": self.file.by_id(context_id),
|
||||||
|
"blender_object": obj,
|
||||||
"geometry": obj.data,
|
"geometry": obj.data,
|
||||||
"total_items": max(1, len(obj.material_slots)),
|
"total_items": max(1, len(obj.material_slots)),
|
||||||
|
"should_force_faceted_brep": context.scene.BIMGeometryProperties.should_force_faceted_brep,
|
||||||
|
"should_force_triangulation": context.scene.BIMGeometryProperties.should_force_triangulation
|
||||||
},
|
},
|
||||||
).execute()
|
).execute()
|
||||||
if not result:
|
if not result:
|
||||||
@@ -92,6 +95,7 @@ class AddRepresentation(bpy.types.Operator):
|
|||||||
for s in obj.material_slots
|
for s in obj.material_slots
|
||||||
if s.material
|
if s.material
|
||||||
],
|
],
|
||||||
|
"should_use_presentation_style_assignment": context.scene.BIMGeometryProperties.should_use_presentation_style_assignment
|
||||||
},
|
},
|
||||||
).execute()
|
).execute()
|
||||||
assign_representation.Usecase(
|
assign_representation.Usecase(
|
||||||
@@ -183,8 +187,11 @@ class UpdateMeshRepresentation(bpy.types.Operator):
|
|||||||
self.file,
|
self.file,
|
||||||
{
|
{
|
||||||
"context": old_representation.ContextOfItems,
|
"context": old_representation.ContextOfItems,
|
||||||
|
"blender_object": obj,
|
||||||
"geometry": obj.data,
|
"geometry": obj.data,
|
||||||
"total_items": max(1, len(obj.material_slots)),
|
"total_items": max(1, len(obj.material_slots)),
|
||||||
|
"should_force_faceted_brep": context.scene.BIMGeometryProperties.should_force_faceted_brep,
|
||||||
|
"should_force_triangulation": context.scene.BIMGeometryProperties.should_force_triangulation
|
||||||
},
|
},
|
||||||
).execute()
|
).execute()
|
||||||
if not new_representation:
|
if not new_representation:
|
||||||
@@ -200,6 +207,7 @@ class UpdateMeshRepresentation(bpy.types.Operator):
|
|||||||
for s in obj.material_slots
|
for s in obj.material_slots
|
||||||
if s.material
|
if s.material
|
||||||
],
|
],
|
||||||
|
"should_use_presentation_style_assignment": context.scene.BIMGeometryProperties.should_use_presentation_style_assignment
|
||||||
},
|
},
|
||||||
).execute()
|
).execute()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import bpy
|
||||||
|
from blenderbim.bim.prop import StrProperty, Attribute
|
||||||
|
from bpy.types import PropertyGroup
|
||||||
|
from bpy.props import (
|
||||||
|
PointerProperty,
|
||||||
|
StringProperty,
|
||||||
|
EnumProperty,
|
||||||
|
BoolProperty,
|
||||||
|
IntProperty,
|
||||||
|
FloatProperty,
|
||||||
|
FloatVectorProperty,
|
||||||
|
CollectionProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BIMGeometryProperties(PropertyGroup):
|
||||||
|
# Revit workaround
|
||||||
|
should_use_presentation_style_assignment: BoolProperty(name="Force Presentation Style Assignment", default=False)
|
||||||
|
# RIB iTwo, DESITE BIM workaround
|
||||||
|
should_force_faceted_brep: BoolProperty(name="Force Faceted Breps", default=False)
|
||||||
|
# Navisworks workaround
|
||||||
|
should_force_triangulation: BoolProperty(name="Force Triangulation", default=False)
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
class Usecase:
|
class Usecase:
|
||||||
def __init__(self, file, settings=None):
|
def __init__(self, file, settings=None):
|
||||||
self.file = file
|
self.file = file
|
||||||
@@ -6,17 +8,10 @@ class Usecase:
|
|||||||
self.settings[key] = value
|
self.settings[key] = value
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
styles = []
|
dummy_context = self.file.create_entity("IfcRepresentationContext")
|
||||||
for subelement in self.file.traverse(self.settings["representation"]):
|
for subelement in self.file.traverse(self.settings["representation"]):
|
||||||
if subelement.is_a("IfcRepresentationItem") and subelement.StyledByItem:
|
if subelement.is_a("IfcRepresentationItem") and subelement.StyledByItem:
|
||||||
styles.append(subelement)
|
[self.file.remove(s) for s in subelement.StyledByItem]
|
||||||
for style in styles:
|
elif subelement.is_a("IfcRepresentation"):
|
||||||
self.remove_deep(style)
|
subelement.ContextOfItems = dummy_context
|
||||||
self.remove_deep(self.settings["representation"])
|
ifcopenshell.util.element.remove_deep(self.file, self.settings["representation"])
|
||||||
|
|
||||||
def remove_deep(self, element):
|
|
||||||
subgraph = list(self.file.traverse(element))
|
|
||||||
subgraph_set = set(subgraph)
|
|
||||||
for ref in subgraph[::-1]:
|
|
||||||
if ref.id() and len(set(self.file.get_inverse(ref)) - subgraph_set) == 0:
|
|
||||||
self.file.remove(ref)
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class BIM_PT_mesh(Panel):
|
|||||||
context.active_object is not None
|
context.active_object is not None
|
||||||
and context.active_object.type == "MESH"
|
and context.active_object.type == "MESH"
|
||||||
and hasattr(context.active_object.data, "BIMMeshProperties")
|
and hasattr(context.active_object.data, "BIMMeshProperties")
|
||||||
|
and context.active_object.data.BIMMeshProperties.ifc_definition_id
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
@@ -78,3 +79,30 @@ def BIM_PT_transform(self, context):
|
|||||||
if context.active_object and context.active_object.BIMObjectProperties.ifc_definition_id:
|
if context.active_object and context.active_object.BIMObjectProperties.ifc_definition_id:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.operator("bim.edit_object_placement")
|
row.operator("bim.edit_object_placement")
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_workarounds(Panel):
|
||||||
|
bl_label = "IFC Vendor Workarounds"
|
||||||
|
bl_idname = "BIM_PT_workarounds"
|
||||||
|
bl_options = {"DEFAULT_CLOSED"}
|
||||||
|
bl_space_type = "PROPERTIES"
|
||||||
|
bl_region_type = "WINDOW"
|
||||||
|
bl_context = "data"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return (
|
||||||
|
context.active_object is not None
|
||||||
|
and context.active_object.type == "MESH"
|
||||||
|
and hasattr(context.active_object.data, "BIMMeshProperties")
|
||||||
|
and context.active_object.data.BIMMeshProperties.ifc_definition_id
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
props = context.scene.BIMGeometryProperties
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(props, "should_force_faceted_brep")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(props, "should_force_triangulation")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.prop(props, "should_use_presentation_style_assignment")
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ class ExportIFC(bpy.types.Operator):
|
|||||||
bl_label = "Export IFC"
|
bl_label = "Export IFC"
|
||||||
filename_ext = ".ifc"
|
filename_ext = ".ifc"
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
json_version: bpy.props.EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
|
||||||
|
json_compact: bpy.props.BoolProperty(name="Export Compact IFCJSON", default=False)
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
if not self.filepath:
|
if not self.filepath:
|
||||||
@@ -87,11 +89,15 @@ class ExportIFC(bpy.types.Operator):
|
|||||||
output_file = bpy.path.ensure_ext(self.filepath, ".ifcjson")
|
output_file = bpy.path.ensure_ext(self.filepath, ".ifcjson")
|
||||||
else:
|
else:
|
||||||
output_file = bpy.path.ensure_ext(self.filepath, ".ifc")
|
output_file = bpy.path.ensure_ext(self.filepath, ".ifc")
|
||||||
ifc_export_settings = export_ifc.IfcExportSettings.factory(context, output_file, logger)
|
|
||||||
ifc_exporter = export_ifc.IfcExporter(ifc_export_settings)
|
settings = export_ifc.IfcExportSettings.factory(context, output_file, logger)
|
||||||
ifc_export_settings.logger.info("Starting export")
|
settings.json_version = self.json_version
|
||||||
|
settings.json_compact = self.json_compact
|
||||||
|
|
||||||
|
ifc_exporter = export_ifc.IfcExporter(settings)
|
||||||
|
settings.logger.info("Starting export")
|
||||||
ifc_exporter.export()
|
ifc_exporter.export()
|
||||||
ifc_export_settings.logger.info("Export finished in {:.2f} seconds".format(time.time() - start))
|
settings.logger.info("Export finished in {:.2f} seconds".format(time.time() - start))
|
||||||
if not bpy.context.scene.DocProperties.ifc_files:
|
if not bpy.context.scene.DocProperties.ifc_files:
|
||||||
new = bpy.context.scene.DocProperties.ifc_files.add()
|
new = bpy.context.scene.DocProperties.ifc_files.add()
|
||||||
new.name = output_file
|
new.name = output_file
|
||||||
@@ -106,17 +112,59 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
|||||||
filename_ext = ".ifc"
|
filename_ext = ".ifc"
|
||||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||||
|
|
||||||
|
should_import_type_representations: bpy.props.BoolProperty(name="Import Type Representations", default=False)
|
||||||
|
should_import_curves: bpy.props.BoolProperty(name="Import Curves", default=False)
|
||||||
|
should_import_spaces: bpy.props.BoolProperty(name="Import Spaces", default=False)
|
||||||
|
should_auto_set_workarounds: bpy.props.BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
|
||||||
|
should_use_cpu_multiprocessing: bpy.props.BoolProperty(name="Import with CPU Multiprocessing", default=True)
|
||||||
|
should_merge_by_class: bpy.props.BoolProperty(name="Import and Merge by Class", default=False)
|
||||||
|
should_merge_by_material: bpy.props.BoolProperty(name="Import and Merge by Material", default=False)
|
||||||
|
should_merge_materials_by_colour: bpy.props.BoolProperty(name="Import and Merge Materials by Colour", default=False)
|
||||||
|
should_clean_mesh: bpy.props.BoolProperty(name="Import and Clean Mesh", default=True)
|
||||||
|
deflection_tolerance: bpy.props.FloatProperty(name="Import Deflection Tolerance", default=0.001)
|
||||||
|
angular_tolerance: bpy.props.FloatProperty(name="Import Angular Tolerance", default=0.5)
|
||||||
|
should_allow_non_element_aggregates: bpy.props.BoolProperty(name="Import Non-Element Aggregates", default=False)
|
||||||
|
should_offset_model: bpy.props.BoolProperty(name="Import and Offset Model", default=False)
|
||||||
|
model_offset_coordinates: bpy.props.StringProperty(name="Model Offset Coordinates", default="0,0,0")
|
||||||
|
ifc_import_filter: bpy.props.EnumProperty(
|
||||||
|
items=[("NONE", "None", ""), ("WHITELIST", "Whitelist", ""), ("BLACKLIST", "Blacklist", ""),],
|
||||||
|
name="Import Filter",
|
||||||
|
)
|
||||||
|
ifc_selector: bpy.props.StringProperty(default="", name="IFC Selector")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
logger = logging.getLogger("ImportIFC")
|
logger = logging.getLogger("ImportIFC")
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
filename=bpy.context.scene.BIMProperties.data_dir + "process.log", filemode="a", level=logging.DEBUG
|
filename=bpy.context.scene.BIMProperties.data_dir + "process.log", filemode="a", level=logging.DEBUG
|
||||||
)
|
)
|
||||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
|
|
||||||
ifc_import_settings.logger.info("Starting import")
|
settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
|
||||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
settings.should_import_type_representations = self.should_import_type_representations
|
||||||
|
settings.should_import_curves = self.should_import_curves
|
||||||
|
settings.should_import_spaces = self.should_import_spaces
|
||||||
|
settings.should_auto_set_workarounds = self.should_auto_set_workarounds
|
||||||
|
settings.should_use_cpu_multiprocessing = self.should_use_cpu_multiprocessing
|
||||||
|
settings.should_merge_by_class = self.should_merge_by_class
|
||||||
|
settings.should_merge_by_material = self.should_merge_by_material
|
||||||
|
settings.should_merge_materials_by_colour = self.should_merge_materials_by_colour
|
||||||
|
settings.should_clean_mesh = self.should_clean_mesh
|
||||||
|
settings.deflection_tolerance = self.deflection_tolerance
|
||||||
|
settings.angular_tolerance = self.angular_tolerance
|
||||||
|
settings.should_allow_non_element_aggregates = self.should_allow_non_element_aggregates
|
||||||
|
settings.should_offset_model = self.should_offset_model
|
||||||
|
settings.model_offset_coordinates = (
|
||||||
|
[float(o) for o in self.model_offset_coordinates.split(",")]
|
||||||
|
if self.model_offset_coordinates
|
||||||
|
else (0, 0, 0)
|
||||||
|
)
|
||||||
|
settings.ifc_import_filter = self.ifc_import_filter
|
||||||
|
settings.ifc_selector = self.ifc_selector
|
||||||
|
|
||||||
|
settings.logger.info("Starting import")
|
||||||
|
ifc_importer = import_ifc.IfcImporter(settings)
|
||||||
ifc_importer.execute()
|
ifc_importer.execute()
|
||||||
ifc_import_settings.logger.info("Import finished in {:.2f} seconds".format(time.time() - start))
|
settings.logger.info("Import finished in {:.2f} seconds".format(time.time() - start))
|
||||||
print("Import finished in {:.2f} seconds".format(time.time() - start))
|
print("Import finished in {:.2f} seconds".format(time.time() - start))
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -1249,6 +1297,7 @@ class CopyAttributeToSelection(bpy.types.Operator):
|
|||||||
attribute_value: bpy.props.StringProperty()
|
attribute_value: bpy.props.StringProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
# TODO: reimplement
|
||||||
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
||||||
self.applicable_attributes_cache = {}
|
self.applicable_attributes_cache = {}
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
|
|||||||
@@ -295,18 +295,6 @@ def getMaterialPsetNames(self, context):
|
|||||||
return materialpsetnames_enum
|
return materialpsetnames_enum
|
||||||
|
|
||||||
|
|
||||||
def getApplicableMaterialAttributes(self, context):
|
|
||||||
global materialattributes_enum
|
|
||||||
materialattributes_enum.clear()
|
|
||||||
if "/" in context.active_object.name:
|
|
||||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
|
||||||
entity = ifc_schema.declaration_by_name("IfcMaterial")
|
|
||||||
materialattributes_enum.extend(
|
|
||||||
[(a.name(), a.name(), "") for a in entity.all_attributes() if self.attributes.find(a.name()) == -1]
|
|
||||||
)
|
|
||||||
return materialattributes_enum
|
|
||||||
|
|
||||||
|
|
||||||
def getContexts(self, context):
|
def getContexts(self, context):
|
||||||
from blenderbim.bim.module.context.data import Data
|
from blenderbim.bim.module.context.data import Data
|
||||||
if not Data.is_loaded:
|
if not Data.is_loaded:
|
||||||
@@ -699,36 +687,6 @@ class BIMProperties(PropertyGroup):
|
|||||||
data_dir: StringProperty(default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory")
|
data_dir: StringProperty(default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory")
|
||||||
ifc_file: StringProperty(name="IFC File")
|
ifc_file: StringProperty(name="IFC File")
|
||||||
export_schema: EnumProperty(items=[("IFC4", "IFC4", ""), ("IFC2X3", "IFC2X3", "")], name="IFC Schema")
|
export_schema: EnumProperty(items=[("IFC4", "IFC4", ""), ("IFC2X3", "IFC2X3", "")], name="IFC Schema")
|
||||||
export_json_version: EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
|
|
||||||
export_json_compact: BoolProperty(name="Export Compact IFCJSON", default=False)
|
|
||||||
export_has_representations: BoolProperty(name="Export Representations", default=True)
|
|
||||||
export_should_guess_quantities: BoolProperty(name="Export with Guessed Quantities", default=False)
|
|
||||||
export_should_use_presentation_style_assignment: BoolProperty(
|
|
||||||
name="Export with Presentation Style Assignment", default=False
|
|
||||||
)
|
|
||||||
export_should_force_faceted_brep: BoolProperty(name="Export with Faceted Breps", default=False)
|
|
||||||
export_should_force_triangulation: BoolProperty(name="Export with Triangulation", default=False)
|
|
||||||
import_should_import_type_representations: BoolProperty(name="Import Type Representations", default=False)
|
|
||||||
import_should_import_curves: BoolProperty(name="Import Curves", 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_auto_set_workarounds: BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
|
|
||||||
import_should_import_native: BoolProperty(name="Import Native Representations", default=False)
|
|
||||||
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_import_with_profiling: BoolProperty(name="Import with Profiling", default=True)
|
|
||||||
import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True)
|
|
||||||
import_should_merge_by_class: BoolProperty(name="Import and Merge by Class", default=False)
|
|
||||||
import_should_merge_by_material: BoolProperty(name="Import and Merge by Material", default=False)
|
|
||||||
import_should_merge_materials_by_colour: BoolProperty(name="Import and Merge Materials by Colour", default=False)
|
|
||||||
import_should_clean_mesh: BoolProperty(name="Import and Clean Mesh", default=True)
|
|
||||||
import_deflection_tolerance: FloatProperty(name="Import Deflection Tolerance", default=0.001)
|
|
||||||
import_angular_tolerance: FloatProperty(name="Import Angular Tolerance", default=0.5)
|
|
||||||
import_should_allow_non_element_aggregates: BoolProperty(name="Import Non-Element Aggregates", 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")
|
|
||||||
|
|
||||||
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
|
|
||||||
has_library: BoolProperty(name="Has Project Library", default=False)
|
has_library: BoolProperty(name="Has Project Library", default=False)
|
||||||
contexts: EnumProperty(items=getContexts, name="Contexts")
|
contexts: EnumProperty(items=getContexts, name="Contexts")
|
||||||
available_contexts: EnumProperty(items=[("Model", "Model", ""), ("Plan", "Plan", "")], name="Available Contexts")
|
available_contexts: EnumProperty(items=[("Model", "Model", ""), ("Plan", "Plan", "")], name="Available Contexts")
|
||||||
@@ -744,11 +702,6 @@ class BIMProperties(PropertyGroup):
|
|||||||
section_plane_colour: FloatVectorProperty(
|
section_plane_colour: FloatVectorProperty(
|
||||||
name="Temporary Section Cutaway Colour", subtype="COLOR", default=(1, 0, 0), min=0.0, max=1.0
|
name="Temporary Section Cutaway Colour", subtype="COLOR", default=(1, 0, 0), min=0.0, max=1.0
|
||||||
)
|
)
|
||||||
ifc_import_filter: EnumProperty(
|
|
||||||
items=[("NONE", "None", ""), ("WHITELIST", "Whitelist", ""), ("BLACKLIST", "Blacklist", ""),],
|
|
||||||
name="Import Filter",
|
|
||||||
)
|
|
||||||
ifc_selector: StringProperty(default="", name="IFC Selector")
|
|
||||||
blender_clash_set_a: CollectionProperty(name="Blender Clash Set A", type=StrProperty)
|
blender_clash_set_a: CollectionProperty(name="Blender Clash Set A", type=StrProperty)
|
||||||
blender_clash_set_b: CollectionProperty(name="Blender Clash Set B", type=StrProperty)
|
blender_clash_set_b: CollectionProperty(name="Blender Clash Set B", type=StrProperty)
|
||||||
clash_sets: CollectionProperty(name="Clash Sets", type=ClashSet)
|
clash_sets: CollectionProperty(name="Clash Sets", type=ClashSet)
|
||||||
@@ -874,7 +827,6 @@ class BIMMaterialProperties(PropertyGroup):
|
|||||||
pset_name: EnumProperty(items=getMaterialPsetNames, name="Pset Name")
|
pset_name: EnumProperty(items=getMaterialPsetNames, name="Pset Name")
|
||||||
psets: CollectionProperty(name="Psets", type=PsetQto)
|
psets: CollectionProperty(name="Psets", type=PsetQto)
|
||||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||||
applicable_attributes: EnumProperty(items=getApplicableMaterialAttributes, name="Attribute Names")
|
|
||||||
# In Blender, a material object can map to an IFC material, IFC surface style, or both
|
# In Blender, a material object can map to an IFC material, IFC surface style, or both
|
||||||
ifc_style_id: IntProperty(name="IFC Style ID")
|
ifc_style_id: IntProperty(name="IFC Style ID")
|
||||||
|
|
||||||
|
|||||||
@@ -477,108 +477,6 @@ class BIM_PT_patch(Panel):
|
|||||||
op = row.operator("bim.execute_ifc_patch")
|
op = row.operator("bim.execute_ifc_patch")
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_mvd(Panel):
|
|
||||||
bl_label = "Model View Definitions (MVD)"
|
|
||||||
bl_idname = "BIM_PT_mvd"
|
|
||||||
bl_options = {"DEFAULT_CLOSED"}
|
|
||||||
bl_space_type = "PROPERTIES"
|
|
||||||
bl_region_type = "WINDOW"
|
|
||||||
bl_context = "scene"
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
scene = context.scene
|
|
||||||
bim_properties = scene.BIMProperties
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_schema")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_json_version")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "ifc_import_filter")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "ifc_selector")
|
|
||||||
|
|
||||||
layout.label(text="Custom MVD:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_has_representations")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_guess_quantities")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_force_faceted_brep")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_import_type_representations")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_import_curves")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_import_spaces")
|
|
||||||
|
|
||||||
layout.label(text="Experimental Modes:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_import_native")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_export_should_roundtrip_native")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_use_cpu_multiprocessing")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_import_with_profiling")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_deflection_tolerance")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_angular_tolerance")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_json_compact")
|
|
||||||
|
|
||||||
layout.label(text="Simplifications:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_merge_by_class")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_merge_by_material")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_merge_materials_by_colour")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_clean_mesh")
|
|
||||||
|
|
||||||
layout.label(text="Vendor Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_auto_set_workarounds")
|
|
||||||
|
|
||||||
layout.label(text="RIB iTWO Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_force_faceted_brep")
|
|
||||||
|
|
||||||
layout.label(text="DESITE BIM Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_force_faceted_brep")
|
|
||||||
|
|
||||||
layout.label(text="Navisworks Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_force_triangulation")
|
|
||||||
|
|
||||||
layout.label(text="ProStructures Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_allow_non_element_aggregates")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_should_offset_model")
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "import_model_offset_coordinates")
|
|
||||||
|
|
||||||
layout.label(text="Revit Workarounds:")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.prop(bim_properties, "export_should_use_presentation_style_assignment")
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_UL_generic(bpy.types.UIList):
|
class BIM_UL_generic(bpy.types.UIList):
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
if item:
|
if item:
|
||||||
|
|||||||
Reference in New Issue
Block a user