mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
WIP refactoring representations to be incrementally edited. See #1222.
# Conflicts: # src/ifcblenderexport/blenderbim/bim/operator.py
This commit is contained in:
@@ -133,8 +133,9 @@ if bpy is not None:
|
||||
operator.SmartClashGroup,
|
||||
operator.SelectSmartGroup,
|
||||
operator.LoadSmartGroupsForActiveClashSet,
|
||||
operator.SwitchContext,
|
||||
operator.RemoveContext,
|
||||
operator.AddRepresentation,
|
||||
operator.SwitchRepresentation,
|
||||
operator.RemoveRepresentation,
|
||||
operator.OpenUpstream,
|
||||
operator.BIM_OT_ChangeClassificationLevel,
|
||||
operator.AddPropertySetTemplate,
|
||||
|
||||
@@ -1056,29 +1056,32 @@ class IfcParser:
|
||||
for context in self.ifc_export_settings.context_tree:
|
||||
for subcontext in context["subcontexts"]:
|
||||
for target_view in subcontext["target_views"]:
|
||||
rep_context = self.get_obj_representation_context(obj, context["name"], subcontext["name"], target_view)
|
||||
if rep_context:
|
||||
self.append_representation_in_context(obj, rep_context, name)
|
||||
representation = self.get_shape_representation(obj, context["name"], subcontext["name"], target_view)
|
||||
if representation:
|
||||
self.append_representation_in_context(obj, representation, name)
|
||||
|
||||
def get_obj_representation_context(self, obj, context, subcontext, target_view):
|
||||
for c in obj.BIMObjectProperties.representation_contexts:
|
||||
if c.context == context and c.name == subcontext and c.target_view == target_view:
|
||||
return c
|
||||
if obj.BIMObjectProperties.representation_contexts:
|
||||
def get_shape_representation(self, obj, context, subcontext, target_view):
|
||||
for representation in obj.BIMObjectProperties.representations:
|
||||
c = self.stored_file.by_id(representation.ifc_definition_id)
|
||||
if c.ContextType == context and c.ContextIdentifier == subcontext and c.TargetView == target_view:
|
||||
return representation
|
||||
if obj.BIMObjectProperties.representations:
|
||||
return
|
||||
if context == "Model" and subcontext == "Body" and target_view == "MODEL_VIEW":
|
||||
representation_context = obj.BIMObjectProperties.representation_contexts.add()
|
||||
representation_context.context = "Model"
|
||||
representation_context.name = "Body"
|
||||
representation_context.target_view = "MODEL_VIEW"
|
||||
return representation_context
|
||||
# TODO: reimplement - see bug #1222
|
||||
#if context == "Model" and subcontext == "Body" and target_view == "MODEL_VIEW":
|
||||
# representation_context = obj.BIMObjectProperties.representation_contexts.add()
|
||||
# representation_context.context = "Model"
|
||||
# representation_context.name = "Body"
|
||||
# representation_context.target_view = "MODEL_VIEW"
|
||||
# return representation_context
|
||||
|
||||
def append_representation_in_context(self, obj, rep_context, name):
|
||||
context = rep_context.context
|
||||
subcontext = rep_context.name
|
||||
target_view = rep_context.target_view
|
||||
def append_representation_in_context(self, obj, shape_representation, name):
|
||||
context_of_items = self.stored_file.by_id(shape_representation.ifc_definition_id).ContextOfItems
|
||||
context = context_of_items.ContextType
|
||||
subcontext = context_of_items.ContextIdentifier
|
||||
target_view = context_of_items.TargetView
|
||||
|
||||
if self.ifc_export_settings.should_roundtrip_native and rep_context.ifc_definition_id:
|
||||
if self.ifc_export_settings.should_roundtrip_native and shape_representation.ifc_definition_id:
|
||||
self.representations[
|
||||
"{}/{}/{}/{}".format(context, subcontext, target_view, name)
|
||||
] = self.get_representation(obj.data, obj, context, subcontext, target_view)
|
||||
@@ -1087,7 +1090,6 @@ class IfcParser:
|
||||
context_prefix = "/".join([context, subcontext, target_view])
|
||||
mesh_name = "/".join([context_prefix, name])
|
||||
mesh = self.search_for_mesh_or_curve_data(mesh_name)
|
||||
# TODO: if the search result is empty, we should check for ifc_definition_id
|
||||
if mesh:
|
||||
self.representations[mesh_name] = self.get_representation(mesh, obj, context, subcontext, target_view)
|
||||
if "Model/Box/MODEL_VIEW" in self.generated_subcontexts and context_prefix == "Model/Body/MODEL_VIEW":
|
||||
@@ -1112,7 +1114,7 @@ class IfcParser:
|
||||
return data
|
||||
|
||||
def get_representation(self, mesh, obj, context, subcontext, target_view):
|
||||
rep_context = self.get_obj_representation_context(obj, context, subcontext, target_view)
|
||||
representation = self.get_shape_representation(obj, context, subcontext, target_view)
|
||||
return {
|
||||
"ifc": None,
|
||||
"raw": mesh,
|
||||
@@ -1120,9 +1122,9 @@ class IfcParser:
|
||||
"context": context,
|
||||
"subcontext": subcontext,
|
||||
"target_view": target_view,
|
||||
"has_ifc_definition": rep_context and rep_context.ifc_definition_id,
|
||||
"has_ifc_definition": representation and representation.ifc_definition_id,
|
||||
"ifc_definition": mesh.BIMMeshProperties.ifc_definition if hasattr(mesh, "BIMMeshProperties") else None,
|
||||
"ifc_definition_id": rep_context.ifc_definition_id if rep_context else 0
|
||||
"ifc_definition_id": representation.ifc_definition_id if representation else 0
|
||||
if hasattr(mesh, "BIMMeshProperties")
|
||||
else None,
|
||||
"is_parametric": mesh.BIMMeshProperties.is_parametric if hasattr(mesh, "BIMMeshProperties") else False,
|
||||
@@ -1344,8 +1346,9 @@ class IfcExporter:
|
||||
self.roundtrip_id_new_to_old = {}
|
||||
|
||||
def export(self, selected_objects):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
if self.file and self.ifc_export_settings.should_export_from_memory:
|
||||
self.stored_file = ifc.IfcStore.get_file() # See bug #1222
|
||||
if self.stored_file and self.ifc_export_settings.should_export_from_memory:
|
||||
self.file = self.stored_file
|
||||
return self.write_ifc_file()
|
||||
self.schema_version = self.ifc_export_settings.schema
|
||||
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.schema_version)
|
||||
@@ -2038,8 +2041,8 @@ class IfcExporter:
|
||||
# At the moment, we assume that styled items only apply to the body context.
|
||||
if representation.RepresentationIdentifier != "Body":
|
||||
continue
|
||||
rep_context = self.ifc_parser.get_obj_representation_context(product["raw"], "Model", "Body", "MODEL_VIEW")
|
||||
if self.ifc_export_settings.should_roundtrip_native and rep_context and rep_context.ifc_definition_id:
|
||||
rep = self.ifc_parser.get_shape_representation(product["raw"], "Model", "Body", "MODEL_VIEW")
|
||||
if self.ifc_export_settings.should_roundtrip_native and rep and rep.ifc_definition_id:
|
||||
# For native roundtripping, each slot could be a one to many relationship to items
|
||||
for item in self.get_geometric_representation_items(representation):
|
||||
original_id = self.roundtrip_id_new_to_old[item.id()]
|
||||
|
||||
@@ -773,6 +773,7 @@ class IfcImporter:
|
||||
obj = self.existing_elements[element.GlobalId]
|
||||
else:
|
||||
obj = bpy.data.objects.new(f"{element.is_a()}/{element.Name}", None)
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
self.add_element_attributes(element, obj.BIMObjectProperties)
|
||||
group_collection.objects.link(obj)
|
||||
self.groups[element.GlobalId] = {"ifc": element, "blender": obj}
|
||||
@@ -809,6 +810,7 @@ class IfcImporter:
|
||||
shape = ifcopenshell.geom.create_shape(self.settings_2d, axis.AxisCurve)
|
||||
mesh = self.create_mesh(axis, shape)
|
||||
obj = bpy.data.objects.new(f"IfcGridAxis/{axis.AxisTag}", mesh)
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
obj.matrix_world = matrix_world
|
||||
self.add_element_attributes(axis, obj.BIMObjectProperties)
|
||||
grid.objects.link(obj)
|
||||
@@ -843,6 +845,7 @@ class IfcImporter:
|
||||
except:
|
||||
self.ifc_import_settings.logger.error("Failed to generate shape for %s", element)
|
||||
obj = bpy.data.objects.new(self.get_name(element), mesh)
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
self.material_creator.create(element, obj, mesh)
|
||||
self.add_element_attributes(element, obj.BIMObjectProperties)
|
||||
self.add_element_classifications(element, obj)
|
||||
@@ -955,6 +958,7 @@ class IfcImporter:
|
||||
mesh = None
|
||||
|
||||
obj = bpy.data.objects.new(self.get_name(element), mesh)
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
|
||||
if shape:
|
||||
m = shape.transformation.matrix.data
|
||||
@@ -1760,6 +1764,7 @@ class IfcImporter:
|
||||
element = rel_aggregate.RelatingObject
|
||||
|
||||
obj = bpy.data.objects.new("{}/{}".format(element.is_a(), element.Name), None)
|
||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
||||
obj.instance_type = "COLLECTION"
|
||||
obj.instance_collection = collection
|
||||
self.place_object_in_spatial_tree(element, obj)
|
||||
@@ -1823,6 +1828,7 @@ class IfcImporter:
|
||||
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_attributes(element, obj.BIMObjectProperties)
|
||||
|
||||
@@ -10,6 +10,7 @@ import subprocess
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.selector
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.schema
|
||||
import tempfile
|
||||
from . import export_ifc
|
||||
@@ -2156,6 +2157,7 @@ class CutSection(bpy.types.Operator):
|
||||
bl_label = "Cut Section"
|
||||
|
||||
def execute(self, context):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
camera = bpy.context.scene.camera
|
||||
if not (camera.type == "CAMERA" and camera.data.type == "ORTHO"):
|
||||
return {"FINISHED"}
|
||||
@@ -2322,11 +2324,10 @@ class CutSection(bpy.types.Operator):
|
||||
bpy.data.objects[name].hide_set(value)
|
||||
|
||||
def does_obj_have_target_view_representation(self, obj, camera):
|
||||
return camera.data.BIMCameraProperties.target_view in [
|
||||
c.target_view
|
||||
for c in obj.BIMObjectProperties.representation_contexts
|
||||
if c.context == "Plan" and c.name == "Annotation"
|
||||
]
|
||||
for representation in obj.BIMObjectProperties.representations:
|
||||
element = self.file.by_id(representation.ifc_definition_id)
|
||||
if ifcopenshell.util.element.is_representation_of_context(element, "Plan", "Annotation", camera.data.BIMCameraProperties.target_view):
|
||||
return True
|
||||
|
||||
def is_landscape(self):
|
||||
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
|
||||
@@ -2464,109 +2465,45 @@ class ActivateView(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SwitchContext(bpy.types.Operator):
|
||||
bl_idname = "bim.switch_context"
|
||||
bl_label = "Switch Context"
|
||||
has_target_context: bpy.props.BoolProperty()
|
||||
context_name: bpy.props.StringProperty()
|
||||
subcontext_name: bpy.props.StringProperty()
|
||||
target_view_name: bpy.props.StringProperty()
|
||||
class AddRepresentation(bpy.types.Operator):
|
||||
bl_idname = "bim.add_representation"
|
||||
bl_label = "Add Representation"
|
||||
|
||||
# Warning: This is an incredibly experimental operator. It effectively does
|
||||
# a mini-import. A better approach will make this obsolete in the future.
|
||||
def execute(self, context):
|
||||
self.obj = bpy.context.active_object
|
||||
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
if "/" not in self.obj.data.name:
|
||||
self.obj.data.name = ifcopenshell.guid.compress(str(uuid.uuid4()).replace("-", ""))
|
||||
self.obj.data.name = "Model/Body/MODEL_VIEW/" + self.obj.data.name
|
||||
has_default_context = False
|
||||
for subcontext in self.obj.BIMObjectProperties.representation_contexts:
|
||||
if (
|
||||
subcontext.context == "Model"
|
||||
and subcontext.name == "Body"
|
||||
and subcontext.target_view == "MODEL_VIEW"
|
||||
):
|
||||
has_default_context = True
|
||||
break
|
||||
if not has_default_context:
|
||||
representation_context = self.obj.BIMObjectProperties.representation_contexts.add()
|
||||
representation_context.context = "Model"
|
||||
representation_context.name = "Body"
|
||||
representation_context.target_view = "MODEL_VIEW"
|
||||
|
||||
self.context = bpy.context.scene.BIMProperties.available_contexts
|
||||
self.subcontext = bpy.context.scene.BIMProperties.available_subcontexts
|
||||
self.target_view = bpy.context.scene.BIMProperties.available_target_views
|
||||
|
||||
if self.has_target_context:
|
||||
self.context = self.context_name
|
||||
self.subcontext = self.subcontext_name
|
||||
self.target_view = self.target_view_name
|
||||
|
||||
existing_mesh = self.obj.data
|
||||
existing_mesh.use_fake_user = True
|
||||
mesh = bpy.data.meshes.get(
|
||||
"{}/{}/{}/{}".format(self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3])
|
||||
mesh = self.obj.data.copy()
|
||||
mesh.name = "{}/{}/{}/{}".format(
|
||||
self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3]
|
||||
)
|
||||
if not mesh:
|
||||
try:
|
||||
global_id = self.obj.BIMObjectProperties.attributes.get("GlobalId").string_value
|
||||
mesh = self.pull_mesh_from_ifc(global_id)
|
||||
except:
|
||||
mesh = self.obj.data.copy()
|
||||
mesh.name = "{}/{}/{}/{}".format(
|
||||
self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3]
|
||||
)
|
||||
has_context = False
|
||||
for context in self.obj.BIMObjectProperties.representation_contexts:
|
||||
if (
|
||||
context.context == self.context
|
||||
and context.name == self.subcontext
|
||||
and context.target_view == self.target_view
|
||||
):
|
||||
has_context = True
|
||||
break
|
||||
if not has_context:
|
||||
representation_context = self.obj.BIMObjectProperties.representation_contexts.add()
|
||||
representation_context.context = self.context
|
||||
representation_context.name = self.subcontext
|
||||
representation_context.target_view = self.target_view
|
||||
mesh.use_fake_user = True
|
||||
representation = self.obj.BIMObjectProperties.representations.add()
|
||||
representation.name = self.subcontext
|
||||
representation.type = "Brep" if self.file.schema == "IFC2X3" else "Tessellation"
|
||||
mesh.use_fake_user = True
|
||||
self.obj.data = mesh
|
||||
|
||||
# TODO: push representation
|
||||
return {"FINISHED"}
|
||||
|
||||
def pull_mesh_from_ifc(self, global_id):
|
||||
def push_mesh_to_ifc(self):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(bpy.context, ifc.IfcStore.path, logger)
|
||||
element = self.file.by_id(global_id)
|
||||
element = self.file.by_id(self.obj.BIMObjectProperties.ifc_definition_id)
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.INCLUDE_CURVES, True)
|
||||
if element.is_a("IfcProduct"):
|
||||
representations = element.Representation.Representations
|
||||
else:
|
||||
representations = element.RepresentationMaps
|
||||
|
||||
for rep in element.Representation.Representations:
|
||||
if (
|
||||
rep.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and rep.ContextOfItems.ContextType == self.context
|
||||
and rep.ContextOfItems.ContextIdentifier == self.subcontext
|
||||
and rep.ContextOfItems.TargetView == self.target_view
|
||||
):
|
||||
break
|
||||
elif (
|
||||
rep.ContextOfItems.is_a("IfcGeometricRepresentationContext")
|
||||
and rep.ContextOfItems.ContextType == self.context
|
||||
and rep.ContextOfItems.ContextIdentifier == self.subcontext
|
||||
):
|
||||
break
|
||||
|
||||
if not element.is_a("IfcProduct"):
|
||||
rep = rep.MappedRepresentation
|
||||
|
||||
shape = ifcopenshell.geom.create_shape(settings, rep)
|
||||
shape = ifcopenshell.geom.create_shape(settings, self.file.by_id(self.ifc_definition_id))
|
||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
ifc_importer.file = self.file
|
||||
mesh = ifc_importer.create_mesh(element, shape)
|
||||
@@ -2574,37 +2511,94 @@ class SwitchContext(bpy.types.Operator):
|
||||
self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3]
|
||||
)
|
||||
self.obj.data = mesh
|
||||
material_creator = import_ifc.MaterialCreator(ifc_import_settings)
|
||||
material_creator = import_ifc.MaterialCreator(ifc_import_settings, ifc_importer)
|
||||
material_creator.create(element, self.obj, mesh)
|
||||
return mesh
|
||||
|
||||
|
||||
class RemoveContext(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_context"
|
||||
bl_label = "Remove Context"
|
||||
class SwitchRepresentation(bpy.types.Operator):
|
||||
bl_idname = "bim.switch_representation"
|
||||
bl_label = "Switch Representation"
|
||||
ifc_definition_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.obj = bpy.context.active_object
|
||||
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
if "/" not in self.obj.data.name:
|
||||
self.obj.data.name = ifcopenshell.guid.compress(str(uuid.uuid4()).replace("-", ""))
|
||||
self.obj.data.name = "Model/Body/MODEL_VIEW/" + self.obj.data.name
|
||||
|
||||
context_of_items = self.file.by_id(self.ifc_definition_id).ContextOfItems
|
||||
self.context = context_of_items.ContextType
|
||||
self.subcontext = context_of_items.ContextIdentifier
|
||||
self.target_view = context_of_items.TargetView
|
||||
|
||||
existing_mesh = self.obj.data
|
||||
existing_mesh.use_fake_user = True
|
||||
mesh = bpy.data.meshes.get(
|
||||
"{}/{}/{}/{}".format(self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3])
|
||||
)
|
||||
if not mesh:
|
||||
mesh = self.pull_mesh_from_ifc()
|
||||
mesh.use_fake_user = True
|
||||
self.obj.data = mesh
|
||||
return {"FINISHED"}
|
||||
|
||||
def pull_mesh_from_ifc(self):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(bpy.context, ifc.IfcStore.path, logger)
|
||||
element = self.file.by_id(self.obj.BIMObjectProperties.ifc_definition_id)
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.INCLUDE_CURVES, True)
|
||||
shape = ifcopenshell.geom.create_shape(settings, self.file.by_id(self.ifc_definition_id))
|
||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
ifc_importer.file = self.file
|
||||
mesh = ifc_importer.create_mesh(element, shape)
|
||||
mesh.name = "{}/{}/{}/{}".format(
|
||||
self.context, self.subcontext, self.target_view, self.obj.data.name.split("/")[3]
|
||||
)
|
||||
self.obj.data = mesh
|
||||
material_creator = import_ifc.MaterialCreator(ifc_import_settings, ifc_importer)
|
||||
material_creator.create(element, self.obj, mesh)
|
||||
return mesh
|
||||
|
||||
|
||||
class RemoveRepresentation(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_representation"
|
||||
bl_label = "Remove Representation"
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
# TODO This should be refactored into a testable agnostic module. See #1222.
|
||||
# Prep work
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
obj = bpy.context.active_object
|
||||
data = obj.BIMObjectProperties.representation_contexts[self.index]
|
||||
representation = obj.BIMObjectProperties.representations[self.index]
|
||||
element = self.file.by_id(representation.ifc_definition_id)
|
||||
c = element.ContextOfItems
|
||||
|
||||
# Blender work
|
||||
if "/" not in obj.data.name:
|
||||
obj.data.name = "Model/Body/MODEL_VIEW/" + obj.data.name
|
||||
|
||||
mesh = bpy.data.meshes.get(
|
||||
"{}/{}/{}/{}".format(data.context, data.name, data.target_view, obj.data.name.split("/")[3])
|
||||
"{}/{}/{}/{}".format(c.ContextType, c.ContextIdentifier, c.TargetView, obj.data.name.split("/")[3])
|
||||
)
|
||||
|
||||
if mesh:
|
||||
if obj.data == mesh:
|
||||
# TODO we can do better than this
|
||||
void_name = "Void/Void/Void/" + obj.data.name.split("/")[3]
|
||||
void_mesh = bpy.data.meshes.get(void_name)
|
||||
if not void_mesh:
|
||||
void_mesh = bpy.data.meshes.new(void_name)
|
||||
obj.data = void_mesh
|
||||
bpy.data.meshes.remove(mesh)
|
||||
obj.BIMObjectProperties.representations.remove(self.index)
|
||||
|
||||
obj.BIMObjectProperties.representation_contexts.remove(self.index)
|
||||
# IFC work
|
||||
# TODO: this works as a MVP but leaves a bunch of junk in the file. See #1222.
|
||||
self.file.remove(element)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -4427,6 +4421,7 @@ class GetRepresentationIfcParameters(bpy.types.Operator):
|
||||
bl_label = "Get Representation IFC Parameters"
|
||||
|
||||
def execute(self, context):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
obj = bpy.context.active_object
|
||||
props = obj.data.BIMMeshProperties
|
||||
element_id = self.get_ifc_definition_id(obj)
|
||||
@@ -4452,9 +4447,10 @@ class GetRepresentationIfcParameters(bpy.types.Operator):
|
||||
context, subcontext, target_view = ("Model", "Body", "MODEL_VIEW")
|
||||
else:
|
||||
context, subcontext, target_view = obj.data.name.split("/")[0:3]
|
||||
for c in obj.BIMObjectProperties.representation_contexts:
|
||||
if c.context == context and c.name == subcontext and c.target_view == target_view:
|
||||
return c.ifc_definition_id or None
|
||||
for representation in obj.BIMObjectProperties.representations:
|
||||
element = self.file.by_id(representation.ifc_definition_id)
|
||||
if ifcopenshell.util.element.is_representation_of_context(element, context, subcontext, target_view):
|
||||
return representation.ifc_definition_id or None
|
||||
|
||||
|
||||
class BakeParametricGeometry(bpy.types.Operator):
|
||||
@@ -4462,14 +4458,16 @@ class BakeParametricGeometry(bpy.types.Operator):
|
||||
bl_label = "Bake Parametric Geometry"
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
if "/" not in obj.data.name:
|
||||
context, subcontext, target_view = ("Model", "Body", "MODEL_VIEW")
|
||||
else:
|
||||
context, subcontext, target_view = obj.data.name.split("/")[0:3]
|
||||
for c in obj.BIMObjectProperties.representation_contexts:
|
||||
if c.context == context and c.name == subcontext and c.target_view == target_view:
|
||||
c.ifc_definition_id = 0
|
||||
# TODO rewrite, see #1222
|
||||
# obj = bpy.context.active_object
|
||||
# if "/" not in obj.data.name:
|
||||
# context, subcontext, target_view = ("Model", "Body", "MODEL_VIEW")
|
||||
# else:
|
||||
# context, subcontext, target_view = obj.data.name.split("/")[0:3]
|
||||
# for representation in obj.BIMObjectProperties.representations:
|
||||
# element = self.file.by_id(representation.ifc_definition_id)
|
||||
# if ifcopenshell.util.element.is_representation_of_context(element, context, subcontext, target_view):
|
||||
# representation.ifc_definition_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -4479,6 +4477,7 @@ class UpdateIfcRepresentation(bpy.types.Operator):
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
props = bpy.context.active_object.data.BIMMeshProperties
|
||||
parameter = props.ifc_parameters[self.index]
|
||||
element = ifc.IfcStore.get_file().by_id(parameter.step_id)[parameter.index] = parameter.value
|
||||
@@ -4505,9 +4504,10 @@ class UpdateIfcRepresentation(bpy.types.Operator):
|
||||
context, subcontext, target_view = ("Model", "Body", "MODEL_VIEW")
|
||||
else:
|
||||
context, subcontext, target_view = obj.data.name.split("/")[0:3]
|
||||
for c in obj.BIMObjectProperties.representation_contexts:
|
||||
if c.context == context and c.name == subcontext and c.target_view == target_view:
|
||||
return c.ifc_definition_id or None
|
||||
for representation in obj.BIMObjectProperties.representations:
|
||||
c = self.file.by_id(self.ifc_definition_id).ContextOfItems
|
||||
if c.ContextType == context and c.ContextIdentifier == subcontext and c.TargetView == target_view:
|
||||
return representation.ifc_definition_id or None
|
||||
|
||||
|
||||
class BlenderClasher:
|
||||
|
||||
@@ -1480,6 +1480,7 @@ class BoundaryCondition(PropertyGroup):
|
||||
|
||||
|
||||
class BIMObjectProperties(PropertyGroup):
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
is_reassigning_class: BoolProperty(name="Is Reassigning Class")
|
||||
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||
@@ -1544,6 +1545,7 @@ class ItemSlotMap(PropertyGroup):
|
||||
|
||||
|
||||
class BIMMeshProperties(PropertyGroup):
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
is_native: BoolProperty(name="Is Native", default=False)
|
||||
is_swept_solid: BoolProperty(name="Is Swept Solid")
|
||||
swept_solids: CollectionProperty(name="Swept Solids", type=SweptSolid)
|
||||
@@ -1553,4 +1555,4 @@ class BIMMeshProperties(PropertyGroup):
|
||||
ifc_parameters: CollectionProperty(name="IFC Parameters", type=IfcParameter)
|
||||
active_representation_item_index: IntProperty(name="Active Representation Item Index")
|
||||
presentation_layer_index: IntProperty(name="Presentation Layer Index", default=-1)
|
||||
ifc_item_ids: CollectionProperty(name="IFC Definition ID", type=ItemSlotMap)
|
||||
ifc_item_ids: CollectionProperty(name="IFC Item IDs", type=ItemSlotMap)
|
||||
|
||||
@@ -645,9 +645,7 @@ class BIM_PT_representations(Panel):
|
||||
row.prop(bpy.context.scene.BIMProperties, "available_contexts", text="")
|
||||
row.prop(bpy.context.scene.BIMProperties, "available_subcontexts", text="")
|
||||
row.prop(bpy.context.scene.BIMProperties, "available_target_views", text="")
|
||||
# TODO: reimplement with incremental editing
|
||||
# op = row.operator("bim.switch_context", icon="ADD", text="")
|
||||
# op.has_target_context = False
|
||||
row.operator("bim.add_representation", icon="ADD", text="")
|
||||
|
||||
self.file = ifc.IfcStore.get_file()
|
||||
for index, representation in enumerate(props.representations):
|
||||
@@ -656,16 +654,12 @@ class BIM_PT_representations(Panel):
|
||||
row.prop(representation, "type", text="")
|
||||
if not representation.ifc_definition_id:
|
||||
continue
|
||||
subcontext = self.file.by_id(representation.ifc_definition_id).ContextOfItems
|
||||
if subcontext.is_a() == "IfcGeometricRepresentationContext":
|
||||
context_of_items = self.file.by_id(representation.ifc_definition_id).ContextOfItems
|
||||
if context_of_items.is_a() == "IfcGeometricRepresentationContext":
|
||||
continue
|
||||
# TODO: reimplement with incremental editing
|
||||
# op = row.operator("bim.switch_context", icon="OUTLINER_DATA_MESH", text="")
|
||||
# op.has_target_context = True
|
||||
# op.context_name = subcontext.ContextType
|
||||
# op.subcontext_name = subcontext.ContextIdentifier
|
||||
# op.target_view_name = subcontext.TargetView
|
||||
# row.operator("bim.remove_context", icon="X", text="").index = index
|
||||
op = row.operator("bim.switch_representation", icon="OUTLINER_DATA_MESH", text="")
|
||||
op.ifc_definition_id = representation.ifc_definition_id
|
||||
row.operator("bim.remove_representation", icon="X", text="").index = index
|
||||
|
||||
|
||||
class BIM_PT_classification_references(Panel):
|
||||
|
||||
@@ -93,3 +93,32 @@ def replace_attribute(element, old, new):
|
||||
if item == old:
|
||||
new_attribute[j] = new
|
||||
element[i] = new_attribute
|
||||
|
||||
|
||||
def is_representation_of_context(representation, context, subcontext=None, target_view=None):
|
||||
if target_view is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.TargetView == target_view
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif subcontext is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif representation.ContextOfItems.ContextType == context:
|
||||
return True
|
||||
|
||||
|
||||
def get_representation(element, context, subcontext=None, target_view=None):
|
||||
if element.is_a("IfcProduct") and element.Representation:
|
||||
for r in element.Representation.Representations:
|
||||
if is_representation_of_context(r, context, subcontext, target_view):
|
||||
return r
|
||||
elif element.is_a("IfcTypeProduct") and element.RepresentationMaps:
|
||||
for r in element.RepresentationMaps:
|
||||
if is_representation_of_context(r.MappedRepresentation, context, subcontext, target_view):
|
||||
return r.MappedRepresentation
|
||||
|
||||
Reference in New Issue
Block a user