mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 18:57:17 +00:00
WIP implement add / remove fills. See #1222.
This commit is contained in:
@@ -471,7 +471,7 @@ class IfcImporter:
|
|||||||
self.profile_code("Create presentation layers")
|
self.profile_code("Create presentation layers")
|
||||||
self.add_project_to_scene()
|
self.add_project_to_scene()
|
||||||
self.profile_code("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.clean_mesh()
|
||||||
self.profile_code("Mesh cleaning")
|
self.profile_code("Mesh cleaning")
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from . import ui, operator
|
from . import ui, prop, operator
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.AddOpening,
|
operator.AddOpening,
|
||||||
operator.RemoveOpening,
|
operator.RemoveOpening,
|
||||||
|
operator.AddFilling,
|
||||||
|
operator.RemoveFilling,
|
||||||
|
prop.VoidProperties,
|
||||||
ui.BIM_PT_voids,
|
ui.BIM_PT_voids,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
pass
|
bpy.types.Scene.VoidProperties = bpy.props.PointerProperty(type=prop.VoidProperties)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
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
|
@classmethod
|
||||||
def load(cls, product_id):
|
def load(cls, product_id):
|
||||||
print('loading', product_id)
|
|
||||||
file = IfcStore.get_file()
|
file = IfcStore.get_file()
|
||||||
if not file:
|
if not file:
|
||||||
return
|
return
|
||||||
cls.products[product_id] = set()
|
cls.products[product_id] = set()
|
||||||
|
if product_id in cls.fillings:
|
||||||
|
del cls.fillings[product_id]
|
||||||
product = file.by_id(product_id)
|
product = file.by_id(product_id)
|
||||||
for rel in file.by_type("IfcRelVoidsElement"):
|
for rel in file.by_type("IfcRelVoidsElement"):
|
||||||
building_element = rel.RelatingBuildingElement
|
building_element = rel.RelatingBuildingElement
|
||||||
@@ -25,10 +26,15 @@ class Data:
|
|||||||
for rel in file.by_type("IfcRelFillsElement"):
|
for rel in file.by_type("IfcRelFillsElement"):
|
||||||
opening = rel.RelatingOpeningElement
|
opening = rel.RelatingOpeningElement
|
||||||
opening_id = int(opening.id())
|
opening_id = int(opening.id())
|
||||||
if opening_id not in cls.openings:
|
|
||||||
continue
|
|
||||||
filling = rel.RelatedBuildingElement
|
filling = rel.RelatedBuildingElement
|
||||||
filling_id = int(filling.id())
|
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.fillings[filling_id] = {"Name": filling.Name, "FillsVoid": opening_id}
|
||||||
cls.openings[opening_id]["HasFillings"].add(filling_id)
|
cls.openings[opening_id]["HasFillings"].add(filling_id)
|
||||||
return # See bug #1224
|
return # See bug #1224
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import blenderbim.bim.module.void.add_opening as add_opening
|
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.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.ifc import IfcStore
|
||||||
from blenderbim.bim.module.void.data import Data
|
from blenderbim.bim.module.void.data import Data
|
||||||
from blenderbim.bim.module.context.data import Data as ContextData
|
from blenderbim.bim.module.context.data import Data as ContextData
|
||||||
@@ -30,10 +32,13 @@ class AddOpening(bpy.types.Operator):
|
|||||||
|
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
element_id = obj.BIMObjectProperties.ifc_definition_id
|
element_id = obj.BIMObjectProperties.ifc_definition_id
|
||||||
add_opening.Usecase(self.file, {
|
add_opening.Usecase(
|
||||||
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
|
self.file,
|
||||||
"element": self.file.by_id(element_id)
|
{
|
||||||
}).execute()
|
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
|
||||||
|
"element": self.file.by_id(element_id),
|
||||||
|
},
|
||||||
|
).execute()
|
||||||
Data.load(element_id)
|
Data.load(element_id)
|
||||||
|
|
||||||
has_modifier = False
|
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()
|
remove_opening.Usecase(self.file, {"opening": self.file.by_id(self.opening_id)}).execute()
|
||||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
return {"FINISHED"}
|
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)
|
row = self.layout.row(align=True)
|
||||||
if len(context.selected_objects) == 2:
|
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:
|
for obj in context.selected_objects:
|
||||||
if "IfcOpeningElement" in obj.name or not obj.BIMObjectProperties.ifc_definition_id:
|
if "IfcOpeningElement" in obj.name or not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
op.opening = obj.name
|
op.opening = obj.name
|
||||||
@@ -35,22 +35,36 @@ class BIM_PT_voids(Panel):
|
|||||||
else:
|
else:
|
||||||
obj_name = obj.name
|
obj_name = obj.name
|
||||||
if opening_id and 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.opening_id = opening_id
|
||||||
op.obj = obj_name
|
op.obj = obj_name
|
||||||
else:
|
else:
|
||||||
row.label(text="Select an opening and an element to modify", icon="HELP")
|
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]
|
opening = Data.openings[opening_id]
|
||||||
if opening["HasFillings"]:
|
if opening["HasFillings"]:
|
||||||
for filling_id in opening["HasFillings"]:
|
for filling_id in opening["HasFillings"]:
|
||||||
filling = Data.fillings[filling_id]
|
filling = Data.fillings[filling_id]
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text=opening["Name"])
|
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
|
||||||
row.label(text=filling["Name"])
|
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
|
||||||
else:
|
else:
|
||||||
row = self.layout.row(align=True)
|
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 = row.operator("bim.remove_opening", icon="X", text="")
|
||||||
op.opening_id = opening_id
|
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="")
|
||||||
|
|||||||
Reference in New Issue
Block a user