mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
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:
@@ -28,22 +28,36 @@ import ifcopenshell
|
||||
|
||||
from bpy.props import StringProperty
|
||||
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):
|
||||
bl_idname = "SvIfcAddPset"
|
||||
bl_label = "IFC Add Pset"
|
||||
Name: StringProperty(name="Name", update=updateNode, default="My_Pset")
|
||||
Properties: StringProperty(name="Properties", update=updateNode, default="{\"Foo\":\"Bar\"}")
|
||||
Elements: StringProperty(name="Elements", update=updateNode)
|
||||
Name: StringProperty(
|
||||
name="Name",
|
||||
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):
|
||||
self.inputs.new("SvStringsSocket", "Name").prop_name = "Name"
|
||||
self.inputs.new("SvTextSocket", "Properties").prop_name = "Properties"
|
||||
self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements"
|
||||
self.outputs.new("SvStringsSocket", "entity")
|
||||
self.outputs.new("SvStringsSocket", "file")
|
||||
self.outputs.new("SvStringsSocket", "Entity")
|
||||
|
||||
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):
|
||||
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]
|
||||
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()
|
||||
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)
|
||||
else:
|
||||
element = self.edit(name, properties, elements)
|
||||
|
||||
self.outputs["entity"].sv_set([[element]])
|
||||
self.outputs["file"].sv_set([[self.file]])
|
||||
self.outputs["Entity"].sv_set([element])
|
||||
|
||||
def create(self, name, properties, elements):
|
||||
results = []
|
||||
for element in elements:
|
||||
result = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name=name)
|
||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, properties=json.loads(properties))
|
||||
SvIfcStore.id_map[result.id()] = self.node_id
|
||||
print("element: ", element)
|
||||
result = ifcopenshell.api.run(
|
||||
"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)
|
||||
return result
|
||||
return results
|
||||
|
||||
def edit(self, name, properties, elements):
|
||||
result = self.get_existing_element()
|
||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, name=name, properties=json.loads(properties))
|
||||
return result
|
||||
result_ids = SvIfcStore.id_map[self.node_id]
|
||||
results = []
|
||||
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):
|
||||
entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)]
|
||||
return self.file.by_id(entity_id)
|
||||
# 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():
|
||||
|
||||
@@ -24,17 +24,37 @@ from ifcsverchok.ifcstore import SvIfcStore
|
||||
|
||||
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
|
||||
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_label = "IFC Add Spatial Element"
|
||||
node_dict = {}
|
||||
|
||||
Names: StringProperty(name="Name(s)", update=updateNode)
|
||||
IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace")
|
||||
Elements: StringProperty(name="Elements", update=updateNode)
|
||||
Names: StringProperty(
|
||||
name="Name(s)",
|
||||
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):
|
||||
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)] = {}
|
||||
|
||||
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):
|
||||
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
|
||||
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))
|
||||
|
||||
@@ -58,7 +82,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
||||
edit = False
|
||||
edit_elements = False
|
||||
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 (
|
||||
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
|
||||
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.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 = flatten_data(self.elements, target_level=2)
|
||||
if not self.elements[0][0]:
|
||||
raise Exception('Mandatory input "Element(s)" is missing.')
|
||||
return
|
||||
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)]:
|
||||
self.node_dict[hash(self)]["len"] = 0
|
||||
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()
|
||||
elements = self.create()
|
||||
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:
|
||||
iterator = [index]
|
||||
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]:
|
||||
if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"):
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result)
|
||||
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
|
||||
"spatial.assign_container",
|
||||
self.file,
|
||||
product=items,
|
||||
relating_structure=result,
|
||||
)
|
||||
SvIfcStore.id_map.setdefault(self.node_id, []).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]:
|
||||
element_set = set([element])
|
||||
for removed_element in subelements - element_set:
|
||||
if removed_element.is_a("IfcSpatialElement") or removed_element.is_a(
|
||||
"IfcSpatialStructureElement"
|
||||
):
|
||||
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
|
||||
"aggregate.unassign_object",
|
||||
self.file,
|
||||
product=removed_element,
|
||||
relating_object=result,
|
||||
)
|
||||
else:
|
||||
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:
|
||||
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(
|
||||
"aggregate.assign_object", self.file, product=added_element, relating_object=result
|
||||
"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
|
||||
"spatial.assign_container",
|
||||
self.file,
|
||||
product=added_element,
|
||||
relating_structure=result,
|
||||
)
|
||||
spatial_ids.append(result.id())
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
||||
|
||||
@@ -26,7 +26,13 @@ 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, IntProperty, BoolProperty, PointerProperty
|
||||
from bpy.props import (
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
IntProperty,
|
||||
BoolProperty,
|
||||
PointerProperty,
|
||||
)
|
||||
from sverchok.node_tree import SverchCustomTreeNode
|
||||
from sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter
|
||||
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
|
||||
|
||||
|
||||
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||
class SvIfcBMeshToIfcRepr(
|
||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
||||
):
|
||||
"""
|
||||
Triggers: BMesh to Ifc Repr
|
||||
Tooltip: Blender mesh to Ifc Shape Representation
|
||||
@@ -53,7 +61,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
updateNode(self, context)
|
||||
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 = [
|
||||
("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),
|
||||
]
|
||||
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(
|
||||
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(
|
||||
name="Context Identifier",
|
||||
@@ -96,16 +113,20 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
|
||||
def sv_init(self, context):
|
||||
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("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("SvMatrixSocket", "Locations")
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.operator(
|
||||
"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.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]
|
||||
|
||||
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)]:
|
||||
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(),
|
||||
)
|
||||
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())
|
||||
locations_obj.append(obj.matrix_world)
|
||||
representations_ids.append(representations_ids_obj)
|
||||
locations.append(locations_obj)
|
||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("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(
|
||||
"Representations", []
|
||||
).append(representations_ids_obj)
|
||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
||||
"Locations", []
|
||||
).append(locations_obj)
|
||||
try:
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
except:
|
||||
@@ -202,7 +229,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
|
||||
for step_id in obj:
|
||||
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]["Locations"]
|
||||
@@ -213,9 +242,13 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
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)
|
||||
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)
|
||||
parent = ifcopenshell.api.run(
|
||||
"context.add_context", self.file, context_type=self.context_type
|
||||
)
|
||||
context = ifcopenshell.api.run(
|
||||
"context.add_context",
|
||||
self.file,
|
||||
@@ -224,7 +257,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
target_view=self.target_view,
|
||||
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
|
||||
|
||||
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 step_id in obj:
|
||||
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]:
|
||||
@@ -243,10 +280,14 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
|
||||
if not self.file.get_inverse(context):
|
||||
if self.file.by_id(context_id).ParentContext:
|
||||
parent = self.file.by_id(context_id).ParentContext
|
||||
ifcopenshell.api.run("context.remove_context", self.file, context=context)
|
||||
ifcopenshell.api.run(
|
||||
"context.remove_context", self.file, context=context
|
||||
)
|
||||
if parent:
|
||||
if not self.file.get_inverse(parent):
|
||||
ifcopenshell.api.run("context.remove_context", self.file, context=parent)
|
||||
ifcopenshell.api.run(
|
||||
"context.remove_context", self.file, context=parent
|
||||
)
|
||||
# print("Removed context with step ID: ", context_id)
|
||||
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
||||
del SvIfcStore.id_map[self.node_id]
|
||||
|
||||
@@ -16,31 +16,48 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import itertools
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcsverchok.helper
|
||||
from ifcsverchok.ifcstore import SvIfcStore
|
||||
from bpy.props import StringProperty
|
||||
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):
|
||||
bl_idname = "SvIfcByGuid"
|
||||
bl_label = "IFC By Guid"
|
||||
file: StringProperty(name="file", update=updateNode)
|
||||
guid: StringProperty(name="guid", update=updateNode)
|
||||
n_id: StringProperty(default="")
|
||||
guid: StringProperty(name="Guid(s)", update=updateNode)
|
||||
id_iter = itertools.count()
|
||||
|
||||
def sv_init(self, context):
|
||||
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
|
||||
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):
|
||||
self.sv_input_names = ["file", "guid"]
|
||||
super().process()
|
||||
print("\n\n", "#" * 30, "Running SvIfcByGuid node", "#" * 30)
|
||||
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.outputs["entity"].sv_set([[file.by_guid(guid)]])
|
||||
self.guids = flatten_data(self.inputs["guid"].sv_get(), target_level=1)
|
||||
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():
|
||||
|
||||
@@ -48,7 +48,11 @@ def get_ifc_products(self, context):
|
||||
]
|
||||
)
|
||||
if file.schema == "IFC2X3":
|
||||
ifc_products[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "")
|
||||
ifc_products[2] = (
|
||||
"IfcSpatialStructureElement",
|
||||
"IfcSpatialStructureElement",
|
||||
"",
|
||||
)
|
||||
return ifc_products
|
||||
|
||||
|
||||
@@ -90,25 +94,31 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
|
||||
update=update_ifc_products,
|
||||
)
|
||||
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(
|
||||
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):
|
||||
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
|
||||
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
|
||||
self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class"
|
||||
self.outputs.new("SvStringsSocket", "Entity")
|
||||
self.inputs.new(
|
||||
"SvStringsSocket", "custom_ifc_class"
|
||||
).prop_name = "custom_ifc_class"
|
||||
self.outputs.new("SvStringsSocket", "Entities")
|
||||
self.outputs.new("SvStringsSocket", "Entity Ids")
|
||||
self.width = 200
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.operator(
|
||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
||||
).tooltip = (
|
||||
"Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
|
||||
)
|
||||
).tooltip = "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
|
||||
|
||||
def process(self):
|
||||
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):
|
||||
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:
|
||||
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:
|
||||
self.outputs["Entity"].sv_set([])
|
||||
self.outputs["Entities"].sv_set([])
|
||||
self.outputs["Entity Ids"].sv_set([])
|
||||
|
||||
|
||||
def register():
|
||||
|
||||
@@ -24,10 +24,17 @@ from ifcsverchok.ifcstore import SvIfcStore
|
||||
|
||||
from bpy.props import StringProperty, BoolProperty
|
||||
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_label = "IFC Create Entity"
|
||||
node_dict = {}
|
||||
@@ -39,12 +46,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
self.process()
|
||||
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)
|
||||
Descriptions: StringProperty(name="Descriptions", default="", update=updateNode)
|
||||
Names: StringProperty(
|
||||
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)
|
||||
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)
|
||||
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", "Descriptions").prop_name = "Descriptions"
|
||||
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("SvStringsSocket", "Properties").prop_name = "Properties"
|
||||
self.outputs.new("SvStringsSocket", "Entities")
|
||||
@@ -69,17 +95,27 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
|
||||
def process(self):
|
||||
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.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.descriptions = flatten_data(
|
||||
self.inputs["Descriptions"].sv_get(), target_level=1
|
||||
)
|
||||
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.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.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
|
||||
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))
|
||||
if not self.inputs["IfcClass"].sv_get()[0][0]:
|
||||
@@ -87,7 +123,9 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
|
||||
edit = False
|
||||
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 (
|
||||
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
|
||||
and input != self.node_dict[hash(self)][self.inputs[i].name]
|
||||
@@ -103,14 +141,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
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 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:
|
||||
raise
|
||||
self.names = self.repeat_input_unique(self.names, len(self.representations))
|
||||
self.descriptions = self.repeat_input_unique(self.descriptions, len(self.representations))
|
||||
elif not self.representations[0]:
|
||||
self.descriptions = self.repeat_input_unique(self.descriptions, len(self.names))
|
||||
self.descriptions = self.repeat_input_unique(
|
||||
self.descriptions, len(self.representations)
|
||||
)
|
||||
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:
|
||||
entities = self.create()
|
||||
@@ -137,19 +180,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
name=self.names[i],
|
||||
description=self.descriptions[i],
|
||||
)
|
||||
print("Entity: ", entity)
|
||||
try:
|
||||
print("Representations: ", self.representations[i])
|
||||
for repr in self.representations[i]:
|
||||
if self.representations[i]:
|
||||
print("Representation: ", repr)
|
||||
if repr:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=entity, representation=repr
|
||||
"geometry.assign_representation",
|
||||
self.file,
|
||||
product=entity,
|
||||
representation=repr,
|
||||
)
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
for loc in self.locations[i]:
|
||||
if isinstance(self.locations[i], Matrix):
|
||||
print("Location: ", loc)
|
||||
if isinstance(loc, Matrix):
|
||||
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:
|
||||
pass
|
||||
@@ -179,19 +232,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
|
||||
entity.Representation = repr
|
||||
elif repr:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=entity, representation=repr
|
||||
"geometry.assign_representation",
|
||||
self.file,
|
||||
product=entity,
|
||||
representation=repr,
|
||||
)
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
for loc in self.locations[i]:
|
||||
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:
|
||||
pass
|
||||
if entity.is_a() != self.ifc_class:
|
||||
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())
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
|
||||
|
||||
bl_idname = "SvIfcCreateShape"
|
||||
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):
|
||||
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.operator(
|
||||
"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")
|
||||
|
||||
def process(self):
|
||||
|
||||
@@ -20,25 +20,53 @@ import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import ifcsverchok.helper
|
||||
from ifcsverchok.ifcstore import SvIfcStore
|
||||
from bpy.props import StringProperty
|
||||
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_label = "IFC Get Attribute"
|
||||
entity: StringProperty(name="entity", update=updateNode)
|
||||
attribute_name: StringProperty(name="attribute_name", update=updateNode)
|
||||
entity: StringProperty(name="Entity Ids", update=updateNode)
|
||||
attribute_name: StringProperty(
|
||||
name="Attribute name",
|
||||
description='Name of attribute, eg. "Name".',
|
||||
update=updateNode,
|
||||
)
|
||||
|
||||
def sv_init(self, context):
|
||||
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")
|
||||
|
||||
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):
|
||||
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]
|
||||
for entities in entity_nested_inputs:
|
||||
if hasattr(entities, "__iter__"):
|
||||
|
||||
@@ -20,35 +20,64 @@ import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import ifcsverchok.helper
|
||||
from ifcsverchok.ifcstore import SvIfcStore
|
||||
from bpy.props import StringProperty
|
||||
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_label = "IFC Get Property"
|
||||
entity: StringProperty(name="entity", update=updateNode)
|
||||
pset_name: StringProperty(name="pset_name", update=updateNode)
|
||||
prop_name: StringProperty(name="prop_name", update=updateNode)
|
||||
entity: StringProperty(name="Entity Ids", update=updateNode)
|
||||
pset_name: StringProperty(
|
||||
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):
|
||||
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", "prop_name").prop_name = "prop_name"
|
||||
self.outputs.new("SvStringsSocket", "value")
|
||||
|
||||
def process(self):
|
||||
self.sv_input_names = ["entity", "pset_name", "prop_name"]
|
||||
self.value_out = []
|
||||
super().process()
|
||||
self.outputs["value"].sv_set(self.value_out)
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.operator(
|
||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
||||
).tooltip = (
|
||||
"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:
|
||||
self.value_out.append(ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name])
|
||||
except:
|
||||
pass
|
||||
self.entities = [self.file.by_id(int(step_id)) for step_id in entities_ids]
|
||||
except Exception as e:
|
||||
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():
|
||||
|
||||
@@ -19,30 +19,50 @@
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcsverchok.helper
|
||||
from ifcsverchok.ifcstore import SvIfcStore
|
||||
from bpy.props import StringProperty
|
||||
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_label = "IFC Read Entity"
|
||||
file: StringProperty(name="file", update=updateNode)
|
||||
entity: StringProperty(name="entity", update=updateNode)
|
||||
entity: StringProperty(name="Entity Id", update=updateNode)
|
||||
current_ifc_class: StringProperty(name="current_ifc_class")
|
||||
|
||||
def sv_init(self, context):
|
||||
self.inputs.new("SvStringsSocket", "file").prop_name = "file"
|
||||
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity"
|
||||
self.outputs.new("SvStringsSocket", "id")
|
||||
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):
|
||||
self.sv_input_names = ["file", "entity"]
|
||||
ifc_class = self.inputs["entity"].sv_get()[0][0]
|
||||
if ifc_class:
|
||||
ifc_class = ifc_class.is_a()
|
||||
file = self.inputs["file"].sv_get()[0][0]
|
||||
self.sv_input_names = ["entity"]
|
||||
# ifc_class = ensure_min_nesting(self.inputs["entity"].sv_get(), 1)
|
||||
entity_id = flatten_data(self.inputs["entity"].sv_get(), target_level=1)
|
||||
print("entity_id", entity_id)
|
||||
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:
|
||||
schema_name = file.wrapped_data.schema
|
||||
else:
|
||||
@@ -52,7 +72,12 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S
|
||||
|
||||
if ifc_class != self.current_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):
|
||||
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.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():
|
||||
bpy.utils.register_class(SvIfcReadEntity)
|
||||
|
||||
@@ -29,7 +29,9 @@ from sverchok.node_tree import SverchCustomTreeNode
|
||||
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
|
||||
Tooltip: Sverchok geometry to Ifc Shape Representation
|
||||
@@ -59,7 +61,11 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
||||
]
|
||||
|
||||
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(
|
||||
name="Context Identifier",
|
||||
@@ -78,7 +84,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
||||
|
||||
def sv_init(self, context):
|
||||
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("SvVerticesSocket", "Vertices")
|
||||
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]
|
||||
|
||||
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)]:
|
||||
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
|
||||
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.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
|
||||
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]))],
|
||||
)
|
||||
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.append(representations_ids_obj)
|
||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(
|
||||
representations_ids_obj
|
||||
)
|
||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
||||
"Representations", []
|
||||
).append(representations_ids_obj)
|
||||
return representations_ids
|
||||
|
||||
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 step_id in obj:
|
||||
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"]
|
||||
return
|
||||
@@ -171,9 +187,13 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
||||
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)
|
||||
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)
|
||||
parent = ifcopenshell.api.run(
|
||||
"context.add_context", self.file, context_type=self.context_type
|
||||
)
|
||||
context = ifcopenshell.api.run(
|
||||
"context.add_context",
|
||||
self.file,
|
||||
@@ -182,7 +202,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
||||
target_view=self.target_view,
|
||||
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
|
||||
|
||||
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]:
|
||||
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
|
||||
"geometry.remove_representation",
|
||||
self.file,
|
||||
representation=self.file.by_id(step_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 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 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)
|
||||
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
||||
del SvIfcStore.id_map[self.node_id]
|
||||
|
||||
Reference in New Issue
Block a user