From 1d523c9636b7953f61e36c64ccca75043338ac47 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 10 Jul 2021 22:06:11 +1000 Subject: [PATCH] Implement assigning material definition representation styles --- .../bim/module/geometry/operator.py | 4 +- .../bim/module/material/operator.py | 9 ++ .../blenderbim/bim/module/style/operator.py | 9 ++ .../api/material/remove_material.py | 1 + .../api/style/assign_material_style.py | 83 +++++++++++++++++++ .../assign_representation_styles.py} | 6 +- 6 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py rename src/ifcopenshell-python/ifcopenshell/api/{geometry/assign_styles.py => style/assign_representation_styles.py} (86%) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 2a51ab4de2..fccaec2288 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -118,7 +118,7 @@ class AddRepresentation(bpy.types.Operator): ] ifcopenshell.api.run( - "geometry.assign_styles", + "style.assign_representation_styles", self.file, **{ "shape_representation": result, @@ -331,7 +331,7 @@ class UpdateRepresentation(bpy.types.Operator): ] ifcopenshell.api.run( - "geometry.assign_styles", + "style.assign_representation_styles", self.file, **{ "shape_representation": new_representation, diff --git a/src/blenderbim/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py index 71514509f1..ebeba9e020 100644 --- a/src/blenderbim/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -2,6 +2,7 @@ import bpy import json import ifcopenshell.api import ifcopenshell.util.attribute +import ifcopenshell.util.representation import blenderbim.bim.helper from blenderbim.bim.module.material.prop import purge as material_prop_purge from blenderbim.bim.ifc import IfcStore @@ -53,6 +54,14 @@ class AddMaterial(bpy.types.Operator): self.file = IfcStore.get_file() result = ifcopenshell.api.run("material.add_material", self.file, **{"name": obj.name}) obj.BIMObjectProperties.ifc_definition_id = result.id() + if obj.BIMMaterialProperties.ifc_style_id: + context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW") + if context: + ifcopenshell.api.run("style.assign_material_style", self.file, **{ + "material": result, + "style": self.file.by_id(obj.BIMMaterialProperties.ifc_style_id), + "context": context, + }) Data.load(IfcStore.get_file()) material_prop_purge() return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 43ef806e56..8cb56ada3c 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -1,5 +1,6 @@ import bpy import ifcopenshell.api +import ifcopenshell.util.representation import blenderbim.bim.helper from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.style.data import Data @@ -74,6 +75,14 @@ class AddStyle(bpy.types.Operator): settings["external_definition"] = None # TODO: Implement. See #1222 style = ifcopenshell.api.run("style.add_style", self.file, **settings) material.BIMMaterialProperties.ifc_style_id = style.id() + if material.BIMObjectProperties.ifc_definition_id: + context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW") + if context: + ifcopenshell.api.run("style.assign_material_style", self.file, **{ + "material": self.file.by_id(material.BIMObjectProperties.ifc_definition_id), + "style": style, + "context": context, + }) return {"FINISHED"} diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py index 39ed5c0a68..327878c58c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py @@ -12,6 +12,7 @@ class Usecase: inverse_elements = self.file.get_inverse(self.settings["material"]) self.file.remove(self.settings["material"]) # TODO: this is probably not robust enough + # TODO: purge material definition representation for inverse in inverse_elements: if inverse.is_a("IfcMaterialConstituent"): self.file.remove(inverse) diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py new file mode 100644 index 0000000000..b626740cde --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py @@ -0,0 +1,83 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "material": None, + "style": None, + "context": None, + "should_use_presentation_style_assignment": False, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.style = self.settings["style"] + if self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]: + self.style = self.file.createIfcPresentationStyleAssignment([self.settings["style"]]) + + if self.settings["material"].HasRepresentation: + self.modify_existing_definition_representation() + else: + self.create_new_definition_representation() + + def modify_existing_definition_representation(self): + definition_representation = self.settings["material"].HasRepresentation[0] + representation = self.get_styled_representation(definition_representation) + if representation: + potential_orphans = [] + items = list(representation.Items) + new_items = [] + removed_items = [] + for item in items: + if not i.is_a("IfcStyledItem"): + continue + if self.has_proposed_style(item): + return + if self.has_same_style_type(item): + removed_items.append(item) + else: + new_items.append(item) + new_items.append(self.create_styled_item()) + representation.Items = new_items + for item in removed_items: + if len(self.file.get_inverse(item)) == 0: + self.file.remove(item) + else: + representations = list(definition_representation.Representations) + representations.append(self.create_styled_representation()) + definition_representation.Representations = representations + + def has_proposed_style(self, styled_item): + return bool([s for s in styled_item.Styles if s == self.settings["style"]]) + + def has_same_style_type(self, styled_item): + return bool([s for s in styled_item.Styles if s.is_a() == self.settings["style"].is_a()]) + + def create_new_definition_representation(self): + representation = self.create_styled_representation() + definition_representation = self.file.create_entity( + "IfcMaterialDefinitionRepresentation", + **{"Representations": [representation], "RepresentedMaterial": self.settings["material"]} + ) + + def get_styled_representation(self, definition_representation): + representations = [ + r + for r in definition_representation.Representations is r.is_a("IfcStyledRepresentation") + and r.ContextOfItems == self.settings["context"] + ] + if representations: + return representations[0] + + def create_styled_representation(self): + return self.file.create_entity( + "IfcStyledRepresentation", + **{ + "ContextOfItems": self.settings["context"], + "RepresentationIdentifier": self.settings["context"].ContextIdentifier, + "Items": [self.create_styled_item()], + } + ) + + def create_styled_item(self): + return self.file.create_entity("IfcStyledItem", **{"Styles": [self.style], "Name": self.settings["style"].Name}) diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py b/src/ifcopenshell-python/ifcopenshell/api/style/assign_representation_styles.py similarity index 86% rename from src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py rename to src/ifcopenshell-python/ifcopenshell/api/style/assign_representation_styles.py index 2fbc699a6c..fc7109845b 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/assign_representation_styles.py @@ -23,9 +23,5 @@ class Usecase: name = style.Name if self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]: style = self.file.createIfcPresentationStyleAssignment([style]) - self.results.append( - self.file.createIfcStyledItem( - item, [style], name - ) - ) + self.results.append(self.file.createIfcStyledItem(item, [style], name)) return self.results