mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Column profiles now auto update when you change the material profile
This commit is contained in:
@@ -396,7 +396,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
def get_classes(self, element, position, svg_writer):
|
||||
classes = [position, element.is_a()]
|
||||
material = ifcopenshell.util.element.get_material(element)
|
||||
material = ifcopenshell.util.element.get_material(element, should_skip_usage=True)
|
||||
if material:
|
||||
classes.append("material-{}".format(re.sub("[^0-9a-zA-Z]+", "", self.get_material_name(material))))
|
||||
classes.append("globalid-{}".format(element.GlobalId))
|
||||
|
||||
@@ -58,7 +58,7 @@ class AddRepresentation(bpy.types.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
context_id: bpy.props.IntProperty()
|
||||
ifc_representation_class: bpy.props.StringProperty()
|
||||
profile_set: bpy.props.IntProperty()
|
||||
profile_set_usage: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
@@ -94,7 +94,7 @@ class AddRepresentation(bpy.types.Operator):
|
||||
"should_force_faceted_brep": context.scene.BIMGeometryProperties.should_force_faceted_brep,
|
||||
"should_force_triangulation": context.scene.BIMGeometryProperties.should_force_triangulation,
|
||||
"ifc_representation_class": self.ifc_representation_class,
|
||||
"profile_set": self.file.by_id(self.profile_set) if self.profile_set else None
|
||||
"profile_set_usage": self.file.by_id(self.profile_set_usage) if self.profile_set_usage else None
|
||||
}
|
||||
|
||||
result = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data)
|
||||
|
||||
@@ -46,11 +46,11 @@ def ensure_solid(usecase_path, ifc_file, settings):
|
||||
if not parametric or parametric["Engine"] != "BlenderBIM.DumbColumn":
|
||||
return
|
||||
material = ifcopenshell.util.element.get_material(product)
|
||||
if material and material.is_a("IfcMaterialProfileSet"):
|
||||
settings["profile_set"] = material
|
||||
if material and material.is_a("IfcMaterialProfileSetUsage"):
|
||||
settings["profile_set_usage"] = material
|
||||
else:
|
||||
return
|
||||
settings["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcMaterialProfileSet"
|
||||
settings["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage"
|
||||
|
||||
|
||||
class DumbColumnGenerator:
|
||||
@@ -110,20 +110,51 @@ class DumbColumnGenerator:
|
||||
bpy.ops.bim.assign_class(
|
||||
obj=obj.name, ifc_class="IfcColumn", predefined_type="COLUMN", should_add_representation=False
|
||||
)
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
||||
profile_set_usage = ifcopenshell.util.element.get_material(element)
|
||||
bpy.ops.bim.add_representation(
|
||||
obj=obj.name,
|
||||
context_id=ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW").id(),
|
||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcMaterialProfileSet",
|
||||
profile_set=self.profile_set.id(),
|
||||
)
|
||||
representation = ifcopenshell.util.representation.get_representation(
|
||||
self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "Model", "Body", "MODEL_VIEW"
|
||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage",
|
||||
profile_set_usage=profile_set_usage.id(),
|
||||
)
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
bpy.ops.bim.switch_representation(obj=obj.name, ifc_definition_id=representation.id(), should_reload=True)
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric")
|
||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbColumn"})
|
||||
MaterialData.load(self.file)
|
||||
obj.select_set(True)
|
||||
return obj
|
||||
|
||||
|
||||
class DumbColumnRegenerator:
|
||||
def regenerate_from_profile(self, usecase_path, ifc_file, settings):
|
||||
self.file = IfcStore.get_file()
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
||||
profile = settings["profile"].Profile
|
||||
if not profile:
|
||||
return
|
||||
for profile_set in [
|
||||
mp.ToMaterialProfileSet[0] for mp in self.file.get_inverse(profile) if mp.is_a("IfcMaterialProfile")
|
||||
]:
|
||||
for inverse in ifc_file.get_inverse(profile_set):
|
||||
if not inverse.is_a("IfcMaterialProfileSetUsage"):
|
||||
continue
|
||||
if ifc_file.schema == "IFC2X3":
|
||||
for rel in ifc_file.get_inverse(inverse):
|
||||
if not rel.is_a("IfcRelAssociatesMaterial"):
|
||||
continue
|
||||
for element in rel.RelatedObjects:
|
||||
self.change_profile(element)
|
||||
else:
|
||||
for rel in inverse.AssociatedTo:
|
||||
for element in rel.RelatedObjects:
|
||||
self.change_profile(element)
|
||||
|
||||
def change_profile(self, element):
|
||||
obj = IfcStore.get_element(element.id())
|
||||
if not obj:
|
||||
return
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
bpy.ops.bim.switch_representation(obj=obj.name, ifc_definition_id=representation.id(), should_reload=True)
|
||||
|
||||
@@ -50,3 +50,8 @@ def load_post(*args):
|
||||
ifcopenshell.api.add_pre_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbColumn.EnsureSolid", column.ensure_solid
|
||||
)
|
||||
ifcopenshell.api.add_post_listener(
|
||||
"material.edit_profile",
|
||||
"BlenderBIM.DumbColumn.RegenerateFromProfile",
|
||||
column.DumbColumnRegenerator().regenerate_from_profile,
|
||||
)
|
||||
|
||||
@@ -30,9 +30,9 @@ class Usecase:
|
||||
# IfcExtrudedAreaSolid/IfcCircleProfileDef
|
||||
# IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef
|
||||
# IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids
|
||||
# IfcExtrudedAreaSolid/IfcMaterialProfileSet
|
||||
# IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage
|
||||
"ifc_representation_class": None, # Whether to cast a mesh into a particular class
|
||||
"profile_set": None, # The material profile set if the extrusion requires it
|
||||
"profile_set_usage": None, # The material profile set if the extrusion requires it
|
||||
}
|
||||
self.ifc_vertices = []
|
||||
for key, value in settings.items():
|
||||
@@ -220,7 +220,7 @@ class Usecase:
|
||||
return self.create_arbitrary_extrusion_representation()
|
||||
elif self.settings["ifc_representation_class"] == "IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids":
|
||||
return self.create_arbitrary_void_extrusion_representation()
|
||||
elif self.settings["ifc_representation_class"] == "IfcExtrudedAreaSolid/IfcMaterialProfileSet":
|
||||
elif self.settings["ifc_representation_class"] == "IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage":
|
||||
return self.create_material_profile_set_extrusion_representation()
|
||||
return self.create_mesh_representation()
|
||||
|
||||
@@ -410,10 +410,8 @@ class Usecase:
|
||||
)
|
||||
|
||||
def create_material_profile_set_extrusion_representation(self):
|
||||
profile_def = (
|
||||
self.settings["profile_set"].CompositeProfile
|
||||
or self.settings["profile_set"].MaterialProfiles[0].Profile
|
||||
)
|
||||
profile_set = self.settings["profile_set_usage"].ForProfileSet
|
||||
profile_def = profile_set.CompositeProfile or profile_set.MaterialProfiles[0].Profile
|
||||
position = None
|
||||
if self.file.schema == "IFC2X3":
|
||||
position = self.file.createIfcAxis2Placement3D(
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import ifcopenshell.util.representation
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -6,9 +9,28 @@ class Usecase:
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if (
|
||||
self.settings["material_profile"].Profile
|
||||
and len(self.file.get_inverse(self.settings["material_profile"].Profile)) == 1
|
||||
):
|
||||
self.file.remove(self.settings["material_profile"].Profile)
|
||||
old_profile = self.settings["material_profile"].Profile
|
||||
self.settings["material_profile"].Profile = self.settings["profile"]
|
||||
for profile_set in self.settings["material_profile"].ToMaterialProfileSet:
|
||||
for inverse in self.file.get_inverse(profile_set):
|
||||
if not inverse.is_a("IfcMaterialProfileSetUsage"):
|
||||
continue
|
||||
if self.file.schema == "IFC2X3":
|
||||
for rel in self.file.get_inverse(inverse):
|
||||
if not rel.is_a("IfcRelAssociatesMaterial"):
|
||||
continue
|
||||
for element in rel.RelatedObjects:
|
||||
self.change_profile(element)
|
||||
else:
|
||||
for rel in inverse.AssociatedTo:
|
||||
for element in rel.RelatedObjects:
|
||||
self.change_profile(element)
|
||||
|
||||
if old_profile and len(self.file.get_inverse(old_profile)) == 0:
|
||||
self.file.remove(old_profile)
|
||||
|
||||
def change_profile(self, element):
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
for subelement in self.file.traverse(representation):
|
||||
if subelement.is_a("IfcSweptAreaSolid"):
|
||||
subelement.SweptArea = self.settings["profile"]
|
||||
|
||||
@@ -62,14 +62,15 @@ def get_type(element):
|
||||
return relationship.RelatingType
|
||||
|
||||
|
||||
def get_material(element):
|
||||
def get_material(element, should_skip_usage=False):
|
||||
if hasattr(element, "HasAssociations") and element.HasAssociations:
|
||||
for relationship in element.HasAssociations:
|
||||
if relationship.is_a("IfcRelAssociatesMaterial"):
|
||||
if relationship.RelatingMaterial.is_a("IfcMaterialLayerSetUsage"):
|
||||
return relationship.RelatingMaterial.ForLayerSet
|
||||
elif relationship.RelatingMaterial.is_a("IfcMaterialProfileSetUsage"):
|
||||
return relationship.RelatingMaterial.ForProfileSet
|
||||
if should_skip_usage:
|
||||
if relationship.RelatingMaterial.is_a("IfcMaterialLayerSetUsage"):
|
||||
return relationship.RelatingMaterial.ForLayerSet
|
||||
elif relationship.RelatingMaterial.is_a("IfcMaterialProfileSetUsage"):
|
||||
return relationship.RelatingMaterial.ForProfileSet
|
||||
return relationship.RelatingMaterial
|
||||
relating_type = get_type(element)
|
||||
if hasattr(relating_type, "HasAssociations") and relating_type.HasAssociations:
|
||||
|
||||
@@ -221,7 +221,7 @@ class Selector:
|
||||
key = ".".join(key.split(".")[1:])
|
||||
elif "." in key and key.split(".")[0] == "material":
|
||||
try:
|
||||
element = ifcopenshell.util.element.get_material(element)
|
||||
element = ifcopenshell.util.element.get_material(element, should_skip_usage=True)
|
||||
if not element:
|
||||
return None
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user