This commit is contained in:
Andrej730
2025-03-06 16:11:58 +05:00
parent 7458040949
commit 79940641b2
6 changed files with 38 additions and 25 deletions
@@ -561,9 +561,12 @@ class EditAssignedMaterial(bpy.types.Operator, tool.Ifc.Operator):
def _execute(self, context):
self.file = tool.Ifc.get()
active_obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
assert active_obj
props = active_obj.BIMObjectMaterialProperties
element = tool.Ifc.get_entity(active_obj)
assert element
material = ifcopenshell.util.element.get_material(element)
assert material
objects = tool.Blender.get_selected_objects()
+17 -9
View File
@@ -50,7 +50,7 @@ from bonsai.bim.module.geometry.helper import Helper
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData, WindowData, DoorData
from bonsai.bim.module.model.opening import FilledOpeningGenerator
from ifcopenshell.util.shape_builder import ShapeBuilder
from typing import Optional, Union, TypeVar, Any, Iterable, Literal, TYPE_CHECKING, Sequence
from typing import Optional, Union, TypeVar, Any, Iterable, Literal, TYPE_CHECKING, Sequence, TypedDict
T = TypeVar("T")
V_ = tool.Blender.V_
@@ -603,8 +603,16 @@ class Model(bonsai.core.tool.Model):
if not openings[i].obj:
openings.remove(i)
class MaterialLayerParameters(TypedDict):
"""Float values are in project units."""
layer_set_direction: Literal["AXIS1", "AXIS2", "AXIS3"]
thickness: float
offset: float
direction_sense: Literal["NEGATIVE", "POSITIVE"]
@classmethod
def get_material_layer_parameters(cls, element: ifcopenshell.entity_instance) -> dict[str, Any]:
def get_material_layer_parameters(cls, element: ifcopenshell.entity_instance) -> MaterialLayerParameters:
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
layer_set_direction = "AXIS2"
offset = 0.0
@@ -619,12 +627,12 @@ class Model(bonsai.core.tool.Model):
material = material.ForLayerSet
if material.is_a("IfcMaterialLayerSet"):
thickness = sum([l.LayerThickness for l in material.MaterialLayers]) * unit_scale
return {
"layer_set_direction": layer_set_direction,
"thickness": thickness,
"offset": offset,
"direction_sense": direction_sense,
}
return cls.MaterialLayerParameters(
layer_set_direction=layer_set_direction,
thickness=thickness,
offset=offset,
direction_sense=direction_sense,
)
@classmethod
def get_booleans(
@@ -2045,7 +2053,7 @@ class Model(bonsai.core.tool.Model):
FilledOpeningGenerator().generate(filling_obj, voided_obj)
@classmethod
def add_extrusion_position(cls, extrusion: ifcopenshell.entity_instance, position: tuple) -> None:
def add_extrusion_position(cls, extrusion: ifcopenshell.entity_instance, position: Vector) -> None:
ifc_file = tool.Ifc.get()
new_position = ifc_file.createIfcAxis2Placement3D(
@@ -18,6 +18,7 @@
import ifcopenshell
import ifcopenshell.api.pset
import ifcopenshell.util.element
from typing import Optional, Any
@@ -54,9 +54,7 @@ def copy_class(file: ifcopenshell.file, product: ifcopenshell.entity_instance) -
connections are still valid.
:param product: The IfcProduct to copy.
:type param: ifcopenshell.entity_instance
:return: The copied product
:rtype: ifcopenshell.entity_instance
Example:
@@ -70,26 +68,26 @@ def copy_class(file: ifcopenshell.file, product: ifcopenshell.entity_instance) -
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"product": product}
return usecase.execute()
return usecase.execute(product)
class Usecase:
file: ifcopenshell.file
settings: dict[str, Any]
def execute(self):
result = ifcopenshell.util.element.copy(self.file, self.settings["product"])
def execute(self, product: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
result = ifcopenshell.util.element.copy(self.file, product)
self.copy_direct_attributes(result)
self.copy_indirect_attributes(self.settings["product"], result)
self.copy_indirect_attributes(product, result)
return result
def copy_direct_attributes(self, to_element):
def copy_direct_attributes(self, to_element: ifcopenshell.entity_instance) -> None:
self.remove_representations(to_element)
self.copy_object_placements(to_element)
self.copy_psets(to_element)
def copy_indirect_attributes(self, from_element, to_element):
def copy_indirect_attributes(
self, from_element: ifcopenshell.entity_instance, to_element: ifcopenshell.entity_instance
) -> None:
for inverse in self.file.get_inverse(from_element):
if inverse.is_a("IfcRelDefinesByProperties"):
# Properties must not be shared between objects for convenience of authoring
@@ -175,13 +173,13 @@ class Usecase:
new_value.append(to_element)
inverse[i] = new_value
def remove_representations(self, element):
def remove_representations(self, element: ifcopenshell.entity_instance) -> None:
if element.is_a("IfcProduct"):
element.Representation = None
elif element.is_a("IfcTypeProduct"):
element.RepresentationMaps = None
def copy_object_placements(self, element):
def copy_object_placements(self, element: ifcopenshell.entity_instance) -> None:
if not element.is_a("IfcProduct") or not element.ObjectPlacement:
return
element.ObjectPlacement = ifcopenshell.util.element.copy(self.file, element.ObjectPlacement)
@@ -189,7 +187,7 @@ class Usecase:
self.file, element.ObjectPlacement.RelativePlacement
)
def copy_psets(self, element):
def copy_psets(self, element: ifcopenshell.entity_instance) -> None:
if not element.is_a("IfcTypeObject") or not element.HasPropertySets:
return
element.HasPropertySets = [
@@ -20,7 +20,6 @@ from fractions import Fraction
from math import pi
from typing import Any
from typing import Dict
from typing import Iterable
from typing import Literal
from typing import Optional
from typing import Union
@@ -821,7 +820,8 @@ def iter_element_and_attributes_per_type(ifc_file: ifcopenshell.file, attr_type_
for element in ifc_file:
entity = schema.declaration_by_name(element.is_a())
attrs = entity.all_attributes()
for attr, val, is_derived in zip(attrs, list(element), entity.derived()):
attrs_derived: tuple[bool, ...] = entity.derived()
for attr, val, is_derived in zip(attrs, list(element), attrs_derived):
if is_derived:
continue
@@ -877,7 +877,7 @@ def convert_file_length_units(ifc_file: ifcopenshell.file, target_units: str = "
new_length = ifcopenshell.api.unit.add_conversion_based_unit(file_patched, name=target_units)
# support tuple of tuples, as in IfcCartesianPointList3D.CoordList
def convert_value(value):
def convert_value(value: FloatOrSequenceOfFloats) -> FloatOrSequenceOfFloats:
if not isinstance(value, tuple):
return convert_unit(value, old_length, new_length)
return tuple(convert_value(v) for v in value)
@@ -18,9 +18,12 @@
import test.bootstrap
import numpy as np
import ifcopenshell.api.context
import ifcopenshell.api.unit
import ifcopenshell.api.root
import ifcopenshell.api.georeference
import ifcopenshell.api.pset
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.unit as subject
from ifcopenshell.util.shape_builder import ShapeBuilder