Files
IfcOpenShell/src/ifcsverchok/nodes/ifc/add_spatial_element.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

149 lines
6.8 KiB
Python
Raw Normal View History

import bpy
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
import bpy
import json
import ifcopenshell
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting
class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcAddSpatialElement"
bl_label = "IFC Add Spatial Element"
node_dict = {}
n_id: StringProperty()
Name: StringProperty(name="Name(s)", update=updateNode)
IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace")
Elements: StringProperty(name="Elements", update=updateNode)
len_elements = 0
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Names").prop_name = "Name"
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements"
self.outputs.new("SvStringsSocket", "Entities")
def process(self):
print("#"*20, "\n running add_spatial_element PROCESS()... \n", "#"*20,)
print("#"*20, "\n hash(self):", hash(self), "\n", "#"*20,)
if not any(socket.is_linked for socket in self.outputs):
return
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1)
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0]
self.elements = ensure_min_nesting(self.inputs["Elements"].sv_get(), 2)
self.elements = flatten_data(self.elements, target_level=2)
if not self.elements[0][0]:
raise Exception('Mandatory input "Element(s)" is missing.')
return
print("elements: ", self.elements)
self.file = SvIfcStore.get_file()
self.elements = [[self.file.by_id(step_id) for step_id in element] for element in self.elements]
print("len elements: ", len(self.elements))
print("elements: ", self.elements)
self.names = self.repeat_input_unique(self.names, len(self.elements))
print("Names: ",self.names)
print("IfcClass: ",self.ifc_class)
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)
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
if (self.node_id not in SvIfcStore.id_map) or (len(self.elements) != self.len_elements):
print("\nRunning create")
elements = self.create()
self.len_elements = len(self.elements)
else:
if edit is True:
elements = self.edit()
else:
elements = SvIfcStore.id_map[self.node_id]
print("\n ##### results: ", elements)
self.outputs["Entities"].sv_set(elements)
def create(self):
results = []
for i, element in enumerate(self.elements):
print("element: ", element)
result = ifcopenshell.api.run("root.create_entity", self.file, name=self.names[i], ifc_class=self.ifc_class)
for items in element:
print("items: ", items)
2022-10-24 14:06:23 +02:00
if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result)
else:
ifcopenshell.api.run("spatial.assign_container", self.file, product=items, relating_structure=result)
SvIfcStore.id_map[result.id()] = self.node_id
SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id())
2022-10-24 14:06:23 +02:00
results.append(result.id())
return results
def edit(self):
results = []
results_ids = SvIfcStore.id_map[self.node_id]
print("#"*20, "\n running add_spatial_element edit()... \n", "#"*20,)
print("#"*20, "\n results_ids:", results_ids, "\n", "#"*20,)
for result_id in results_ids:
result = self.file.by_id(result_id)
print("#"*20, "\n result", result, "\n", "#"*20,)
subelements = set(ifcopenshell.util.element.get_decomposition(result))
for element in self.elements:
print("\n\n\n","#"*50)
print("\nElement: ", element)
element_set = set(element)
print("\nRESULT: ", result)
print("subelements: ", subelements)
print("elements_set: ", element_set)
for removed_element in subelements - element_set:
# Just realised I don't have a spatial.unassign_container, but if so we'd do it here
if removed_element.is_a("IfcSpatialElement") or removed_element.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run("aggregate.unassign_object", self.file, product=removed_element, relating_object=result)
else:
pass
for added_element in element_set - subelements:
2022-10-24 14:06:23 +02:00
if added_element.is_a("IfcSpatialElement") or added_element.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run("aggregate.assign_object", self.file, product=added_element, relating_object=result)
else:
ifcopenshell.api.run("spatial.assign_container", self.file, product=added_element, relating_structure=result)
print("assigned container")
2022-10-24 14:06:23 +02:00
results.append(result.id())
return results
def repeat_input_unique(self, input, count):
input = repeat_last_for_length(input, count, deepcopy=False)
if input[0]:
input = [a if not (s:=sum(j == a for j in input[:i])) else f'{a}-{s+1}' for i, a in enumerate(input)] # add number to duplicates
return input
def get_existing_element(self):
entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)]
return self.file.by_id(entity_id)
def register():
bpy.utils.register_class(SvIfcAddSpatialElement)
def unregister():
bpy.utils.unregister_class(SvIfcAddSpatialElement)
SvIfcStore.purge()