mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-08 00:41:36 +00:00
move to tools methods for working with manual booleans #3709
Also fixed a bug adding boolean when pset is already added and representation type in add_boolean
```
File "\addons\blenderbim\tool\ifc.py", line 201, in execute
IfcStore.execute_ifc_operator(self, context)
File "\addons\blenderbim\bim\ifc.py", line 336, in execute_ifc_operator
result = getattr(operator, "_execute")(context)
File "\addons\blenderbim\bim\module\model\opening.py", line 534, in _execute
data = json.loads(pset["Data"])
File "\addons\blenderbim\libs\site\packages\ifcopenshell\entity_instance.py", line 248, in __getitem__
if key < 0 or key >= len(self):
TypeError: '<' not supported between instances of 'str' and 'int'
```
This commit is contained in:
@@ -528,17 +528,7 @@ class AddBoolean(Operator, tool.Ifc.Operator):
|
||||
"geometry.add_boolean", tool.Ifc.get(), representation=representation, operator="DIFFERENCE", **mesh_data
|
||||
)
|
||||
|
||||
pset = ifcopenshell.util.element.get_pset(element1, "BBIM_Boolean")
|
||||
if pset:
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
data = json.loads(pset["Data"])
|
||||
data.extend([b.id() for b in booleans])
|
||||
data = list(set(data))
|
||||
else:
|
||||
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element1, name="BBIM_Boolean")
|
||||
data = [b.id() for b in booleans]
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": json.dumps(data)})
|
||||
|
||||
tool.Model.mark_manual_booleans(element1, booleans)
|
||||
tool.Model.clear_scene_openings()
|
||||
|
||||
blenderbim.core.geometry.switch_representation(
|
||||
@@ -672,17 +662,17 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
||||
except:
|
||||
continue
|
||||
|
||||
boolean_id = None
|
||||
boolean = None
|
||||
for inverse in tool.Ifc.get().get_inverse(item):
|
||||
if inverse.is_a("IfcBooleanResult"):
|
||||
boolean_id = inverse.id()
|
||||
boolean = inverse
|
||||
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_id)
|
||||
bbim_boolean_updates.setdefault(element, []).append(boolean)
|
||||
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if body:
|
||||
blenderbim.core.geometry.switch_representation(
|
||||
@@ -696,18 +686,8 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
||||
)
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
for element, boolean_ids in bbim_boolean_updates.items():
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
if not pset:
|
||||
continue
|
||||
data = set(json.loads(pset["Data"]))
|
||||
data -= set(boolean_ids)
|
||||
data = list(data)
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
if data:
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": json.dumps(data)})
|
||||
else:
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||
for element, booleans in bbim_boolean_updates.items():
|
||||
tool.Model.unmark_manual_booleans(element, booleans)
|
||||
|
||||
tool.Blender.set_active_object(upstream_obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -474,11 +474,7 @@ class Model(blenderbim.core.tool.Model):
|
||||
return {"thickness": thickness, "offset": offset, "direction_sense": direction_sense}
|
||||
|
||||
@classmethod
|
||||
def get_manual_booleans(cls, element):
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
if not pset:
|
||||
return []
|
||||
boolean_ids = json.loads(pset["Data"])
|
||||
def get_booleans(cls, element):
|
||||
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if not body:
|
||||
return []
|
||||
@@ -487,11 +483,51 @@ class Model(blenderbim.core.tool.Model):
|
||||
while items:
|
||||
item = items.pop()
|
||||
if item.is_a("IfcBooleanResult"):
|
||||
if item.id() in boolean_ids:
|
||||
booleans.append(item)
|
||||
booleans.append(item)
|
||||
items.append(item.FirstOperand)
|
||||
return booleans
|
||||
|
||||
@classmethod
|
||||
def get_manual_booleans(cls, element):
|
||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
if not pset:
|
||||
return []
|
||||
boolean_ids = json.loads(pset["Data"])
|
||||
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if not body:
|
||||
return []
|
||||
booleans = [b for b in cls.get_booleans(element) if b.id() in boolean_ids]
|
||||
return booleans
|
||||
|
||||
@classmethod
|
||||
def mark_manual_booleans(cls, element, booleans):
|
||||
pset_data = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
||||
boolean_ids = [b.id() for b in booleans]
|
||||
if pset_data:
|
||||
pset = tool.Ifc.get().by_id(pset_data["id"])
|
||||
data = json.loads(pset_data["Data"])
|
||||
data.extend(boolean_ids)
|
||||
data = list(set(data))
|
||||
else:
|
||||
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="BBIM_Boolean")
|
||||
data = boolean_ids
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": json.dumps(data)})
|
||||
|
||||
@classmethod
|
||||
def unmark_manual_booleans(cls, element, booleans):
|
||||
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)
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
if data:
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": json.dumps(data)})
|
||||
else:
|
||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||
|
||||
@classmethod
|
||||
def get_flow_segment_axis(cls, obj):
|
||||
z_values = [v[2] for v in obj.bound_box]
|
||||
|
||||
@@ -54,10 +54,20 @@ class TestGenerateOccurrenceName(NewFile):
|
||||
|
||||
|
||||
class TestGetManualBooleans(NewFile):
|
||||
def test_run(self):
|
||||
assert isinstance(subject(), blenderbim.core.tool.Model)
|
||||
def test_get_manual_booleans(self):
|
||||
clippings = [
|
||||
{
|
||||
"type": "IfcBooleanClippingResult",
|
||||
"operand_type": "IfcHalfSpaceSolid",
|
||||
"matrix": np.eye(4).tolist(),
|
||||
},
|
||||
{
|
||||
"type": "IfcBooleanResult",
|
||||
"operand_type": "IfcHalfSpaceSolid",
|
||||
"matrix": np.eye(4).tolist(),
|
||||
},
|
||||
]
|
||||
|
||||
def setup_profile_represntation(self, clippings=[]):
|
||||
ifc = ifcopenshell.file()
|
||||
self.ifc = ifc
|
||||
tool.Ifc.set(ifc)
|
||||
@@ -89,21 +99,9 @@ class TestGetManualBooleans(NewFile):
|
||||
"geometry.add_profile_representation", ifc, context=body, profile=hea100, depth=5, clippings=clippings
|
||||
)
|
||||
ifcopenshell.api.run("geometry.assign_representation", ifc, product=element, representation=representation)
|
||||
return element, representation
|
||||
|
||||
def test_manual_booleans(self):
|
||||
element, representation = self.setup_profile_represntation()
|
||||
matrix = np.eye(4)
|
||||
ifcopenshell.api.run(
|
||||
"geometry.add_boolean", self.ifc, representation=representation, type="IfcHalfSpaceSolid", matrix=matrix
|
||||
)
|
||||
assert len(subject.get_manual_booleans(element)) == 1
|
||||
|
||||
def test_automatic_booleans_ignored(self):
|
||||
clipping = {
|
||||
"type": "IfcBooleanClippingResult",
|
||||
"operand_type": "IfcHalfSpaceSolid",
|
||||
"matrix": np.eye(4).tolist(),
|
||||
}
|
||||
element, representation = self.setup_profile_represntation(clippings=[clipping])
|
||||
booleans = subject.get_booleans(element)
|
||||
assert len(booleans) == 2
|
||||
assert len(subject.get_manual_booleans(element)) == 0
|
||||
subject.mark_manual_booleans(element, booleans)
|
||||
assert len(subject.get_manual_booleans(element)) == 2
|
||||
|
||||
@@ -57,9 +57,11 @@ class Usecase:
|
||||
)
|
||||
):
|
||||
items.append(self.file.createIfcBooleanClippingResult(self.settings["operator"], item, result))
|
||||
representation_type = "Clipping"
|
||||
else:
|
||||
items.append(self.file.createIfcBooleanResult(self.settings["operator"], item, result))
|
||||
self.settings["representation"].RepresentationType = "CSG"
|
||||
representation_type = "CSG"
|
||||
self.settings["representation"].RepresentationType = representation_type
|
||||
self.settings["representation"].Items = items
|
||||
return items
|
||||
|
||||
|
||||
Reference in New Issue
Block a user