Updated following nodes to work with the current workflow: add_pset, by_guid, get_attribute, get_property, read_entity. Added tooltips and other minor fixes

This commit is contained in:
martinaCodes
2022-11-11 02:50:30 +01:00
parent cc567534f1
commit b7bdddf640
11 changed files with 508 additions and 169 deletions
+58 -22
View File
@@ -28,22 +28,36 @@ import ifcopenshell
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, flatten_data
class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcAddPset" bl_idname = "SvIfcAddPset"
bl_label = "IFC Add Pset" bl_label = "IFC Add Pset"
Name: StringProperty(name="Name", update=updateNode, default="My_Pset") Name: StringProperty(
Properties: StringProperty(name="Properties", update=updateNode, default="{\"Foo\":\"Bar\"}") name="Name",
Elements: StringProperty(name="Elements", update=updateNode) description="Name of the property set. Eg. Pset_WallCommon.",
update=updateNode,
default="My_Pset",
)
Properties: StringProperty(
name="Properties",
description='Propertied in a JSON key:value format.Eg. {"IsExternal":"True"}',
update=updateNode,
default='{"Foo":"Bar"}',
)
Elements: StringProperty(name="Element Ids", update=updateNode)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Name").prop_name = "Name" self.inputs.new("SvStringsSocket", "Name").prop_name = "Name"
self.inputs.new("SvTextSocket", "Properties").prop_name = "Properties" self.inputs.new("SvTextSocket", "Properties").prop_name = "Properties"
self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements" self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements"
self.outputs.new("SvStringsSocket", "entity") self.outputs.new("SvStringsSocket", "Entity")
self.outputs.new("SvStringsSocket", "file")
def draw_buttons(self, context, layout):
layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Add a property set and corresponding properties to IfcElements."
def process(self): def process(self):
if not any(socket.is_linked for socket in self.outputs): if not any(socket.is_linked for socket in self.outputs):
@@ -51,37 +65,59 @@ class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIf
name = self.inputs["Name"].sv_get()[0][0] name = self.inputs["Name"].sv_get()[0][0]
properties = self.inputs["Properties"].sv_get()[0][0] properties = self.inputs["Properties"].sv_get()[0][0]
elements = self.inputs["Elements"].sv_get()[0] element_ids = flatten_data(self.inputs["Elements"].sv_get(), target_level=1)
if SvIfcStore.file is None:
SvIfcStore.file = SvIfcStore.create_boilerplate()
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
try:
elements = [self.file.by_id(int(step_id)) for step_id in element_ids]
print(elements[0])
except Exception as e:
raise Exception("Instance ID not found", e)
if self.node_id not in SvIfcStore.id_map.values(): if self.node_id not in SvIfcStore.id_map:
element = self.create(name, properties, elements) element = self.create(name, properties, elements)
else: else:
element = self.edit(name, properties, elements) element = self.edit(name, properties, elements)
self.outputs["entity"].sv_set([[element]]) self.outputs["Entity"].sv_set([element])
self.outputs["file"].sv_set([[self.file]])
def create(self, name, properties, elements): def create(self, name, properties, elements):
results = [] results = []
for element in elements: for element in elements:
result = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name=name) print("element: ", element)
ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, properties=json.loads(properties)) result = ifcopenshell.api.run(
SvIfcStore.id_map[result.id()] = self.node_id "pset.add_pset", self.file, product=element, name=name
)
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=result,
properties=json.loads(properties),
)
print("result: ", result)
SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id())
results.append(result) results.append(result)
return result return results
def edit(self, name, properties, elements): def edit(self, name, properties, elements):
result = self.get_existing_element() result_ids = SvIfcStore.id_map[self.node_id]
ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, name=name, properties=json.loads(properties)) results = []
return result for result_id in result_ids:
result = self.file.by_id(result_id)
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=result,
name=name,
properties=json.loads(properties),
)
results.append(result)
return results
def get_existing_element(self): # def get_existing_element(self):
entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)] # entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)]
return self.file.by_id(entity_id)
# return self.file.by_id(entity_id)
def register(): def register():
@@ -24,17 +24,37 @@ from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting from sverchok.data_structure import (
updateNode,
flatten_data,
repeat_last_for_length,
ensure_min_nesting,
)
class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcAddSpatialElement(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
bl_idname = "SvIfcAddSpatialElement" bl_idname = "SvIfcAddSpatialElement"
bl_label = "IFC Add Spatial Element" bl_label = "IFC Add Spatial Element"
node_dict = {} node_dict = {}
Names: StringProperty(name="Name(s)", update=updateNode) Names: StringProperty(
IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace") name="Name(s)",
Elements: StringProperty(name="Elements", update=updateNode) description="Name or list of names of the spacial element.",
update=updateNode,
)
IfcClass: StringProperty(
name="IFC Class",
description='IfcClass of the spacial element. Eg. "IfcSpace".\nYou can use the "IFC Class Picker" node to find a relevant class.',
update=updateNode,
default="IfcSpace",
)
Elements: StringProperty(
name="Elements",
description="The IfcElements you want to add to the spacial element.\nThis can also be a (list of) spacial elements. Eg. IfcSpaces aggregated to an IfcBuildingStorey.",
update=updateNode,
)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names" self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
@@ -44,12 +64,16 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.node_dict[hash(self)] = {} 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 = "Ifc entity by type." layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Add IfcElements to an IfcSpatialElement."
def process(self): def process(self):
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:
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads self.node_dict[
hash(self)
] = {} # happens if node is already on canvas when blender loads
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))
@@ -58,7 +82,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
edit = False edit = False
edit_elements = False edit_elements = False
for i in range(len(self.inputs)): for i in range(len(self.inputs)):
input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default=[]) input = self.inputs[self.sv_input_names[i]].sv_get(
deepcopy=True, default=[]
)
if ( if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name] and input != self.node_dict[hash(self)][self.inputs[i].name]
@@ -69,20 +95,27 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.node_dict[hash(self)][self.inputs[i].name] = input.copy() self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1) 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.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 = ensure_min_nesting(self.inputs["Elements"].sv_get(), 2)
self.elements = flatten_data(self.elements, target_level=2) self.elements = flatten_data(self.elements, target_level=2)
if not self.elements[0][0]: if not self.elements[0][0]:
raise Exception('Mandatory input "Element(s)" is missing.') raise Exception('Mandatory input "Element(s)" is missing.')
return return
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
self.elements = [[self.file.by_id(step_id) for step_id in element] for element in self.elements] self.elements = [
[self.file.by_id(step_id) for step_id in element]
for element in self.elements
]
if "len" not in self.node_dict[hash(self)]: if "len" not in self.node_dict[hash(self)]:
self.node_dict[hash(self)]["len"] = 0 self.node_dict[hash(self)]["len"] = 0
self.names = self.repeat_input_unique(self.names, len(self.elements)) self.names = self.repeat_input_unique(self.names, len(self.elements))
if (self.node_id not in SvIfcStore.id_map) or (len(self.elements) != self.node_dict[hash(self)]["len"]): if (self.node_id not in SvIfcStore.id_map) or (
len(self.elements) != self.node_dict[hash(self)]["len"]
):
self.remove() self.remove()
elements = self.create() elements = self.create()
self.node_dict[hash(self)]["len"] = len(self.elements) self.node_dict[hash(self)]["len"] = len(self.elements)
@@ -99,13 +132,28 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
if index is not None: if index is not None:
iterator = [index] iterator = [index]
for i in iterator: for i in iterator:
result = ifcopenshell.api.run("root.create_entity", self.file, name=self.names[i], ifc_class=self.ifc_class) result = ifcopenshell.api.run(
"root.create_entity",
self.file,
name=self.names[i],
ifc_class=self.ifc_class,
)
for items in self.elements[i]: for items in self.elements[i]:
if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"): if items.is_a("IfcSpatialElement") or items.is_a(
ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result) "IfcSpatialStructureElement"
):
ifcopenshell.api.run(
"aggregate.assign_object",
self.file,
product=items,
relating_object=result,
)
else: else:
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", self.file, product=items, relating_structure=result "spatial.assign_container",
self.file,
product=items,
relating_structure=result,
) )
SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id())
spatial_ids.append(result.id()) spatial_ids.append(result.id())
@@ -129,24 +177,38 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
for element in self.elements[i]: for element in self.elements[i]:
element_set = set([element]) element_set = set([element])
for removed_element in subelements - element_set: for removed_element in subelements - element_set:
if removed_element.is_a("IfcSpatialElement") or removed_element.is_a( if removed_element.is_a(
"IfcSpatialStructureElement" "IfcSpatialElement"
): ) or removed_element.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run( ifcopenshell.api.run(
"aggregate.unassign_object", self.file, product=removed_element, relating_object=result "aggregate.unassign_object",
self.file,
product=removed_element,
relating_object=result,
) )
else: else:
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.unassign_container", self.file, product=removed_element, relating_object=result "spatial.unassign_container",
self.file,
product=removed_element,
relating_object=result,
) )
for added_element in element_set - subelements: for added_element in element_set - subelements:
if added_element.is_a("IfcSpatialElement") or added_element.is_a("IfcSpatialStructureElement"): if added_element.is_a(
"IfcSpatialElement"
) or added_element.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run( ifcopenshell.api.run(
"aggregate.assign_object", self.file, product=added_element, relating_object=result "aggregate.assign_object",
self.file,
product=added_element,
relating_object=result,
) )
else: else:
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", self.file, product=added_element, relating_structure=result "spatial.assign_container",
self.file,
product=added_element,
relating_structure=result,
) )
spatial_ids.append(result.id()) spatial_ids.append(result.id())
SvIfcStore.id_map[self.node_id] = spatial_ids SvIfcStore.id_map[self.node_id] = spatial_ids
@@ -163,7 +225,8 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
input = repeat_last_for_length(input, count, deepcopy=False) input = repeat_last_for_length(input, count, deepcopy=False)
if input[0]: if input[0]:
input = [ input = [
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(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 ] # add number to duplicates
return input return input
+62 -21
View File
@@ -26,7 +26,13 @@ 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, BoolProperty, PointerProperty from bpy.props import (
StringProperty,
EnumProperty,
IntProperty,
BoolProperty,
PointerProperty,
)
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter from sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter
from blenderbim.bim.module.root.prop import get_contexts from blenderbim.bim.module.root.prop import get_contexts
@@ -36,7 +42,9 @@ from sverchok.core.socket_data import sv_get_socket
from itertools import chain, cycle from itertools import chain, cycle
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcBMeshToIfcRepr(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
""" """
Triggers: BMesh to Ifc Repr Triggers: BMesh to Ifc Repr
Tooltip: Blender mesh to Ifc Shape Representation Tooltip: Blender mesh to Ifc Shape Representation
@@ -53,7 +61,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
updateNode(self, context) updateNode(self, context)
self.refresh_local = False self.refresh_local = False
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) refresh_local: BoolProperty(
name="Update Node", description="Update Node", update=refresh_node
)
context_types = [ context_types = [
("Model", "Model", "Context type: Model", 0), ("Model", "Model", "Context type: Model", 0),
@@ -73,10 +83,17 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3), ("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3),
] ]
blender_objects: PointerProperty( blender_objects: PointerProperty(
name="Blender Mesh(es)", description="Blender Mesh Object(s)", update=updateNode, type=bpy.types.Object name="Blender Mesh(es)",
description="Blender Mesh Object(s)",
update=updateNode,
type=bpy.types.Object,
) )
context_type: EnumProperty( context_type: EnumProperty(
name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode name="Context Type",
description="Default: Model",
default="Model",
items=context_types,
update=updateNode,
) )
context_identifier: EnumProperty( context_identifier: EnumProperty(
name="Context Identifier", name="Context Identifier",
@@ -96,16 +113,20 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
def sv_init(self, context): def sv_init(self, context):
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("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.outputs.new("SvMatrixSocket", "Locations") self.outputs.new("SvMatrixSocket", "Locations")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.operator( 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. \nTakes one or multiple geometries." ).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries.\nDeconstructs joined geometries and creates a separate representation for each."
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)
@@ -115,7 +136,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
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:
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads self.node_dict[
hash(self)
] = {} # happens if node is already on canvas when blender loads
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))
@@ -179,16 +202,20 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
context=self.get_context(), 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_obj.append(representation.id()) representations_ids_obj.append(representation.id())
locations_obj.append(obj.matrix_world) locations_obj.append(obj.matrix_world)
representations_ids.append(representations_ids_obj) representations_ids.append(representations_ids_obj)
locations.append(locations_obj) locations.append(locations_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append( SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
representations_ids_obj "Representations", []
) ).append(representations_ids_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(locations_obj) SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Locations", []
).append(locations_obj)
try: try:
bpy.ops.object.mode_set(mode="OBJECT") bpy.ops.object.mode_set(mode="OBJECT")
except: except:
@@ -202,7 +229,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj: for step_id in obj:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id) "geometry.remove_representation",
self.file,
representation=self.file.by_id(step_id),
) )
del SvIfcStore.id_map[self.node_id]["Representations"] del SvIfcStore.id_map[self.node_id]["Representations"]
del SvIfcStore.id_map[self.node_id]["Locations"] del SvIfcStore.id_map[self.node_id]["Locations"]
@@ -213,9 +242,13 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
self.file, self.context_type, self.context_identifier, self.target_view self.file, self.context_type, self.context_identifier, self.target_view
) )
if not context: if not context:
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type) parent = ifcopenshell.util.representation.get_context(
self.file, self.context_type
)
if not parent: if not parent:
parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type) parent = ifcopenshell.api.run(
"context.add_context", self.file, context_type=self.context_type
)
context = ifcopenshell.api.run( context = ifcopenshell.api.run(
"context.add_context", "context.add_context",
self.file, self.file,
@@ -224,7 +257,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
target_view=self.target_view, target_view=self.target_view,
parent=parent, parent=parent,
) )
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Contexts", []
).append(context.id())
return context return context
def sv_free(self): def sv_free(self):
@@ -234,7 +269,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj: for step_id in obj:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id) "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]:
@@ -243,10 +280,14 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
if not self.file.get_inverse(context): if not self.file.get_inverse(context):
if self.file.by_id(context_id).ParentContext: if self.file.by_id(context_id).ParentContext:
parent = 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) ifcopenshell.api.run(
"context.remove_context", self.file, context=context
)
if parent: if parent:
if not self.file.get_inverse(parent): if not self.file.get_inverse(parent):
ifcopenshell.api.run("context.remove_context", self.file, context=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]
+26 -9
View File
@@ -16,31 +16,48 @@
# 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/>.
import itertools
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, flatten_data
class SvIfcByGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcByGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcByGuid" bl_idname = "SvIfcByGuid"
bl_label = "IFC By Guid" bl_label = "IFC By Guid"
file: StringProperty(name="file", update=updateNode) n_id: StringProperty(default="")
guid: StringProperty(name="guid", update=updateNode) guid: StringProperty(name="Guid(s)", update=updateNode)
id_iter = itertools.count()
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
self.inputs.new("SvStringsSocket", "guid").prop_name = "guid" self.inputs.new("SvStringsSocket", "guid").prop_name = "guid"
self.outputs.new("SvStringsSocket", "entity") self.outputs.new("SvStringsSocket", "Entities")
def draw_buttons(self, context, layout):
layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Get IFC element by guid. Takes one or multiple guids."
def process(self): def process(self):
self.sv_input_names = ["file", "guid"] print("\n\n", "#" * 30, "Running SvIfcByGuid node", "#" * 30)
super().process() print("self: ", self)
print("id(self): ", id(self))
print("hash(self): ", hash(self))
print("node_id: ", self.node_id)
self.id = next(self.id_iter)
print("self.id (itertool counter): ", self.id)
def process_ifc(self, file, guid): self.guids = flatten_data(self.inputs["guid"].sv_get(), target_level=1)
self.outputs["entity"].sv_set([[file.by_guid(guid)]]) if not self.guids[0]:
return
self.file = SvIfcStore.get_file()
self.entities = [self.file.by_guid(guid) for guid in self.guids]
self.outputs["Entities"].sv_set(self.entities)
def register(): def register():
+26 -11
View File
@@ -48,7 +48,11 @@ def get_ifc_products(self, context):
] ]
) )
if file.schema == "IFC2X3": if file.schema == "IFC2X3":
ifc_products[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "") ifc_products[2] = (
"IfcSpatialStructureElement",
"IfcSpatialStructureElement",
"",
)
return ifc_products return ifc_products
@@ -90,25 +94,31 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
update=update_ifc_products, update=update_ifc_products,
) )
ifc_class: EnumProperty( ifc_class: EnumProperty(
items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode items=get_ifc_classes,
name="IfcClass",
description="Pick an IfcClass from drop-down.",
update=updateNode,
) )
custom_ifc_class: StringProperty( custom_ifc_class: StringProperty(
name="Custom IfcClass", description="Give the name of your custom IfcClass.", update=updateNode name="Custom IfcClass",
description="Give the name of your custom IfcClass.",
update=updateNode,
) )
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product" self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class" self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class" self.inputs.new(
self.outputs.new("SvStringsSocket", "Entity") "SvStringsSocket", "custom_ifc_class"
).prop_name = "custom_ifc_class"
self.outputs.new("SvStringsSocket", "Entities")
self.outputs.new("SvStringsSocket", "Entity Ids")
self.width = 200 self.width = 200
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.operator( layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = ( ).tooltip = "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
"Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
)
def process(self): def process(self):
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
@@ -120,11 +130,16 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
def process_ifc(self, ifc_product, ifc_class, custom_ifc_class): def process_ifc(self, ifc_product, ifc_class, custom_ifc_class):
if custom_ifc_class: if custom_ifc_class:
self.outputs["Entity"].sv_set([self.file.by_type(custom_ifc_class)]) entities = self.file.by_type(custom_ifc_class)
self.outputs["Entities"].sv_set(entities)
self.outputs["Entity Ids"].sv_set([e.id() for e in entities])
elif ifc_class: elif ifc_class:
self.outputs["Entity"].sv_set([self.file.by_type(ifc_class)]) entities = self.file.by_type(ifc_class)
self.outputs["Entities"].sv_set(self.file.by_type(ifc_class))
self.outputs["Entity Ids"].sv_set([e.id() for e in entities])
else: else:
self.outputs["Entity"].sv_set([]) self.outputs["Entities"].sv_set([])
self.outputs["Entity Ids"].sv_set([])
def register(): def register():
+89 -25
View File
@@ -24,10 +24,17 @@ from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty, BoolProperty from bpy.props import StringProperty, BoolProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting from sverchok.data_structure import (
updateNode,
flatten_data,
repeat_last_for_length,
ensure_min_nesting,
)
class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcCreateEntity(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
bl_idname = "SvIfcCreateEntity" bl_idname = "SvIfcCreateEntity"
bl_label = "IFC Create Entity" bl_label = "IFC Create Entity"
node_dict = {} node_dict = {}
@@ -39,12 +46,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
self.process() self.process()
self.refresh_local = False self.refresh_local = False
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) refresh_local: BoolProperty(
name="Update Node", description="Update Node", update=refresh_node
)
Names: StringProperty(name="Names", default="", update=updateNode) Names: StringProperty(
Descriptions: StringProperty(name="Descriptions", default="", update=updateNode) name="Names",
default="",
description="Entity name or list of names.",
update=updateNode,
)
Descriptions: StringProperty(
name="Descriptions",
default="",
description="Entity description or list of descriptions.",
update=updateNode,
)
IfcClass: StringProperty(name="IfcClass", update=updateNode) IfcClass: StringProperty(name="IfcClass", update=updateNode)
Representations: StringProperty(name="Representations", default="", update=updateNode) Representations: StringProperty(
name="Representations",
description='IfcRepresentation(s). Use eg. "IFC BMesh to IFC" or "IFC Sverchok to IFC" nodes to create representations.',
default="",
update=updateNode,
)
# Locations: FloatVectorProperty(name="Locations", default="", update=updateNode) # Locations: FloatVectorProperty(name="Locations", default="", update=updateNode)
Properties: StringProperty(name="properties", update=updateNode) Properties: StringProperty(name="properties", update=updateNode)
@@ -52,7 +76,9 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names" self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions" self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions"
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass" self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
self.inputs.new("SvStringsSocket", "Representations").prop_name = "Representations" self.inputs.new(
"SvStringsSocket", "Representations"
).prop_name = "Representations"
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False
self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties" self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
self.outputs.new("SvStringsSocket", "Entities") self.outputs.new("SvStringsSocket", "Entities")
@@ -69,17 +95,27 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
def process(self): def process(self):
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1) self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1)
self.descriptions = flatten_data(self.inputs["Descriptions"].sv_get(), target_level=1) self.descriptions = flatten_data(
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0] self.inputs["Descriptions"].sv_get(), target_level=1
self.representations = ensure_min_nesting(self.inputs["Representations"].sv_get(), 2) )
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[
0
]
self.representations = ensure_min_nesting(
self.inputs["Representations"].sv_get(), 2
)
self.representations = flatten_data(self.representations, target_level=2) self.representations = flatten_data(self.representations, target_level=2)
self.locations = ensure_min_nesting(self.inputs["Locations"].sv_get(default=[]), 2) self.locations = ensure_min_nesting(
self.inputs["Locations"].sv_get(default=[]), 2
)
self.properties = self.inputs["Properties"].sv_get() self.properties = self.inputs["Properties"].sv_get()
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:
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads self.node_dict[
hash(self)
] = {} # happens if node is already on canvas when blender loads
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))
if not self.inputs["IfcClass"].sv_get()[0][0]: if not self.inputs["IfcClass"].sv_get()[0][0]:
@@ -87,7 +123,9 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
edit = False edit = False
for i in range(len(self.inputs)): for i in range(len(self.inputs)):
input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default=[]) input = self.inputs[self.sv_input_names[i]].sv_get(
deepcopy=True, default=[]
)
if ( if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name] and input != self.node_dict[hash(self)][self.inputs[i].name]
@@ -103,14 +141,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
try: try:
# self.representations = [self.file.by_id(step_id) for step_id in self.representations] # self.representations = [self.file.by_id(step_id) for step_id in self.representations]
self.representations = [ self.representations = [
[self.file.by_id(step_id) for step_id in representation] for representation in self.representations [self.file.by_id(step_id) for step_id in representation]
for representation in self.representations
] ]
except Exception as e: except Exception as e:
raise raise
self.names = self.repeat_input_unique(self.names, len(self.representations)) self.names = self.repeat_input_unique(self.names, len(self.representations))
self.descriptions = self.repeat_input_unique(self.descriptions, len(self.representations)) self.descriptions = self.repeat_input_unique(
elif not self.representations[0]: self.descriptions, len(self.representations)
self.descriptions = self.repeat_input_unique(self.descriptions, len(self.names)) )
elif not self.representations[0][0]:
self.descriptions = self.repeat_input_unique(
self.descriptions, len(self.names)
)
if self.node_id not in SvIfcStore.id_map: if self.node_id not in SvIfcStore.id_map:
entities = self.create() entities = self.create()
@@ -137,19 +180,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
name=self.names[i], name=self.names[i],
description=self.descriptions[i], description=self.descriptions[i],
) )
print("Entity: ", entity)
try: try:
print("Representations: ", self.representations[i])
for repr in self.representations[i]: for repr in self.representations[i]:
if self.representations[i]: print("Representation: ", repr)
if repr:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr "geometry.assign_representation",
self.file,
product=entity,
representation=repr,
) )
except IndexError: except IndexError:
pass pass
try: try:
for loc in self.locations[i]: for loc in self.locations[i]:
if isinstance(self.locations[i], Matrix): print("Location: ", loc)
if isinstance(loc, Matrix):
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=entity, matrix=loc "geometry.edit_object_placement",
self.file,
product=entity,
matrix=loc,
) )
except IndexError: except IndexError:
pass pass
@@ -179,19 +232,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
entity.Representation = repr entity.Representation = repr
elif repr: elif repr:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr "geometry.assign_representation",
self.file,
product=entity,
representation=repr,
) )
except IndexError: except IndexError:
pass pass
try: try:
for loc in self.locations[i]: for loc in self.locations[i]:
if isinstance(loc, Matrix): if isinstance(loc, Matrix):
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=loc) ifcopenshell.api.run(
"geometry.edit_object_placement",
self.file,
product=entity,
matrix=loc,
)
except IndexError: except IndexError:
pass pass
if entity.is_a() != self.ifc_class: if entity.is_a() != self.ifc_class:
SvIfcStore.id_map[self.node_id].remove(step_id) SvIfcStore.id_map[self.node_id].remove(step_id)
entity = ifcopenshell.util.schema.reassign_class(self.file, entity, self.ifc_class) entity = ifcopenshell.util.schema.reassign_class(
self.file, entity, self.ifc_class
)
SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id()) SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id())
entities_ids.append(entity.id()) entities_ids.append(entity.id())
@@ -203,7 +266,8 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
input = repeat_last_for_length(input, count, deepcopy=False) input = repeat_last_for_length(input, count, deepcopy=False)
if input[0]: if input[0]:
input = [ input = [
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(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 ] # add number to duplicates
return input return input
+2 -2
View File
@@ -46,7 +46,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
bl_idname = "SvIfcCreateShape" bl_idname = "SvIfcCreateShape"
bl_label = "IFC Create Blender Shape" bl_label = "IFC Create Blender Shape"
entity: StringProperty(name="Entities", update=updateNode) entity: StringProperty(name="Entity Id(s)", update=updateNode)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Entities").prop_name = "entity" self.inputs.new("SvStringsSocket", "Entities").prop_name = "entity"
@@ -56,7 +56,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
row = layout.row(align=True) row = layout.row(align=True)
row.operator( row.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Create Blender shape from IfcEntity ID. Takes one or multiple IfcEntity IDs." ).tooltip = "Create Blender shape from IfcEntity Id. Takes one or multiple IfcEntity IDs."
row.prop(self, "refresh_local", icon="FILE_REFRESH") row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self): def process(self):
+34 -6
View File
@@ -20,25 +20,53 @@ import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, flatten_data
class SvIfcGetAttribute(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcGetAttribute(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
bl_idname = "SvIfcGetAttribute" bl_idname = "SvIfcGetAttribute"
bl_label = "IFC Get Attribute" bl_label = "IFC Get Attribute"
entity: StringProperty(name="entity", update=updateNode) entity: StringProperty(name="Entity Ids", update=updateNode)
attribute_name: StringProperty(name="attribute_name", update=updateNode) attribute_name: StringProperty(
name="Attribute name",
description='Name of attribute, eg. "Name".',
update=updateNode,
)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" self.inputs.new("SvStringsSocket", "entity").prop_name = "entity"
self.inputs.new("SvStringsSocket", "attribute_name").prop_name = "attribute_name" self.inputs.new(
"SvStringsSocket", "attribute_name"
).prop_name = "attribute_name"
self.outputs.new("SvStringsSocket", "value") self.outputs.new("SvStringsSocket", "value")
def draw_buttons(self, context, layout):
layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = (
"Get the value of an attribute of an IfcEntity. Can take multiple entities."
)
def process(self): def process(self):
self.value_out = [] self.value_out = []
entity_nested_inputs = self.inputs["entity"].sv_get() entity_nested_input_ids = flatten_data(
self.inputs["entity"].sv_get(), target_level=1
)
if not entity_nested_input_ids[0]:
return
self.file = SvIfcStore.get_file()
try:
entity_nested_inputs = [
self.file.by_id(int(step_id)) for step_id in entity_nested_input_ids
]
print(entity_nested_inputs)
except Exception as e:
raise Exception("Instance ID not found", e)
attribute_name = self.inputs["attribute_name"].sv_get()[0][0] attribute_name = self.inputs["attribute_name"].sv_get()[0][0]
for entities in entity_nested_inputs: for entities in entity_nested_inputs:
if hasattr(entities, "__iter__"): if hasattr(entities, "__iter__"):
+44 -15
View File
@@ -20,35 +20,64 @@ import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, flatten_data
class SvIfcGetProperty(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcGetProperty(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
bl_idname = "SvIfcGetProperty" bl_idname = "SvIfcGetProperty"
bl_label = "IFC Get Property" bl_label = "IFC Get Property"
entity: StringProperty(name="entity", update=updateNode) entity: StringProperty(name="Entity Ids", update=updateNode)
pset_name: StringProperty(name="pset_name", update=updateNode) pset_name: StringProperty(
prop_name: StringProperty(name="prop_name", update=updateNode) name="Pset Name",
description='Name of the property set, eg. "Pset_WallCommon".',
update=updateNode,
)
prop_name: StringProperty(
name="Prop Name",
description='Name of the property, eg. "IsExternal".',
update=updateNode,
)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" self.inputs.new("SvStringsSocket", "entity_ids").prop_name = "entity"
self.inputs.new("SvStringsSocket", "pset_name").prop_name = "pset_name" self.inputs.new("SvStringsSocket", "pset_name").prop_name = "pset_name"
self.inputs.new("SvStringsSocket", "prop_name").prop_name = "prop_name" self.inputs.new("SvStringsSocket", "prop_name").prop_name = "prop_name"
self.outputs.new("SvStringsSocket", "value") self.outputs.new("SvStringsSocket", "value")
def process(self): def draw_buttons(self, context, layout):
self.sv_input_names = ["entity", "pset_name", "prop_name"] layout.operator(
self.value_out = [] "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
super().process() ).tooltip = (
self.outputs["value"].sv_set(self.value_out) "Get the value of a property of an IfcEntity. Can take multiple entity ids."
)
def process_ifc(self, entity, pset_name, prop_name): def process(self):
self.sv_input_names = ["entity_ids", "pset_name", "prop_name"]
entities_ids = flatten_data(self.inputs["entity_ids"].sv_get(), target_level=1)
pset_name = flatten_data(self.inputs["pset_name"].sv_get(), target_level=1)[0]
prop_name = flatten_data(self.inputs["prop_name"].sv_get(), target_level=1)[0]
if not entities_ids[0]:
return
self.file = SvIfcStore.get_file()
try: try:
self.value_out.append(ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name]) self.entities = [self.file.by_id(int(step_id)) for step_id in entities_ids]
except: except Exception as e:
pass raise Exception(f"Invalid entity id: {e}")
self.value_out = []
for entity in self.entities:
try:
self.value_out.append(
ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name]
)
except:
pass
self.outputs["value"].sv_set(self.value_out)
def register(): def register():
+36 -18
View File
@@ -19,30 +19,50 @@
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, ensure_min_nesting, flatten_data
class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcReadEntity(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
bl_idname = "SvIfcReadEntity" bl_idname = "SvIfcReadEntity"
bl_label = "IFC Read Entity" bl_label = "IFC Read Entity"
file: StringProperty(name="file", update=updateNode) entity: StringProperty(name="Entity Id", update=updateNode)
entity: StringProperty(name="entity", update=updateNode)
current_ifc_class: StringProperty(name="current_ifc_class") current_ifc_class: StringProperty(name="current_ifc_class")
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" self.inputs.new("SvStringsSocket", "entity").prop_name = "entity"
self.outputs.new("SvStringsSocket", "id") self.outputs.new("SvStringsSocket", "id")
self.outputs.new("SvStringsSocket", "is_a") self.outputs.new("SvStringsSocket", "is_a")
def draw_buttons(self, context, layout):
layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = (
"Decompose an IfcEntity into its attributes. Takes one entity id as input"
)
def process(self): def process(self):
self.sv_input_names = ["file", "entity"] self.sv_input_names = ["entity"]
ifc_class = self.inputs["entity"].sv_get()[0][0] # ifc_class = ensure_min_nesting(self.inputs["entity"].sv_get(), 1)
if ifc_class: entity_id = flatten_data(self.inputs["entity"].sv_get(), target_level=1)
ifc_class = ifc_class.is_a() print("entity_id", entity_id)
file = self.inputs["file"].sv_get()[0][0] if not entity_id[0]:
return
if len(entity_id) > 1:
raise Exception("Only one entity can be read at a time")
self.file = SvIfcStore.get_file()
try:
entity = self.file.by_id(entity_id[0])
except Exception as e:
raise Exception("Instance with id {} not found".format(entity_id), e)
if entity:
ifc_class = entity.is_a()
file = SvIfcStore.get_file()
if file: if file:
schema_name = file.wrapped_data.schema schema_name = file.wrapped_data.schema
else: else:
@@ -52,7 +72,12 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S
if ifc_class != self.current_ifc_class: if ifc_class != self.current_ifc_class:
self.generate_outputs(ifc_class) self.generate_outputs(ifc_class)
super().process()
self.outputs["id"].sv_set([entity.id()])
self.outputs["is_a"].sv_set([entity.is_a()])
for i in range(0, self.entity_schema.attribute_count()):
name = self.entity_schema.attribute_by_index(i).name()
self.outputs[name].sv_set([entity[i]])
def generate_outputs(self, ifc_class): def generate_outputs(self, ifc_class):
while len(self.outputs) > 2: while len(self.outputs) > 2:
@@ -62,13 +87,6 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S
self.outputs.new("SvStringsSocket", name).prop_name = name self.outputs.new("SvStringsSocket", name).prop_name = name
self.current_ifc_class = ifc_class self.current_ifc_class = ifc_class
def process_ifc(self, entity):
self.outputs["id"].sv_set([[entity.id()]])
self.outputs["is_a"].sv_set([[entity.is_a()]])
for i in range(0, self.entity_schema.attribute_count()):
name = self.entity_schema.attribute_by_index(i).name()
self.outputs[name].sv_set([[entity[i]]])
def register(): def register():
bpy.utils.register_class(SvIfcReadEntity) bpy.utils.register_class(SvIfcReadEntity)
+44 -16
View File
@@ -29,7 +29,9 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, ensure_min_nesting from sverchok.data_structure import updateNode, ensure_min_nesting
class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcSverchokToIfcRepr(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
""" """
Triggers: Sv to Ifc Repr Triggers: Sv to Ifc Repr
Tooltip: Sverchok geometry to Ifc Shape Representation Tooltip: Sverchok geometry to Ifc Shape Representation
@@ -59,7 +61,11 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
] ]
context_type: EnumProperty( context_type: EnumProperty(
name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode name="Context Type",
description="Default: Model",
default="Model",
items=context_types,
update=updateNode,
) )
context_identifier: EnumProperty( context_identifier: EnumProperty(
name="Context Identifier", name="Context Identifier",
@@ -78,7 +84,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
def sv_init(self, context): def sv_init(self, context):
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.inputs.new("SvVerticesSocket", "Vertices")
self.inputs.new("SvStringsSocket", "Edges") self.inputs.new("SvStringsSocket", "Edges")
@@ -99,7 +107,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
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:
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads self.node_dict[
hash(self)
] = {} # happens if node is already on canvas when blender loads
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))
@@ -113,7 +123,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
edit = True edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input self.node_dict[hash(self)][self.inputs[i].name] = input
self.vertices = ensure_min_nesting(self.inputs["Vertices"].sv_get(deepcopy=False), 4) self.vertices = ensure_min_nesting(
self.inputs["Vertices"].sv_get(deepcopy=False), 4
)
self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4) self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4)
self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4) self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
data = list(zip(self.vertices, self.edges, self.faces)) data = list(zip(self.vertices, self.edges, self.faces))
@@ -147,12 +159,14 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
faces=[list(map(tuple, item[2]))], faces=[list(map(tuple, item[2]))],
) )
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_obj.append(representation.id()) representations_ids_obj.append(representation.id())
representations_ids.append(representations_ids_obj) representations_ids.append(representations_ids_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append( SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
representations_ids_obj "Representations", []
) ).append(representations_ids_obj)
return representations_ids return representations_ids
def edit(self): def edit(self):
@@ -161,7 +175,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj: for step_id in obj:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id) "geometry.remove_representation",
self.file,
representation=self.file.by_id(step_id),
) )
del SvIfcStore.id_map[self.node_id]["Representations"] del SvIfcStore.id_map[self.node_id]["Representations"]
return return
@@ -171,9 +187,13 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.file, self.context_type, self.context_identifier, self.target_view self.file, self.context_type, self.context_identifier, self.target_view
) )
if not context: if not context:
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type) parent = ifcopenshell.util.representation.get_context(
self.file, self.context_type
)
if not parent: if not parent:
parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type) parent = ifcopenshell.api.run(
"context.add_context", self.file, context_type=self.context_type
)
context = ifcopenshell.api.run( context = ifcopenshell.api.run(
"context.add_context", "context.add_context",
self.file, self.file,
@@ -182,7 +202,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
target_view=self.target_view, target_view=self.target_view,
parent=parent, parent=parent,
) )
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Contexts", []
).append(context.id())
return context return context
def sv_free(self): def sv_free(self):
@@ -191,7 +213,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
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"]:
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id) "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]:
@@ -200,10 +224,14 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
if not self.file.get_inverse(context): if not self.file.get_inverse(context):
if self.file.by_id(context_id).ParentContext: if self.file.by_id(context_id).ParentContext:
parent = 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) ifcopenshell.api.run(
"context.remove_context", self.file, context=context
)
if parent: if parent:
if not self.file.get_inverse(parent): if not self.file.get_inverse(parent):
ifcopenshell.api.run("context.remove_context", self.file, context=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]