bim.add_material_set to ensure adding valid material sets

This commit is contained in:
Andrej730
2024-09-02 18:33:10 +05:00
parent 90e9c21320
commit c6e8d2a585
7 changed files with 91 additions and 1 deletions
@@ -156,6 +156,7 @@ class DuplicateMaterial(bpy.types.Operator, tool.Ifc.Operator):
class AddMaterialSet(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_material_set"
bl_label = "Add Material Set"
bl_description = "Create a new material set, will use a default material/profile as a placeholder"
bl_options = {"REGISTER", "UNDO"}
set_type: bpy.props.StringProperty()
+1
View File
@@ -40,6 +40,7 @@ def add_material(
def add_material_set(ifc: tool.Ifc, material: tool.Material, set_type: str) -> ifcopenshell.entity_instance:
ifc_material = ifc.run("material.add_material_set", name="Unnamed", set_type=set_type)
material.ensure_new_material_set_is_valid(ifc_material)
if material.is_editing_materials():
material.import_material_definitions(material.get_active_material_type())
return ifc_material
+1
View File
@@ -510,6 +510,7 @@ class Material:
def enable_editing_materials(cls): pass
def ensure_material_assigned(cls, elements, material_type, material): pass
def ensure_material_unassigned(cls, elements): pass
def ensure_new_material_set_is_valid(cls, material): pass
def get_active_material_item(cls): pass
def get_active_material_type(cls): pass
def get_default_material(cls): pass
+37 -1
View File
@@ -27,7 +27,8 @@ import bonsai.bim.helper
import ifcopenshell.util.unit
import ifcopenshell.util.element
from collections import defaultdict
from typing import Union, Any, TYPE_CHECKING, Optional
from typing import Union, Any, TYPE_CHECKING, Optional, Literal
from typing_extensions import assert_never
if TYPE_CHECKING:
# Avoid circular imports.
@@ -352,3 +353,38 @@ class Material(bonsai.core.tool.Material):
elements.extend(tool.Model.get_occurrences_without_material_override(element))
tool.Model.apply_ifc_material_changes(elements, assigned_material=assigned_material)
@classmethod
def ensure_new_material_set_is_valid(cls, material: ifcopenshell.entity_instance) -> None:
material_type = material.is_a()
ifc_file = tool.Ifc.get()
default_material = cls.get_default_material()
if material_type == "IfcMaterialConstituentSet":
material_constituent = ifcopenshell.api.material.add_constituent(
ifc_file,
constituent_set=material,
material=default_material,
)
material.MaterialConstituents = [material_constituent]
elif material_type == "IfcMaterialLayerSet":
material_layer = ifcopenshell.api.material.add_layer(
ifc_file,
layer_set=material,
material=default_material,
)
material.MaterialLayers = [material_layer]
elif material_type == "IfcMaterialProfileSet":
profile = tool.Profile.get_default_profile()
material_profile = ifcopenshell.api.material.add_profile(
ifc_file,
profile_set=material,
profile=profile,
material=None,
)
material.MaterialProfiles = [material_profile]
elif material_type == "IfcMaterialList":
material.Materials = [default_material]
else:
assert False, f"Invalid material type found: {material_type}."
+16
View File
@@ -17,6 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell
import ifcopenshell.api.profile
import ifcopenshell.geom
import ifcopenshell.util.element
import ifcopenshell.util.unit
@@ -78,6 +79,21 @@ class Profile(bonsai.core.tool.Profile):
return profile
return None
@classmethod
def get_default_profile(cls) -> ifcopenshell.entity_instance:
"""Return first found IfcProfileDef in IFC file or create a new default profile."""
ifc_file = tool.Ifc.get()
profile = next(iter(ifc_file.by_type("IfcProfileDef")), None)
if profile:
return profile
profile = ifcopenshell.api.profile.add_parameterized_profile(ifc_file, ifc_class="IfcRectangleProfileDef")
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
profile.ProfileType = "AREA"
profile.ProfileName = "Default Profile"
profile.XDim = 0.1 / si_conversion
profile.YDim = 0.1 / si_conversion
return profile
@classmethod
def get_model_profiles(cls) -> list[ifcopenshell.entity_instance]:
return tool.Ifc.get().by_type("IfcProfileDef")
+2
View File
@@ -49,6 +49,7 @@ class TestAddMaterialSet:
ifc.run("material.add_material_set", name="Unnamed", set_type="set_type").should_be_called().will_return(
"material"
)
material.ensure_new_material_set_is_valid("material").should_be_called()
material.is_editing_materials().should_be_called().will_return(False)
assert subject.add_material_set(ifc, material, set_type="set_type") == "material"
@@ -56,6 +57,7 @@ class TestAddMaterialSet:
ifc.run("material.add_material_set", name="Unnamed", set_type="set_type").should_be_called().will_return(
"material"
)
material.ensure_new_material_set_is_valid("material").should_be_called()
material.is_editing_materials().should_be_called().will_return(True)
material.get_active_material_type().should_be_called().will_return("material_type")
material.import_material_definitions("material_type").should_be_called()
+33
View File
@@ -150,3 +150,36 @@ class TestIsMaterialUsedInSets(NewFile):
material_set.MaterialLayers = [material_set_item]
material_set_item.Material = material
assert subject.is_material_used_in_sets(material) is True
class TestEnsureNewMaterialSetIsValid(NewFile):
def test_material_constituent_set(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
material_set = ifc.create_entity("IfcMaterialConstituentSet")
subject.ensure_new_material_set_is_valid(material_set)
assert len(constituents := material_set.MaterialConstituents) == 1
assert constituents[0].Material
def test_material_layer_set(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
material_set = ifc.create_entity("IfcMaterialLayerSet")
subject.ensure_new_material_set_is_valid(material_set)
assert len(layers := material_set.MaterialLayers) == 1
assert layers[0].Material
def test_material_profile_set(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
material_set = ifc.create_entity("IfcMaterialProfileSet")
subject.ensure_new_material_set_is_valid(material_set)
assert len(profiles := material_set.MaterialProfiles) == 1
assert profiles[0].Profile
def test_material_list(self):
ifc = ifcopenshell.file()
tool.Ifc.set(ifc)
material_set = ifc.create_entity("IfcMaterialList")
subject.ensure_new_material_set_is_valid(material_set)
assert len(material_set.Materials) == 1