fixed create_entity and minor changes to bmesh_to_ifc

This commit is contained in:
martinaCodes
2022-10-10 09:01:00 +02:00
committed by Dion Moult
parent 38031a02bc
commit 5d569dea30
6 changed files with 343 additions and 411 deletions
-2
View File
@@ -52,7 +52,6 @@ def nodes_index():
("ifc.read_file", "SvIfcReadFile"),
("ifc.write_file", "SvIfcWriteFile"),
("ifc.create_entity", "SvIfcCreateEntity"),
("ifc.create_entity2", "SvIfcCreateEntity2"),
("ifc.create_shape", "SvIfcCreateShape"),
("ifc.read_entity", "SvIfcReadEntity"),
("ifc.by_id", "SvIfcById"),
@@ -70,7 +69,6 @@ def nodes_index():
("ifc.api", "SvIfcApi"),
("ifc.api_WIP", "SvIfcApiWIP"),
("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcGeo"),
("ifc.bmesh_to_ifc2", "SvIfcBMeshToIfcRepr"),
("ifc.create_project", "SvIfcCreateProject"),
("ifc.quick_project_setup", "SvIfcQuickProjectSetup")
@@ -60,6 +60,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
result = self.get_existing_element()
subelements = set(ifcopenshell.util.element.get_decomposition(result))
elements_set = set(elements)
print("RESULT: ", result)
print("subelements: ", subelements)
print("elements_set: ", elements_set)
for removed_element in subelements - elements_set:
# Just realised I don't have a spatial.unassign_container, but if so we'd do it here
pass
+191 -47
View File
@@ -16,76 +16,220 @@
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from copy import deepcopy
from email.policy import default
import bpy
import ifcopenshell
import ifcsverchok.helper
import ifcopenshell.api
from ifcsverchok.ifcstore import SvIfcStore
import blenderbim.tool as tool
import blenderbim.core.geometry as core
from bpy.props import StringProperty
from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, PointerProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
from sverchok.data_structure import (updateNode, flatten_data, fixed_iter, flat_iter)
from blenderbim.bim.module.root.prop import get_contexts
from sverchok.data_structure import zip_long_repeat, node_id
from sverchok.core.socket_data import sv_get_socket
from itertools import chain, cycle
class SvIfcBMeshToIfcGeo(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
"""
Triggers: BMesh to Ifc Geo
Tooltip: Blender mesh to Ifc Geometric Representation
Triggers: BMesh to Ifc Repr
Tooltip: Blender mesh to Ifc Shape Representation
"""
bl_idname = "SvIfcBMeshToIfcGeo"
bl_label = "IFC Blender Mesh to IFC Geo (old)"
bl_idname = "SvIfcBMeshToIfcRepr"
bl_label = "IFC Blender Mesh to IFC Repr"
node_dict = {}
is_scene_dependent = True # if True and is_interactive then the node will be updated upon scene changes
def refresh_node(self, context):
if self.refresh_local:
self.process()
self.refresh_local = False
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node)
n_id: StringProperty()
context_types = [
('Model', 'Model', 'Context type: Model', 0),
('Plan', 'Plan', 'Context type: Plan', 1),
]
context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1),
('Box', 'Box', 'Context identifier: Box', 2),
('Axis', 'Axis', 'Context identifier: Axis', 3),
]
target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3),
]
paradigms = [
('Tessellation', 'Tessellation', 'Geometry paradigm: Tessellation', 0),
('Extrusion', 'Extrusion', 'Geometry paradigm: Extrusion', 1),
]
blender_objects: PointerProperty(name="Blender Mesh(es)", description="Blender Mesh Object(s)",update=updateNode, type=bpy.types.Object)
context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode)
context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode)
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode)
paradigm: EnumProperty(name="Paradigm", description="Which geometry type to convert to. Choose between tessellation or extrusion. Default: Tessellation.",default="Tessellation",items=paradigms, update=updateNode)
tooltip: StringProperty(name="Tooltip")
context_id: bpy.props.IntProperty()
def sv_init(self, context):
input_socket = self.inputs.new("SvStringsSocket", "file")
input_socket.tooltip = "ifc file to add the geometry to"
input_socket = self.inputs.new("SvObjectSocket", "blender_object")
input_socket.tooltip = "Pick or pass Blender Mesh object"
input_socket = self.inputs.new("SvStringsSocket", "ifc_representation_class")
input_socket.tooltip = "Whether to cast a mesh into a particular class"
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
self.inputs.new("SvStringsSocket", "paradigm").prop_name = "paradigm"
self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" #no prop for now
self.outputs.new("SvVerticesSocket", "file")
self.outputs.new("SvVerticesSocket", "representation")
self.outputs.new("SvVerticesSocket", "Representations")
self.width = 210
self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout):
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Geometric Representation"
#op.tooltip = self.tooltip
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation"
row = layout.row(align=True)
row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH')
def process(self):
file = self.inputs["file"].sv_get()[0][0]
blender_object = self.inputs["blender_object"].sv_get()[0]
geometry = blender_object.data
self.process_ifc(file, blender_object, geometry)
def process_ifc(self, file, blender_object, geometry):
#get context
try:
for context in file.by_type("IFCGEOMETRICREPRESENTATIONCONTEXT", include_subtypes=True):
if context.get_info()["ContextType"] == "Model" and context.get_info()["ContextIdentifier"] == "Body":
repr_context= context
elif context.get_info()["ContextType"] == "Model":
repr_context= context
except:
raise Exception(
"Ifc Geometric Representation Context is missing."
)
print("#"*20, "\n running bmesh_to_ifc3 PROCESS()... \n", "#"*20,)
print("#"*20, "\n hash(self):", hash(self), "\n", "#"*20,)
representation = [ifcopenshell.api.run("geometry.add_representation", file, should_run_listeners=False,blender_object = blender_object, geometry=geometry, context = repr_context)]
try:
self.outputs["file"].sv_set([[file]])
self.outputs["representation"].sv_set([representation])
except:
raise Exception(
"Couldn't write to file. Representation: {}".format(
representation
)
)
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
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]:
return
edit = False
for i in range(len(self.inputs)):
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]:
edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input
#temporary
if self.paradigm == "Extrusion":
raise Exception("Extrusion not yet implemented.")
return
if self.refresh_local:
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()
self.context = self.get_context()
if self.node_id not in SvIfcStore.id_map:
representations = self.create(blender_objects)
else:
if edit is True:
self.edit()
representations = self.create(blender_objects)
else:
representations = self.get_existing_element()
print("representations: ", representations)
print("SvIfcStore.id_map: ", SvIfcStore.id_map)
self.outputs["Representations"].sv_set(representations)
self.outputs["file"].sv_set([[self.file]])
def create(self, blender_objects):
results = []
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)
if not representation:
raise Exception("Couldn't create representation. Possibly wrong context.")
results.append([representation])
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id())
return results
def edit(self):
# results = self.get_existing_element()
if "Representations" not in SvIfcStore.id_map[self.node_id]:
return
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
#if self.file.by_id(step_id).is_a('IfcShapeRepresentation'):
print("step_id: ", step_id)
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_existing_element(self):
results = []
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
results.append([self.file.by_id(step_id)])
return results
def get_context(self):
context = ifcopenshell.util.representation.get_context(self.file, self.context_type, self.context_identifier, self.target_view)
if not context:
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type)
if not parent:
parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type)
print("\nParent: ", parent)
context = ifcopenshell.api.run(
"context.add_context",
self.file,
context_type=self.context_type,
context_identifier=self.context_identifier,
target_view=self.target_view,
parent=parent,
)
# SvIfcStore.id_map.setdefault(self.node_id, []).append(context.id())
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id())
return context
def sv_free(self):
try:
print('DELETING')
self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]:
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))
if "Contexts" in SvIfcStore.id_map[self.node_id]:
for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]:
if not self.file.get_inverse(self.file.by_id(self.context.id())):
ifcopenshell.api.run("context.remove_context", self.file, representation=self.file.by_id(context_id))
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:
pass
def register():
bpy.utils.register_class(SvIfcBMeshToIfcGeo)
bpy.utils.register_class(SvIfcBMeshToIfcRepr)
def unregister():
bpy.utils.unregister_class(SvIfcBMeshToIfcGeo)
bpy.utils.unregister_class(SvIfcBMeshToIfcRepr)
-166
View File
@@ -1,166 +0,0 @@
# IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcsverchok.helper
import ifcopenshell.api
from ifcsverchok.ifcstore import SvIfcStore
import blenderbim.tool as tool
import blenderbim.core.geometry as core
from bpy.props import StringProperty, EnumProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
from blenderbim.bim.module.root.prop import get_contexts
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
"""
Triggers: BMesh to Ifc Repr
Tooltip: Blender mesh to Ifc Shape Representation
"""
bl_idname = "SvIfcBMeshToIfcRepr"
bl_label = "IFC Blender Mesh to IFC Repr"
blender_objects: StringProperty(name="Blender Mesh(es)", description="Blender Mesh Object(s)", update=updateNode)
ifc_representation_class: StringProperty(name="Ifc Representation Class", description="Whether to cast a mesh into a particular class", update=updateNode)
context_types = [
('Model', 'Model', 'Context type: Model', 0),
('Plan', 'Plan', 'Context type: Plan', 1),
]
context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1),
('Box', 'Box', 'Context identifier: Box', 2),
('Axis', 'Axis', 'Context identifier: Axis', 3),
]
target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3),
]
paradigms = [
('Tessellation', 'Tessellation', 'Geometry paradigm: Tessellation', 0),
('Extrusion', 'Extrusion', 'Geometry paradigm: Extrusion', 1),
]
context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode)
context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode)
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode)
paradigm: EnumProperty(name="Paradigm", description="Which geometry type to convert to. Choose between tessellation or extrusion. Default: Tessellation.",default="Tessellation",items=paradigms, update=updateNode)
tooltip: StringProperty(name="Tooltip")
context_id: bpy.props.IntProperty()
def sv_init(self, context):
self.inputs.new("SvObjectSocket", "blender_objects") #no prop for now
self.inputs.new("SvStringsSocket", "ifc_representation_class").prop_name = "ifc_representation_class"
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
self.inputs.new("SvStringsSocket", "paradigm").prop_name = "paradigm"
self.outputs.new("SvVerticesSocket", "file")
self.outputs.new("SvVerticesSocket", "Representation")
def draw_buttons(self, context, layout):
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation"
# layout.prop(self, 'context_type', text='')
# layout.prop(self, 'context_identifier', text='')
# layout.prop(self, 'target_view', text='')
# layout.prop(self, 'paradigm', text='')
#op.tooltip = self.tooltip
def process(self):
# if not self.inputs['blender_objects'].is_linked:
# return
self.file = SvIfcStore.get_file()
self.sv_input_names = [i.name for i in self.inputs]
for i in range(0, len(self.inputs)):
print("self.sv_input_names[i]: ", self.sv_input_names[i])
print("self.inputs[i].sv_get(): ", self.inputs[i].sv_get())
if self.sv_input_names[i] != "blender_objects":
setattr(self, self.sv_input_names[i], self.inputs[i].sv_get()) #doesn't work for lists?
self.blender_objects = self.inputs["blender_object"].sv_get()
self.create_context()
if self.node_id not in SvIfcStore.id_map.values():
for blender_object in self.blender_objects:
geometry = blender_object.data
self.process_ifc(self.file, blender_object, geometry)
else:
#TODO: edit existing representation
raise Exception("Editing not yet implemented")
SvIfcStore.file = self.file
try:
self.outputs["file"].sv_set([[self.file]]) #only for testing
self.outputs["Representation"].sv_set([self.representation])
except:
raise Exception(
"Couldn't write to file. Representation: {}".format(
self.representation
)
)
def process_ifc(self, blender_object, geometry):
try:
self.representation = [ifcopenshell.api.run("geometry.add_representation", self.file, should_run_listeners=False,blender_object = blender_object, geometry=geometry, context = self.context)]
except:
raise Exception("Couldn't create representation. Representation: {}".format(
self.representation
))
SvIfcStore.id_map[self.representation.id()] = self.node_id
def create_context(self):
if self.file.by_type("IFCGEOMETRICREPRESENTATIONCONTEXT", include_subtypes=True):
for context in self.file.by_type("IFCGEOMETRICREPRESENTATIONCONTEXT", include_subtypes=True):
if context.get_info()["ContextType"] == "Model" and context.get_info()["ContextIdentifier"] == "Body":
self.context = context
elif context.get_info()["ContextType"] == "Model":
self.context= context
else:
model = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type)
self.context = ifcopenshell.api.run(
"context.add_context",
self.file,
context_type=self.context_type,
context_identifier=self.context_identifier,
target_view=self.target_view,
parent=model,
)
SvIfcStore.id_map[self.context.id()] = self.node_id
def sv_free(self):
try:
SvIfcStore.id_map.pop(self.representation.id())
SvIfcStore.id_map.pop(self.context.id())
except KeyError or AttributeError:
pass
def register():
bpy.utils.register_class(SvIfcBMeshToIfcRepr)
def unregister():
bpy.utils.unregister_class(SvIfcBMeshToIfcRepr)
+149 -91
View File
@@ -1,115 +1,173 @@
import bpy
# IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
# from helper import SayHello
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
# import ifcsverchok.ifc_store
# from bpy.props import StringProperty
# from sverchok.node_tree import SverchCustomTreeNode
# from sverchok.data_structure import updateNode
import bpy
import ifcopenshell
import ifcsverchok.helper
from bpy.props import StringProperty
from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, PointerProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length
input_map = {}
class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcCreateEntity"
bl_label = "IFC Create Entity"
file: StringProperty(name="file", update=updateNode)
ifc_class: StringProperty(name="ifc_class", update=updateNode)
current_ifc_class: StringProperty(name="current_ifc_class")
node_dict = {}
is_scene_dependent = True # if True and is_interactive then the node will be updated upon scene changes
def refresh_node(self, context):
if self.refresh_local:
self.process()
self.refresh_local = False
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node)
Names: StringProperty(name="Names", default="", update=updateNode)
Descriptions: StringProperty(name="Descriptions", default="", update=updateNode)
IfcClass: StringProperty(name="IfcClass", update=updateNode)
Representations: StringProperty(name="Representations", default="", update=updateNode)
Properties: StringProperty(name="properties", update=updateNode)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
self.outputs.new("SvStringsSocket", "file")
self.outputs.new("SvStringsSocket", "entity")
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions"
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
self.inputs.new("SvStringsSocket", "Representations").prop_name = "Representations"
self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
self.outputs.new("SvStringsSocket", "Entities")
self.outputs.new("SvStringsSocket", "file") # only for testing
self.node_dict[hash(self)] = {}
def process(self):
self.sv_input_names = ["file", "ifc_class"]
ifc_class = self.inputs["ifc_class"].sv_get()[0][0]
if ifc_class:
file = self.inputs["file"].sv_get()[0][0]
if file:
schema_name = file.wrapped_data.schema
else:
schema_name = "IFC4"
self.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
self.entity_schema = self.schema.declaration_by_name(ifc_class)
print("#"*20, "\n running create_entity3 PROCESS()... \n", "#"*20,)
print("#"*20, "\n hash(self):", hash(self), "\n", "#"*20,)
if ifc_class != self.current_ifc_class:
self.generate_inputs(ifc_class)
try:
for i in range(0, len(self.inputs)):
input = self.inputs[i].sv_get()
except:
# This occurs when a blender save file is reloaded
self.generate_inputs(ifc_class)
for i in range(0, self.entity_schema.attribute_count()):
self.sv_input_names.append(self.entity_schema.attribute_by_index(i).name())
super().process()
self.names = self.inputs["Names"].sv_get()
self.descriptions = self.inputs["Descriptions"].sv_get()
self.ifc_class = self.inputs["IfcClass"].sv_get()[0][0]
self.representations = self.inputs["Representations"].sv_get()
self.properties = self.inputs["Properties"].sv_get()
def generate_inputs(self, ifc_class):
while len(self.inputs) > 2:
self.inputs.remove(self.inputs[-1])
for i in range(0, self.entity_schema.attribute_count()):
name = self.entity_schema.attribute_by_index(i).name()
setattr(SvIfcCreateEntity, name, StringProperty(name=name))
self.inputs.new("SvStringsSocket", name).prop_name = name
self.current_ifc_class = ifc_class
def process_ifc(self, file, ifc_class, *attributes):
entity = file.create_entity(ifc_class)
for i in range(0, len(entity)):
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
print("node_dict: ", self.node_dict)
if not self.inputs["IfcClass"].sv_get()[0][0]:
raise Exception("Insert IfcClass")
return
edit = False
for i in range(len(self.inputs)):
input = self.inputs[self.sv_input_names[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]:
edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input
if self.refresh_local:
edit = True
self.names = repeat_last_for_length(self.names, len(self.representations), deepcopy=False)
self.descriptions = repeat_last_for_length(self.descriptions, len(self.representations), deepcopy=False)
# print("REPRESENTATION: ", self.representations)
# print("IfcClass: ",self.ifc_class)
print("Names: ",self.names)
print("Descriptions: ",self.descriptions)
self.file = SvIfcStore.get_file()
if self.node_id not in SvIfcStore.id_map:
enities = self.create()
else:
if edit is True:
enities = self.edit()
else:
enities = self.get_existing_element()
print("Entities: ", enities)
print("SvIfcStore.id_map: ", SvIfcStore.id_map)
self.outputs["Entities"].sv_set(enities)
self.outputs["file"].sv_set([[self.file]])
def create(self):
# print("#"*20, "\n running create entity CREATE()... \n")
results = []
for i, name in enumerate(self.names):
print(type(self.names[i][0]))
try:
value = attributes[i]
if isinstance(value, str) and value == "":
value = None
except:
value = None
if value is None and entity.is_a("IfcRoot") and i == 0:
value = ifcopenshell.guid.new()
if value is not None and entity.attribute_name(i) == "Representation":
value = file.createIfcProductDefinitionShape(None, None, Representations = [value])
#product_shape = ifcopenshell.api.run("geometry.assign_representation", file, product = , representation = value)
if value is not None:
value = self.cast_value(self.entity_schema.attribute_by_index(i), value)
try:
entity[i] = value
except:
raise Exception(
"The IFC class {} requires a valid value for {} - you provided {}".format(
ifc_class, entity.attribute_name(i), value
)
)
self.entity = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=self.ifc_class, name=self.names[i][0], description=self.descriptions[i][0])
try:
ifcopenshell.api.run("geometry.assign_representation", self.file, product=self.entity, representation=self.representations[i][0])
except IndexError:
pass
results.append([self.entity])
SvIfcStore.id_map.setdefault(self.node_id, []).append(self.entity.id())
except:
raise Exception("Something went wrong. Cannot create entity.")
return results
def edit(self):
results = []
id_map_copy = SvIfcStore.id_map[self.node_id].copy()
for i, step_id in enumerate(id_map_copy):
self.entity = self.file.by_id(step_id)
self.entity.Name = self.names[i][0]
self.entity.Description = self.descriptions[i][0]
if self.representations[i][0] and not self.file.by_type("IFCPRODUCTDEFINITIONSHAPE"):
ifcopenshell.api.run("geometry.assign_representation", self.file, product=self.entity, representation=self.representations[i][0])
elif self.representations[i][0]:
self.entity.Representation = self.representations[i][0]
else:
pass
self.outputs["file"].sv_set([[file]])
self.outputs["entity"].sv_set([[entity]])
if self.entity.is_a() != self.ifc_class:
SvIfcStore.id_map[self.node_id].remove(step_id)
self.entity = ifcopenshell.util.schema.reassign_class(self.file, self.entity, self.ifc_class)
SvIfcStore.id_map.setdefault(self.node_id, []).append(self.entity.id())
results.append([self.entity])
def cast_value(self, attribute, value):
data_type = self.get_attribute_data_type(attribute.type_of_attribute())
if data_type == "integer":
value = int(value)
return value
return results
def get_attribute_data_type(self, data_type):
if hasattr(data_type, "declared_type"):
return self.get_attribute_data_type(data_type.declared_type())
return data_type
def get_existing_element(self):
# print("#"*20, "\n running create entity get_existing_element()... \n", "#"*20,)
results = []
for i, step_id in enumerate(SvIfcStore.id_map[self.node_id]):
self.entity = self.file.by_id(step_id)
results.append([self.entity])
return results
def sv_free(self):
try:
print('DELETING')
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
except KeyError or AttributeError:
pass
def register():
-105
View File
@@ -1,105 +0,0 @@
import bpy
# from helper import SayHello
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
# import ifcsverchok.ifc_store
# from bpy.props import StringProperty
# from sverchok.node_tree import SverchCustomTreeNode
# from sverchok.data_structure import updateNode
import bpy
import ifcopenshell
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
class SvIfcCreateEntity2(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcCreateEntity2"
bl_label = "IFC Create Entity2"
Name: StringProperty(name="Name",default="", update=updateNode)
Description: StringProperty(name="Description", default="", update=updateNode)
ifc_class: StringProperty(name="IfcClass", update=updateNode)
representation: StringProperty(name="representation", default="", update=updateNode)
properties: StringProperty(name="properties", update=updateNode)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Name").prop_name = "Name"
self.inputs.new("SvStringsSocket", "Description").prop_name = "Description"
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "ifc_class"
self.inputs.new("SvStringsSocket", "Representation").prop_name = "representation"
self.inputs.new("SvStringsSocket", "Properties").prop_name = "properties"
self.outputs.new("SvStringsSocket", "entity")
self.outputs.new("SvStringsSocket", "file") #only for testing
def process(self):
if not self.inputs['IfcClass'].is_linked:
return
self.sv_input_names = [i.name for i in self.inputs]
name = self.inputs["Name"].sv_get()[0][0]
description = self.inputs['Description'].sv_get()[0][0]
ifc_class = self.inputs['IfcClass'].sv_get()[0][0]
representation = self.inputs['Representation'].sv_get()[0][0]
self.file = SvIfcStore.get_file()
print("file: " , self.file)
print(SvIfcStore.file)
if self.node_id not in SvIfcStore.id_map.values():
self.process_ifc(name, description, ifc_class, representation)
else:
entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)]
self.entity = self.file.by_id(entity_id)
print(name)
self.entity.Name = name
self.entity.Description = description
if representation and not self.file.by_type("IFCPRODUCTDEFINITIONSHAPE"):
ifcopenshell.api.run("geometry.assign_representation", self.file, product=self.entity, representation=representation)
elif representation:
self.entity.Representation = representation
else:
pass
if self.entity.is_a() != ifc_class:
# This crashes blender
ifcopenshell.util.schema.reassign_class(self.file, self.entity, ifc_class)
SvIfcStore.file = self.file
self.outputs["entity"].sv_set([[self.entity]])
self.outputs["file"].sv_set([[self.file]]) #only for testing
def process_ifc(self, name, description, ifc_class, representation):
try:
self.entity = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name, description=description)
if representation:
ifcopenshell.api.run("geometry.assign_representation", self.file, product=self.entity, representation=representation)
except:
raise Exception("Something went wrong. Cannot create entity.")
print("entity: ", self.entity)
SvIfcStore.id_map[self.entity.id()] = self.node_id
print("id_map: ", SvIfcStore.id_map)
def sv_free(self):
try:
SvIfcStore.id_map.pop(self.entity.id())
except KeyError or AttributeError:
print("Either KeyError or AttributeError occurred.")
pass
print("I'm free!")
def register():
bpy.utils.register_class(SvIfcCreateEntity2)
def unregister():
bpy.utils.unregister_class(SvIfcCreateEntity2)