sverchok_to_ifc node added + works for multiple geometries. Parent contexts also get deleted if not used.

This commit is contained in:
martinaCodes
2022-10-23 16:18:42 +02:00
committed by Dion Moult
parent 6542fc7db3
commit 37aa17fcf3
4 changed files with 124 additions and 71 deletions
+2 -2
View File
@@ -68,8 +68,8 @@ def nodes_index():
("ifc.select_blender_objects", "SvIfcSelectBlenderObjects"), ("ifc.select_blender_objects", "SvIfcSelectBlenderObjects"),
("ifc.api", "SvIfcApi"), ("ifc.api", "SvIfcApi"),
("ifc.api_WIP", "SvIfcApiWIP"), ("ifc.api_WIP", "SvIfcApiWIP"),
("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcGeo"), ("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcRepr"),
("ifc.sverchok_to_ifc", "SvIfcSverchokToIfc"), ("ifc.sverchok_to_ifc", "SvIfcSverchokToIfcRepr"),
("ifc.create_project", "SvIfcCreateProject"), ("ifc.create_project", "SvIfcCreateProject"),
("ifc.quick_project_setup", "SvIfcQuickProjectSetup") ("ifc.quick_project_setup", "SvIfcQuickProjectSetup")
+15 -27
View File
@@ -17,6 +17,7 @@
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>. # along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from copy import deepcopy from copy import deepcopy
from decimal import Context
from email.policy import default from email.policy import default
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -89,21 +90,17 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
self.inputs.new("SvStringsSocket", "paradigm").prop_name = "paradigm" self.inputs.new("SvStringsSocket", "paradigm").prop_name = "paradigm"
self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" #no prop for now self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" #no prop for now
self.outputs.new("SvVerticesSocket", "Representations") self.outputs.new("SvVerticesSocket", "Representations")
self.width = 210
self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation" layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries."
row = layout.row(align=True) row = layout.row(align=True)
row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True) row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH') row.prop(self, 'refresh_local', icon='FILE_REFRESH')
def process(self): def process(self):
# print("#"*20, "\n running bmesh_to_ifc3 PROCESS()... \n", "#"*20,)
# print("#"*20, "\n hash(self):", hash(self), "\n", "#"*20,)
self.sv_input_names = [i.name for i in self.inputs] self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict: if hash(self) not in self.node_dict:
@@ -111,35 +108,24 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
if not self.node_dict[hash(self)]: if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
# print("node_dict: ", self.node_dict)
if not self.inputs["blender_objects"].sv_get()[0]: if not self.inputs["blender_objects"].sv_get()[0]:
return return
edit = False edit = False
for i in range(len(self.inputs)): for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=False) input = self.inputs[i].sv_get(deepcopy=False)
# print("input: ", input)
# print("self.node_dict[hash(self)][self.inputs[i].name]: ", self.node_dict[hash(self)][self.inputs[i].name])
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]:
edit = True edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input self.node_dict[hash(self)][self.inputs[i].name] = input
blender_objects = self.inputs["blender_objects"].sv_get()
self.file = SvIfcStore.get_file()
#temporary #temporary
if self.paradigm == "Extrusion": if self.paradigm == "Extrusion":
raise Exception("Extrusion not yet implemented.") raise Exception("Extrusion not yet implemented.")
return return
if self.refresh_local: if self.refresh_local:
edit = True edit = True
blender_objects = self.inputs["blender_objects"].sv_get()
# print("\ncontext_type: ", self.context_type)
# print("context_identifier: ", self.context_identifier)
# print("blender_objects: ", blender_objects)
self.file = SvIfcStore.get_file()
print(self.file)
self.context = self.get_context()
if self.node_id not in SvIfcStore.id_map: if self.node_id not in SvIfcStore.id_map:
representations = self.create(blender_objects) representations = self.create(blender_objects)
else: else:
@@ -151,14 +137,13 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
representations = SvIfcStore.id_map[self.node_id]["Representations"] representations = SvIfcStore.id_map[self.node_id]["Representations"]
print("representations: ", representations) print("representations: ", representations)
print("SvIfcStore.id_map: ", SvIfcStore.id_map)
self.outputs["Representations"].sv_set(representations) self.outputs["Representations"].sv_set(representations)
def create(self, blender_objects): def create(self, blender_objects):
representations_ids = [] representations_ids = []
for blender_object in blender_objects: for blender_object in blender_objects:
representation = ifcopenshell.api.run("geometry.add_representation", self.file, should_run_listeners=False,blender_object = blender_object, geometry=blender_object.data, context = self.context) representation = ifcopenshell.api.run("geometry.add_representation", self.file, should_run_listeners=False,blender_object = blender_object, geometry=blender_object.data, context = self.get_context())
if not representation: if not representation:
raise Exception("Couldn't create representation. Possibly wrong context.") raise Exception("Couldn't create representation. Possibly wrong context.")
representations_ids.append(representation.id()) representations_ids.append(representation.id())
@@ -203,19 +188,22 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
return context return context
def sv_free(self): def sv_free(self):
try: try:
print('DELETING')
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]: if "Representations" in SvIfcStore.id_map[self.node_id]:
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
print("step_id: ", step_id)
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id)) ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id))
if "Contexts" in SvIfcStore.id_map[self.node_id]: if "Contexts" in SvIfcStore.id_map[self.node_id]:
for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]: for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]:
if not self.file.get_inverse(self.file.by_id(self.context.id())): context = self.file.by_id(context_id)
ifcopenshell.api.run("context.remove_context", self.file, representation=self.file.by_id(context_id)) if not self.file.get_inverse(context):
if self.file.by_id(context_id).ParentContext:
parent = self.file.by_id(context_id).ParentContext
ifcopenshell.api.run("context.remove_context", self.file, context=context)
if parent:
if not self.file.get_inverse(parent):
ifcopenshell.api.run("context.remove_context", self.file, context=parent)
print("Removed context with step ID: ", context_id) print("Removed context with step ID: ", context_id)
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id) SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
del SvIfcStore.id_map[self.node_id] del SvIfcStore.id_map[self.node_id]
@@ -191,9 +191,7 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
def sv_free(self): def sv_free(self):
try: try:
print('DELETING')
del SvIfcStore.id_map[self.node_id] del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)] del self.node_dict[hash(self)]
print('Node was deleted') print('Node was deleted')
+103 -36
View File
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>. # along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from copy import deepcopy
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
@@ -23,15 +24,21 @@ import ifcopenshell.api
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
import blenderbim.tool as tool import blenderbim.tool as tool
import blenderbim.core.geometry as core import blenderbim.core.geometry as core
from bpy.props import StringProperty, EnumProperty, IntProperty from bpy.props import StringProperty, EnumProperty, IntProperty, FloatVectorProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode
class SvIfcSverchokToIfc(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcSverchokToIfc" """
bl_label = "IFC Sverchok to IFC" Triggers: Sv to Ifc Repr
Tooltip: Sverchok geometry to Ifc Shape Representation
"""
bl_idname = "SvIfcSverchokToIfcRepr"
bl_label = "IFC Sverchok to IFC Repr"
node_dict = {}
n_id: StringProperty()
context_types = [ context_types = [
('Model', 'Model', 'Context type: Model', 0), ('Model', 'Model', 'Context type: Model', 0),
('Plan', 'Plan', 'Context type: Plan', 1), ('Plan', 'Plan', 'Context type: Plan', 1),
@@ -55,50 +62,92 @@ class SvIfcSverchokToIfc(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode) target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvVerticesSocket", "Vertices")
self.inputs.new("SvStringsSocket", "Edges")
self.inputs.new("SvStringsSocket", "Faces")
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type" self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier" self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view" self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
self.inputs.new("SvVerticesSocket", "Vertices")
self.outputs.new("SvVerticesSocket", "Representation") self.inputs.new("SvStringsSocket", "Edges")
self.inputs.new("SvStringsSocket", "Faces")
self.outputs.new("SvVerticesSocket", "Representation(s)")
self.outputs.new("SvVerticesSocket", "File") self.outputs.new("SvVerticesSocket", "File")
self.width = 210
self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
op = layout.operator( op = layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Blender mesh to Ifc Shape Representation" ).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries."
def process(self): def process(self):
self.file = SvIfcStore.get_file() if not any(socket.is_linked for socket in self.inputs):
return
self.file = SvIfcStore.get_file()
self.sv_input_names = [i.name for i in self.inputs] self.sv_input_names = [i.name for i in self.inputs]
if self.node_id in SvIfcStore.id_map: if hash(self) not in self.node_dict:
for step_id in SvIfcStore.id_map[self.node_id]: self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
ifcopenshell.api.run( if not self.node_dict[hash(self)]:
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id) self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
)
del SvIfcStore.id_map[self.node_id]
results = [] print("node_dict: ", self.node_dict)
edit = False
for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=False)
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]:
edit = True
print("Edit = True")
self.node_dict[hash(self)][self.inputs[i].name] = input
representation = ifcopenshell.api.run( self.vertices = self.inputs["Vertices"].sv_get(deepcopy=False)
self.edges = self.inputs["Edges"].sv_get(deepcopy=False)
self.faces = self.inputs["Faces"].sv_get(deepcopy=False)
data = list(zip(self.vertices, self.edges, self.faces))
if self.node_id not in SvIfcStore.id_map:
representations = self.create(data)
else:
print("edit: ", edit)
if edit is True:
self.edit()
representations = self.create(data)
else:
# representations = self.get_existing_element()
representations = SvIfcStore.id_map[self.node_id]["Representations"]
self.outputs["Representation(s)"].sv_set(representations)
def create(self, data):
representations_ids = []
self.context = self.get_context()
for item in data:
representation = ifcopenshell.api.run(
"geometry.add_sverchok_representation", "geometry.add_sverchok_representation",
self.file, self.file,
should_run_listeners=False, should_run_listeners=False,
context=self.get_context(), context=self.context,
vertices=self.inputs["Vertices"].sv_get(), vertices=[item[0]],
faces=self.inputs["Faces"].sv_get(), edges=[item[1]],
) faces=[item[2]],
results.append(representation) )
SvIfcStore.id_map.setdefault(self.node_id, []).append(representation.id()) if not representation:
raise Exception("Couldn't create representation. Possibly wrong context.")
representations_ids.append(representation.id())
print("Representation: ", representation)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id())
return representations_ids
SvIfcStore.file = self.file def edit(self):
# results = self.get_existing_element()
self.outputs["File"].sv_set([[self.file]]) # only for testing if "Representations" not in SvIfcStore.id_map[self.node_id]:
self.outputs["Representation"].sv_set([results]) return
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
del SvIfcStore.id_map[self.node_id]["Representations"]
return
def get_context(self): def get_context(self):
context = ifcopenshell.util.representation.get_context( context = ifcopenshell.util.representation.get_context(
@@ -114,23 +163,41 @@ class SvIfcSverchokToIfc(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe
context_type=self.context_type, context_type=self.context_type,
context_identifier=self.context_identifier, context_identifier=self.context_identifier,
target_view=self.target_view, target_view=self.target_view,
parent=model, parent=parent,
) )
print("context: ", context)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id())
return context return context
def sv_free(self): def sv_free(self):
print("it was deleted")
try: try:
pass self.file = SvIfcStore.get_file()
# SvIfcStore.id_map.pop(self.representation.id()) if "Representations" in SvIfcStore.id_map[self.node_id]:
# SvIfcStore.id_map.pop(self.context.id()) for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id))
if "Contexts" in SvIfcStore.id_map[self.node_id]:
for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]:
context = self.file.by_id(context_id)
if not self.file.get_inverse(context):
if self.file.by_id(context_id).ParentContext:
parent = self.file.by_id(context_id).ParentContext
ifcopenshell.api.run("context.remove_context", self.file, context=context)
if parent:
if not self.file.get_inverse(parent):
ifcopenshell.api.run("context.remove_context", self.file, context=parent)
print("Removed context with step ID: ", context_id)
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
except KeyError or AttributeError: except KeyError or AttributeError:
pass pass
def register(): def register():
bpy.utils.register_class(SvIfcSverchokToIfc) bpy.utils.register_class(SvIfcSverchokToIfcRepr)
def unregister(): def unregister():
bpy.utils.unregister_class(SvIfcSverchokToIfc) bpy.utils.unregister_class(SvIfcSverchokToIfcRepr)