mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Fix #3973. Fix #4787. Clarify that you cannot have aggregated physical elements where the whole has a body representation.
This commit is contained in:
@@ -55,21 +55,24 @@ class BIM_OT_aggregate_assign_object(bpy.types.Operator, Operator):
|
|||||||
if not relating_obj:
|
if not relating_obj:
|
||||||
return
|
return
|
||||||
|
|
||||||
for obj in bpy.context.selected_objects + [bpy.context.active_object]:
|
for obj in tool.Blender.get_selected_objects():
|
||||||
if obj == relating_obj:
|
if obj == relating_obj:
|
||||||
continue
|
continue
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
continue
|
continue
|
||||||
result = core.assign_object(
|
try:
|
||||||
tool.Ifc,
|
core.assign_object(
|
||||||
tool.Aggregate,
|
tool.Ifc,
|
||||||
tool.Collector,
|
tool.Aggregate,
|
||||||
relating_obj=relating_obj,
|
tool.Collector,
|
||||||
related_obj=obj,
|
relating_obj=relating_obj,
|
||||||
)
|
related_obj=obj,
|
||||||
if not result:
|
)
|
||||||
self.report({"ERROR"}, f" Cannot aggregate {obj.name} to {relating_obj.name}")
|
except core.IncompatibleAggregateError:
|
||||||
|
self.report({"ERROR"}, f"Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||||
|
except core.AggregateRepresentationError:
|
||||||
|
self.report({"ERROR"}, f"Cannot aggregate to {relating_obj.name} with a body representation")
|
||||||
|
|
||||||
|
|
||||||
class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator):
|
class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator):
|
||||||
|
|||||||
@@ -41,9 +41,12 @@ def assign_object(
|
|||||||
related_obj: Optional[bpy.types.Object] = None,
|
related_obj: Optional[bpy.types.Object] = None,
|
||||||
) -> Union[ifcopenshell.entity_instance, None]:
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
if not aggregator.can_aggregate(relating_obj, related_obj):
|
if not aggregator.can_aggregate(relating_obj, related_obj):
|
||||||
return
|
raise IncompatibleAggregateError
|
||||||
|
relating_object = ifc.get_entity(relating_obj)
|
||||||
|
if aggregator.has_physical_body_representation(relating_object):
|
||||||
|
raise AggregateRepresentationError
|
||||||
rel = ifc.run(
|
rel = ifc.run(
|
||||||
"aggregate.assign_object", products=[ifc.get_entity(related_obj)], relating_object=ifc.get_entity(relating_obj)
|
"aggregate.assign_object", products=[ifc.get_entity(related_obj)], relating_object=relating_object
|
||||||
)
|
)
|
||||||
collector.assign(relating_obj)
|
collector.assign(relating_obj)
|
||||||
collector.assign(related_obj)
|
collector.assign(related_obj)
|
||||||
@@ -84,3 +87,11 @@ def add_part_to_object(
|
|||||||
part_obj = blender.create_ifc_object(ifc_class=part_class, name=part_name)
|
part_obj = blender.create_ifc_object(ifc_class=part_class, name=part_name)
|
||||||
assign_object(ifc, aggregator, collector, relating_obj=obj, related_obj=part_obj)
|
assign_object(ifc, aggregator, collector, relating_obj=obj, related_obj=part_obj)
|
||||||
blender.set_active_object(obj)
|
blender.set_active_object(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class IncompatibleAggregateError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AggregateRepresentationError(Exception):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ class Aggregate(blenderbim.core.tool.Aggregate):
|
|||||||
related_object = tool.Ifc.get_entity(related_obj)
|
related_object = tool.Ifc.get_entity(related_obj)
|
||||||
if not relating_object or not related_object:
|
if not relating_object or not related_object:
|
||||||
return False
|
return False
|
||||||
if (relating_object.is_a("IfcElement") or relating_object.is_a("IfcElementType")) and related_object.is_a("IfcElement"):
|
if (relating_object.is_a("IfcElement") or relating_object.is_a("IfcElementType")) and related_object.is_a(
|
||||||
if relating_obj.data: # See #3973
|
"IfcElement"
|
||||||
return False
|
):
|
||||||
return True
|
return True
|
||||||
if tool.Ifc.get_schema() == "IFC2X3":
|
if tool.Ifc.get_schema() == "IFC2X3":
|
||||||
if relating_object.is_a("IfcSpatialStructureElement") and related_object.is_a("IfcSpatialStructureElement"):
|
if relating_object.is_a("IfcSpatialStructureElement") and related_object.is_a("IfcSpatialStructureElement"):
|
||||||
@@ -46,6 +46,13 @@ class Aggregate(blenderbim.core.tool.Aggregate):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def has_physical_body_representation(cls, element: ifcopenshell.entity_instance) -> bool:
|
||||||
|
if element.is_a("IfcElement") or element.is_a("IfcElementType"): # See 3973
|
||||||
|
if ifcopenshell.util.representation.get_representation(element, "Model", "Body"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def disable_editing(cls, obj: bpy.types.Object) -> None:
|
def disable_editing(cls, obj: bpy.types.Object) -> None:
|
||||||
obj.BIMObjectAggregateProperties.is_editing = False
|
obj.BIMObjectAggregateProperties.is_editing = False
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.root
|
||||||
|
import ifcopenshell.api.unit
|
||||||
|
import ifcopenshell.api.context
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from test.bim.bootstrap import NewFile
|
from test.bim.bootstrap import NewFile
|
||||||
@@ -92,16 +95,24 @@ class TestCanAggregate(NewFile):
|
|||||||
subelement_obj = bpy.data.objects.new("Object", None)
|
subelement_obj = bpy.data.objects.new("Object", None)
|
||||||
assert subject.can_aggregate(element_obj, subelement_obj) is False
|
assert subject.can_aggregate(element_obj, subelement_obj) is False
|
||||||
|
|
||||||
def test_aggregates_with_meshes_are_invalid(self):
|
|
||||||
|
class TestHasPhysicalBodyRepresentation(NewFile):
|
||||||
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
tool.Ifc.set(ifc)
|
|
||||||
element = ifc.createIfcElementAssembly()
|
element = ifc.createIfcElementAssembly()
|
||||||
element_obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
assert subject.has_physical_body_representation(element) is False
|
||||||
tool.Ifc.link(element, element_obj)
|
ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcProject")
|
||||||
subelement = ifc.createIfcBeam()
|
ifcopenshell.api.unit.assign_unit(ifc)
|
||||||
subelement_obj = bpy.data.objects.new("Object", None)
|
context = ifcopenshell.api.context.add_context(ifc, context_type="Model")
|
||||||
tool.Ifc.link(subelement, subelement_obj)
|
body = ifcopenshell.api.context.add_context(
|
||||||
assert subject.can_aggregate(element_obj, subelement_obj) is False
|
ifc, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context
|
||||||
|
)
|
||||||
|
builder = ifcopenshell.util.shape_builder.ShapeBuilder(ifc)
|
||||||
|
origin = builder.create_axis2_placement_3d()
|
||||||
|
block = ifc.createIfcCsgSolid(ifc.createIfcBlock(origin, 200, 200, 200))
|
||||||
|
rep = builder.get_representation(context=body, items=[block])
|
||||||
|
ifcopenshell.api.geometry.assign_representation(ifc, product=element, representation=rep)
|
||||||
|
assert subject.has_physical_body_representation(element) is True
|
||||||
|
|
||||||
|
|
||||||
class TestDisableEditing(NewFile):
|
class TestDisableEditing(NewFile):
|
||||||
|
|||||||
Reference in New Issue
Block a user