mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +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
|
"geometry.add_boolean", tool.Ifc.get(), representation=representation, operator="DIFFERENCE", **mesh_data
|
||||||
)
|
)
|
||||||
|
|
||||||
pset = ifcopenshell.util.element.get_pset(element1, "BBIM_Boolean")
|
tool.Model.mark_manual_booleans(element1, booleans)
|
||||||
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.clear_scene_openings()
|
tool.Model.clear_scene_openings()
|
||||||
|
|
||||||
blenderbim.core.geometry.switch_representation(
|
blenderbim.core.geometry.switch_representation(
|
||||||
@@ -672,17 +662,17 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
|||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
boolean_id = None
|
boolean = None
|
||||||
for inverse in tool.Ifc.get().get_inverse(item):
|
for inverse in tool.Ifc.get().get_inverse(item):
|
||||||
if inverse.is_a("IfcBooleanResult"):
|
if inverse.is_a("IfcBooleanResult"):
|
||||||
boolean_id = inverse.id()
|
boolean = inverse
|
||||||
break
|
break
|
||||||
ifcopenshell.api.run("geometry.remove_boolean", tool.Ifc.get(), item=item)
|
ifcopenshell.api.run("geometry.remove_boolean", tool.Ifc.get(), item=item)
|
||||||
|
|
||||||
if obj.data.BIMMeshProperties.obj:
|
if obj.data.BIMMeshProperties.obj:
|
||||||
upstream_obj = obj.data.BIMMeshProperties.obj
|
upstream_obj = obj.data.BIMMeshProperties.obj
|
||||||
element = tool.Ifc.get_entity(upstream_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")
|
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||||
if body:
|
if body:
|
||||||
blenderbim.core.geometry.switch_representation(
|
blenderbim.core.geometry.switch_representation(
|
||||||
@@ -696,18 +686,8 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
|
|||||||
)
|
)
|
||||||
bpy.data.objects.remove(obj)
|
bpy.data.objects.remove(obj)
|
||||||
|
|
||||||
for element, boolean_ids in bbim_boolean_updates.items():
|
for element, booleans in bbim_boolean_updates.items():
|
||||||
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean")
|
tool.Model.unmark_manual_booleans(element, booleans)
|
||||||
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)
|
|
||||||
|
|
||||||
tool.Blender.set_active_object(upstream_obj)
|
tool.Blender.set_active_object(upstream_obj)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -474,11 +474,7 @@ class Model(blenderbim.core.tool.Model):
|
|||||||
return {"thickness": thickness, "offset": offset, "direction_sense": direction_sense}
|
return {"thickness": thickness, "offset": offset, "direction_sense": direction_sense}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_manual_booleans(cls, element):
|
def get_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")
|
body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||||
if not body:
|
if not body:
|
||||||
return []
|
return []
|
||||||
@@ -487,11 +483,51 @@ class Model(blenderbim.core.tool.Model):
|
|||||||
while items:
|
while items:
|
||||||
item = items.pop()
|
item = items.pop()
|
||||||
if item.is_a("IfcBooleanResult"):
|
if item.is_a("IfcBooleanResult"):
|
||||||
if item.id() in boolean_ids:
|
booleans.append(item)
|
||||||
booleans.append(item)
|
|
||||||
items.append(item.FirstOperand)
|
items.append(item.FirstOperand)
|
||||||
return booleans
|
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
|
@classmethod
|
||||||
def get_flow_segment_axis(cls, obj):
|
def get_flow_segment_axis(cls, obj):
|
||||||
z_values = [v[2] for v in obj.bound_box]
|
z_values = [v[2] for v in obj.bound_box]
|
||||||
|
|||||||
@@ -54,10 +54,20 @@ class TestGenerateOccurrenceName(NewFile):
|
|||||||
|
|
||||||
|
|
||||||
class TestGetManualBooleans(NewFile):
|
class TestGetManualBooleans(NewFile):
|
||||||
def test_run(self):
|
def test_get_manual_booleans(self):
|
||||||
assert isinstance(subject(), blenderbim.core.tool.Model)
|
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()
|
ifc = ifcopenshell.file()
|
||||||
self.ifc = ifc
|
self.ifc = ifc
|
||||||
tool.Ifc.set(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
|
"geometry.add_profile_representation", ifc, context=body, profile=hea100, depth=5, clippings=clippings
|
||||||
)
|
)
|
||||||
ifcopenshell.api.run("geometry.assign_representation", ifc, product=element, representation=representation)
|
ifcopenshell.api.run("geometry.assign_representation", ifc, product=element, representation=representation)
|
||||||
return element, representation
|
|
||||||
|
|
||||||
def test_manual_booleans(self):
|
booleans = subject.get_booleans(element)
|
||||||
element, representation = self.setup_profile_represntation()
|
assert len(booleans) == 2
|
||||||
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])
|
|
||||||
assert len(subject.get_manual_booleans(element)) == 0
|
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))
|
items.append(self.file.createIfcBooleanClippingResult(self.settings["operator"], item, result))
|
||||||
|
representation_type = "Clipping"
|
||||||
else:
|
else:
|
||||||
items.append(self.file.createIfcBooleanResult(self.settings["operator"], item, result))
|
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
|
self.settings["representation"].Items = items
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user