mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Fix #4267 and add tests
Crash was caused by unmark_manual_booleans accessing boolean element after they were deleted from IFC
This commit is contained in:
@@ -668,17 +668,17 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
||||
except:
|
||||
continue
|
||||
|
||||
boolean = None
|
||||
boolean_id = None
|
||||
for inverse in tool.Ifc.get().get_inverse(item):
|
||||
if inverse.is_a("IfcBooleanResult"):
|
||||
boolean = inverse
|
||||
boolean_id = inverse.id()
|
||||
break
|
||||
ifcopenshell.api.run("geometry.remove_boolean", tool.Ifc.get(), item=item)
|
||||
|
||||
if obj.data.BIMMeshProperties.obj:
|
||||
upstream_obj = obj.data.BIMMeshProperties.obj
|
||||
element = tool.Ifc.get_entity(upstream_obj)
|
||||
bbim_boolean_updates.setdefault(element, []).append(boolean)
|
||||
bbim_boolean_updates.setdefault(element, []).append(boolean_id)
|
||||
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if body:
|
||||
blenderbim.core.geometry.switch_representation(
|
||||
@@ -692,8 +692,8 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
||||
)
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
for element, booleans in bbim_boolean_updates.items():
|
||||
tool.Model.unmark_manual_booleans(element, booleans)
|
||||
for element, boolean_ids in bbim_boolean_updates.items():
|
||||
tool.Model.unmark_manual_booleans(element, boolean_ids)
|
||||
|
||||
tool.Blender.set_active_object(upstream_obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -259,8 +259,10 @@ class BooleansMarkAsManual(bpy.types.Operator):
|
||||
if self.mark_as_manual:
|
||||
tool.Model.mark_manual_booleans(element, booleans)
|
||||
else:
|
||||
tool.Model.unmark_manual_booleans(element, booleans)
|
||||
tool.Model.unmark_manual_booleans(element, [b.id() for b in booleans])
|
||||
|
||||
self.report({"INFO"}, f"{len(booleans)} were marked as {'manual' if self.mark_as_manual else 'automatic'}")
|
||||
self.report(
|
||||
{"INFO"}, f"{len(booleans)} booleans were marked as {'manual' if self.mark_as_manual else 'automatic'}"
|
||||
)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -521,11 +521,12 @@ class Model(blenderbim.core.tool.Model):
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data})
|
||||
|
||||
@classmethod
|
||||
def unmark_manual_booleans(cls, element, booleans):
|
||||
def unmark_manual_booleans(cls, element, boolean_ids):
|
||||
# NOTE: we use use boolean_ids instead of boolean entities
|
||||
# so it will be possible to unmark manual booleans after they already was deleted
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
if not pset:
|
||||
return
|
||||
boolean_ids = [b.id() for b in booleans]
|
||||
data = set(json.loads(pset["Data"]))
|
||||
data -= set(boolean_ids)
|
||||
data = list(data)
|
||||
|
||||
@@ -21,6 +21,7 @@ import ifcopenshell
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.tool as tool
|
||||
import numpy as np
|
||||
import json
|
||||
from test.bim.bootstrap import NewFile
|
||||
from blenderbim.tool.model import Model as subject
|
||||
from ifcopenshell.util.shape_builder import V
|
||||
@@ -108,6 +109,37 @@ class TestGetManualBooleans(NewFile):
|
||||
assert len(subject.get_manual_booleans(element)) == 2
|
||||
|
||||
|
||||
class TestMarkManualBooleans(NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc.set(ifc)
|
||||
|
||||
element = ifc.createIfcWall()
|
||||
boolean = ifc.createIfcBooleanClippingResult()
|
||||
subject.mark_manual_booleans(element, [boolean])
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
assert pset
|
||||
value = json.loads(pset["Data"])
|
||||
assert set(value) == {boolean.id()}
|
||||
|
||||
|
||||
class TestUnmarkManualBooleans(NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
tool.Ifc.set(ifc)
|
||||
|
||||
element = ifc.createIfcWall()
|
||||
boolean = ifc.createIfcBooleanClippingResult()
|
||||
boolean2 = ifc.createIfcBooleanClippingResult()
|
||||
subject.mark_manual_booleans(element, [boolean, boolean2])
|
||||
subject.unmark_manual_booleans(element, [boolean.id()])
|
||||
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
assert pset
|
||||
value = json.loads(pset["Data"])
|
||||
assert set(value) == {boolean2.id()}
|
||||
|
||||
|
||||
class TestStairCalculatedParams(NewFile):
|
||||
def compare_data(self, pset_data, expected_calculated_data):
|
||||
calculated_data = subject.get_active_stair_calculated_params(pset_data)
|
||||
|
||||
Reference in New Issue
Block a user