WIP implement add / remove fills. See #1222.

This commit is contained in:
Dion Moult
2021-01-12 16:39:01 +11:00
parent 9400eab0ff
commit b78e710479
8 changed files with 117 additions and 17 deletions
@@ -471,7 +471,7 @@ class IfcImporter:
self.profile_code("Create presentation layers")
self.add_project_to_scene()
self.profile_code("Add project to scene")
if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 10000:
if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 1000:
self.clean_mesh()
self.profile_code("Mesh cleaning")
@@ -1,16 +1,19 @@
import bpy
from . import ui, operator
from . import ui, prop, operator
classes = (
operator.AddOpening,
operator.RemoveOpening,
operator.AddFilling,
operator.RemoveFilling,
prop.VoidProperties,
ui.BIM_PT_voids,
)
def register():
pass
bpy.types.Scene.VoidProperties = bpy.props.PointerProperty(type=prop.VoidProperties)
def unregister():
pass
del bpy.types.Scene.VoidProperties
@@ -0,0 +1,16 @@
import ifcopenshell
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"opening": None, "element": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
self.file.create_entity("IfcRelFillsElement", **{
"GlobalId": ifcopenshell.guid.new(),
"RelatingOpeningElement": self.settings["opening"],
"RelatedBuildingElement": self.settings["element"]
})
@@ -8,11 +8,12 @@ class Data:
@classmethod
def load(cls, product_id):
print('loading', product_id)
file = IfcStore.get_file()
if not file:
return
cls.products[product_id] = set()
if product_id in cls.fillings:
del cls.fillings[product_id]
product = file.by_id(product_id)
for rel in file.by_type("IfcRelVoidsElement"):
building_element = rel.RelatingBuildingElement
@@ -25,10 +26,15 @@ class Data:
for rel in file.by_type("IfcRelFillsElement"):
opening = rel.RelatingOpeningElement
opening_id = int(opening.id())
if opening_id not in cls.openings:
continue
filling = rel.RelatedBuildingElement
filling_id = int(filling.id())
if filling_id == product_id and opening_id not in cls.openings:
cls.openings[opening_id] = {"Name": opening.Name, "HasFillings": set()}
if opening_id not in cls.openings:
continue
cls.fillings[filling_id] = {"Name": filling.Name, "FillsVoid": opening_id}
cls.openings[opening_id]["HasFillings"].add(filling_id)
return # See bug #1224
@@ -1,6 +1,8 @@
import bpy
import blenderbim.bim.module.void.add_opening as add_opening
import blenderbim.bim.module.void.remove_opening as remove_opening
import blenderbim.bim.module.void.add_filling as add_filling
import blenderbim.bim.module.void.remove_filling as remove_filling
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.void.data import Data
from blenderbim.bim.module.context.data import Data as ContextData
@@ -30,10 +32,13 @@ class AddOpening(bpy.types.Operator):
self.file = IfcStore.get_file()
element_id = obj.BIMObjectProperties.ifc_definition_id
add_opening.Usecase(self.file, {
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
"element": self.file.by_id(element_id)
}).execute()
add_opening.Usecase(
self.file,
{
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
"element": self.file.by_id(element_id),
},
).execute()
Data.load(element_id)
has_modifier = False
@@ -72,3 +77,40 @@ class RemoveOpening(bpy.types.Operator):
remove_opening.Usecase(self.file, {"opening": self.file.by_id(self.opening_id)}).execute()
Data.load(obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"}
class AddFilling(bpy.types.Operator):
bl_idname = "bim.add_filling"
bl_label = "Add Filling"
opening: bpy.props.StringProperty()
obj: bpy.props.StringProperty()
def execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
opening = bpy.data.objects.get(self.opening) if self.opening else context.scene.VoidProperties.desired_opening
self.file = IfcStore.get_file()
element_id = obj.BIMObjectProperties.ifc_definition_id
add_filling.Usecase(
self.file,
{
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
"element": self.file.by_id(element_id),
},
).execute()
Data.load(element_id)
return {"FINISHED"}
class RemoveFilling(bpy.types.Operator):
bl_idname = "bim.remove_filling"
bl_label = "Remove Filling"
obj: bpy.props.StringProperty()
def execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
self.file = IfcStore.get_file()
remove_filling.Usecase(
self.file, {"element": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)}
).execute()
Data.load(obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"}
@@ -0,0 +1,7 @@
import bpy
from bpy.types import PropertyGroup
from bpy.props import PointerProperty
class VoidProperties(PropertyGroup):
desired_opening: PointerProperty(name="Desired Opening To Fill", type=bpy.types.Object)
@@ -0,0 +1,12 @@
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"element": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.file.by_type("IfcRelFillsElement"):
if rel.RelatedBuildingElement == self.settings["element"]:
self.file.remove(rel)
break
@@ -18,7 +18,7 @@ class BIM_PT_voids(Panel):
row = self.layout.row(align=True)
if len(context.selected_objects) == 2:
op = row.operator("bim.add_opening", icon="ADD", text="Add Selected")
op = row.operator("bim.add_opening", icon="ADD", text="Add Opening")
for obj in context.selected_objects:
if "IfcOpeningElement" in obj.name or not obj.BIMObjectProperties.ifc_definition_id:
op.opening = obj.name
@@ -35,22 +35,36 @@ class BIM_PT_voids(Panel):
else:
obj_name = obj.name
if opening_id and obj_name:
op = row.operator("bim.remove_opening", icon="X", text="Remove Selected")
op = row.operator("bim.remove_opening", icon="X", text="Remove Opening")
op.opening_id = opening_id
op.obj = obj_name
else:
row.label(text="Select an opening and an element to modify", icon="HELP")
for opening_id in Data.products[props.ifc_definition_id]:
opening_ids = Data.products[props.ifc_definition_id]
if not opening_ids:
row = self.layout.row(align=True)
row.label(text="No Openings", icon="SELECT_SUBTRACT")
for opening_id in opening_ids:
opening = Data.openings[opening_id]
if opening["HasFillings"]:
for filling_id in opening["HasFillings"]:
filling = Data.fillings[filling_id]
row = self.layout.row(align=True)
row.label(text=opening["Name"])
row.label(text=filling["Name"])
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
else:
row = self.layout.row(align=True)
row.label(text=opening["Name"])
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
op = row.operator("bim.remove_opening", icon="X", text="")
op.opening_id = opening_id
if props.ifc_definition_id not in Data.fillings:
row = self.layout.row(align=True)
row.prop(context.scene.VoidProperties, "desired_opening", text="", icon="SELECT_INTERSECT")
row.operator("bim.add_filling", icon="ADD", text="")
else:
opening = Data.openings[Data.fillings[props.ifc_definition_id]["FillsVoid"]]
row = self.layout.row(align=True)
row.label(text=opening["Name"], icon="SELECT_INTERSECT")
row.operator("bim.remove_filling", icon="X", text="")