Important rework of handling multiple/nested items in bmesh_to_ifc, create_entity and sverchok_to_ifc nodes. Formatting and other minor fixes.

This commit is contained in:
martinaCodes
2022-11-09 01:49:01 +01:00
committed by Dion Moult
parent 4ae7643874
commit 8a26f30506
30 changed files with 542 additions and 390 deletions
+39 -35
View File
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -28,21 +28,18 @@ bl_info = {
"warning": "", "warning": "",
} }
import sys
import importlib import importlib
import nodeitems_utils import nodeitems_utils
import sverchok from sverchok.core import make_node_list
from sverchok.core import sv_registration_utils, make_node_list
from sverchok.utils import auto_gather_node_classes, get_node_class_reference from sverchok.utils import auto_gather_node_classes, get_node_class_reference
from sverchok.menu import SverchNodeItem, SverchNodeCategory, register_node_panels from sverchok.menu import SverchNodeItem, SverchNodeCategory
from sverchok.utils.extra_categories import ( from sverchok.utils.extra_categories import (
register_extra_category_provider, register_extra_category_provider,
unregister_extra_category_provider, unregister_extra_category_provider,
) )
from sverchok.ui.nodeview_space_menu import make_extra_category_menus from sverchok.ui.nodeview_space_menu import make_extra_category_menus
from sverchok.utils.logging import info, debug from sverchok.utils.logging import info, debug
import asyncio
import time
def nodes_index(): def nodes_index():
return [ return [
@@ -73,8 +70,7 @@ def nodes_index():
("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcRepr"), ("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcRepr"),
("ifc.sverchok_to_ifc", "SvIfcSverchokToIfcRepr"), ("ifc.sverchok_to_ifc", "SvIfcSverchokToIfcRepr"),
("ifc.create_project", "SvIfcCreateProject"), ("ifc.create_project", "SvIfcCreateProject"),
("ifc.quick_project_setup", "SvIfcQuickProjectSetup") ("ifc.quick_project_setup", "SvIfcQuickProjectSetup"),
], ],
) )
] ]
@@ -96,26 +92,23 @@ imported_modules = make_node_list()
reload_event = False reload_event = False
import bpy import bpy
import os from os.path import splitext
from os.path import abspath, splitext
import ifcopenshell import ifcopenshell
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
from sverchok.data_structure import flatten_data
class IFC_Sv_UpdateCurrent(bpy.types.Operator): class IFC_Sv_UpdateCurrent(bpy.types.Operator):
"""Update current Sverchok node tree""" """Update current Sverchok node tree"""
bl_idname = "ifc.sverchok_update_current" bl_idname = "ifc.sverchok_update_current"
bl_label = "Update current node tree" bl_label = "Update current node tree"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} bl_options = {"REGISTER", "UNDO", "INTERNAL"}
node_group: bpy.props.StringProperty(default="") node_group: bpy.props.StringProperty(default="")
force_mode: bpy.props.BoolProperty(default=False) force_mode: bpy.props.BoolProperty(default=False)
def execute(self, context): def execute(self, context):
print("#"*10, "Update current node tree")
self.file = SvIfcStore.purge() self.file = SvIfcStore.purge()
self.file = SvIfcStore.get_file()
self.file.write("/Users/martina/Documents/GSoC/CodeTests/IfcFileTest_7_11_purged.ifc")
node_tree = context.space_data.node_tree node_tree = context.space_data.node_tree
if node_tree: if node_tree:
if self.force_mode or node_tree.sv_process: if self.force_mode or node_tree.sv_process:
@@ -125,7 +118,8 @@ class IFC_Sv_UpdateCurrent(bpy.types.Operator):
finally: finally:
bpy.context.window.cursor_set("DEFAULT") bpy.context.window.cursor_set("DEFAULT")
self.report({"INFO"}, "Node tree updated.") self.report({"INFO"}, "Node tree updated.")
return {'FINISHED'} return {"FINISHED"}
class IFC_Sv_write_file(bpy.types.Operator): class IFC_Sv_write_file(bpy.types.Operator):
bl_idname = "ifc.write_file_panel" bl_idname = "ifc.write_file_panel"
@@ -141,43 +135,52 @@ class IFC_Sv_write_file(bpy.types.Operator):
return any("IFC" in n for n in context.space_data.edit_tree.nodes.keys()) return any("IFC" in n for n in context.space_data.edit_tree.nodes.keys())
def ensure_hirarchy(self, file): def ensure_hirarchy(self, file):
elements_in_buildings = [] elements_in_buildings = set()
if not 0 <= 0 < len(file.by_type("IfcBuilding")): if len(file.by_type("IfcBuilding")) == 0:
my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building") my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building")
elements = ifcopenshell.util.element.get_decomposition(my_building) elements = ifcopenshell.util.element.get_decomposition(my_building)
else: else:
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
elements = ifcopenshell.util.element.get_decomposition(building) elements = ifcopenshell.util.element.get_decomposition(building)
elements_in_buildings.extend(elements) elements_in_buildings.update(elements)
for spatial in (file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement")): for spatial in file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement"):
if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)): if not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings):
elements = ifcopenshell.util.element.get_decomposition(spatial) elements = ifcopenshell.util.element.get_decomposition(spatial)
ifcopenshell.api.run("aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]) ifcopenshell.api.run(
"aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]
)
elements_in_buildings_after = []
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
elements = ifcopenshell.util.element.get_decomposition(building) elements = ifcopenshell.util.element.get_decomposition(building)
elements_in_buildings_after.extend(elements) elements_in_buildings.update(elements)
elements = file.by_type("IfcElement") elements = file.by_type("IfcElement")
for element in elements: for element in elements:
if element not in elements_in_buildings: if element not in elements_in_buildings:
ifcopenshell.api.run("spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]) ifcopenshell.api.run(
"spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]
)
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
elements = ifcopenshell.util.element.get_decomposition(building) elements = ifcopenshell.util.element.get_decomposition(building)
if not building.Decomposes: if not building.Decomposes:
if not 0 <= 0 < len(file.by_type("IfcSite")): if len(file.by_type("IfcSite")) == 0:
ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site")
ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]) ifcopenshell.api.run(
"aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]
)
try: try:
if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"): if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"):
continue continue
except IndexError: except IndexError:
pass pass
ifcopenshell.api.run("aggregate.assign_object", file, product=file.by_type("IfcSite")[0], relating_object=file.by_type("IfcProject")[0]) ifcopenshell.api.run(
"aggregate.assign_object",
file,
product=file.by_type("IfcSite")[0],
relating_object=file.by_type("IfcProject")[0],
)
self.file = file self.file = file
return return
@@ -198,6 +201,7 @@ class IFC_Sv_write_file(bpy.types.Operator):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"} return {"RUNNING_MODAL"}
class IFC_PT_write_file_panel(bpy.types.Panel): class IFC_PT_write_file_panel(bpy.types.Panel):
bl_idname = "IFC_PT_write_file_panel" bl_idname = "IFC_PT_write_file_panel"
bl_label = "Write IFC to file" bl_label = "Write IFC to file"
@@ -217,10 +221,12 @@ class IFC_PT_write_file_panel(bpy.types.Panel):
row = layout.split(factor=0.2, align=True) row = layout.split(factor=0.2, align=True)
row = layout.row() row = layout.row()
row2 = layout.row() row2 = layout.row()
row.operator('ifc.sverchok_update_current', text='IFC Re-run all nodes') row.operator("ifc.sverchok_update_current", text="IFC Re-run all nodes")
row2.operator("ifc.write_file_panel") row2.operator("ifc.write_file_panel")
CLASSES = [IFC_Sv_UpdateCurrent,IFC_Sv_write_file, IFC_PT_write_file_panel]
CLASSES = [IFC_Sv_UpdateCurrent, IFC_Sv_write_file, IFC_PT_write_file_panel]
def register_nodes(): def register_nodes():
node_modules = make_node_list() node_modules = make_node_list()
@@ -281,9 +287,7 @@ def register():
auto_gather_node_classes(extra_nodes) auto_gather_node_classes(extra_nodes)
menu = make_menu() menu = make_menu()
menu_category_provider = SvExCategoryProvider("IFCSVERCHOK", menu) menu_category_provider = SvExCategoryProvider("IFCSVERCHOK", menu)
register_extra_category_provider( register_extra_category_provider(menu_category_provider) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories:
menu_category_provider
) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories:
nodeitems_utils.register_node_categories("IFCSVERCHOK", menu) nodeitems_utils.register_node_categories("IFCSVERCHOK", menu)
our_menu_classes = make_extra_category_menus() our_menu_classes = make_extra_category_menus()
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+22 -25
View File
@@ -1,13 +1,25 @@
# import os # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
# import uuid
# import hashlib
# import zipfile
# import tempfile
import ifcopenshell import ifcopenshell
from ifcopenshell import template from ifcopenshell import template
# import blenderbim.bim.handler
# from pathlib import Path
class SvIfcStore: class SvIfcStore:
path = "" path = ""
@@ -52,7 +64,6 @@ class SvIfcStore:
SvIfcStore.future = [] SvIfcStore.future = []
SvIfcStore.schema_identifiers = ["IFC4", "IFC2X3"] SvIfcStore.schema_identifiers = ["IFC4", "IFC2X3"]
@staticmethod @staticmethod
def create_boilerplate(): def create_boilerplate():
@@ -61,11 +72,10 @@ class SvIfcStore:
organization=None, organization=None,
creator=None, creator=None,
project_name="IfcSverchokDemoProject", project_name="IfcSverchokDemoProject",
) )
if bpy.context.scene.unit_settings.system == 'IMPERIAL': if bpy.context.scene.unit_settings.system == "IMPERIAL":
#TODO change units to imperial # TODO change units to imperial
pass pass
# model = ifcopenshell.api.run("context.add_context", file, context_type="Model")
model = ifcopenshell.util.representation.get_context(file, context="Model") model = ifcopenshell.util.representation.get_context(file, context="Model")
print("model: ", model) print("model: ", model)
context = ifcopenshell.api.run( context = ifcopenshell.api.run(
@@ -76,22 +86,9 @@ class SvIfcStore:
target_view="MODEL_VIEW", target_view="MODEL_VIEW",
parent=model, parent=model,
) )
# site = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site")
# building = ifcopenshell.api.run(
# "root.create_entity", file, ifc_class="IfcBuilding", name="My Building"
# )
# building_storey = ifcopenshell.api.run(
# "root.create_entity", file, ifc_class="IfcBuildingStorey", name="My Storey"
# )
# ifcopenshell.api.run("aggregate.assign_object", file, product=site, relating_object=file.by_type("IfcProject")[0])
# ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=site)
# ifcopenshell.api.run("aggregate.assign_object", file, product=building_storey, relating_object=building)
SvIfcStore.file = file SvIfcStore.file = file
return SvIfcStore.file return SvIfcStore.file
@staticmethod @staticmethod
def get_file(): def get_file():
+1 -3
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -16,4 +15,3 @@
# #
# 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/>.
+1 -3
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -16,4 +15,3 @@
# #
# 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/>.
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+18
View File
@@ -1,3 +1,21 @@
# IfcSverchok - IFC Sverchok extension
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -1,3 +1,21 @@
# IfcSverchok - IFC Sverchok extension
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -13,7 +31,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
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(name="Name(s)", update=updateNode)
IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace") IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace")
Elements: StringProperty(name="Elements", update=updateNode) Elements: StringProperty(name="Elements", update=updateNode)
@@ -24,14 +42,14 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements" self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements"
self.outputs.new("SvStringsSocket", "Entities") self.outputs.new("SvStringsSocket", "Entities")
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 = "Ifc entity by type."
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))
@@ -40,8 +58,11 @@ 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 isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name]
):
edit = True edit = True
if self.inputs[i].name == "Elements": if self.inputs[i].name == "Elements":
edit_elements = True edit_elements = True
@@ -83,7 +104,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"): if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result) ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result)
else: else:
ifcopenshell.api.run("spatial.assign_container", self.file, product=items, relating_structure=result) ifcopenshell.api.run(
"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())
return spatial_ids return spatial_ids
@@ -106,15 +129,25 @@ 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("IfcSpatialStructureElement"): if removed_element.is_a("IfcSpatialElement") or removed_element.is_a(
ifcopenshell.api.run("aggregate.unassign_object", self.file, product=removed_element, relating_object=result) "IfcSpatialStructureElement"
):
ifcopenshell.api.run(
"aggregate.unassign_object", self.file, product=removed_element, relating_object=result
)
else: else:
ifcopenshell.api.run("spatial.unassign_container", self.file, product=removed_element, relating_object=result) ifcopenshell.api.run(
"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("aggregate.assign_object", self.file, product=added_element, relating_object=result) ifcopenshell.api.run(
"aggregate.assign_object", self.file, product=added_element, relating_object=result
)
else: else:
ifcopenshell.api.run("spatial.assign_container", self.file, product=added_element, relating_structure=result) ifcopenshell.api.run(
"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
return spatial_ids return spatial_ids
@@ -129,17 +162,20 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
def repeat_input_unique(self, input, count): def repeat_input_unique(self, input, count):
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 = [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 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 return input
def sv_free(self): def sv_free(self):
try: try:
del SvIfcStore.id_map[self.node_id] del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)] del self.node_dict[hash(self)]
print('Node was deleted') # print('Node was deleted')
except KeyError or AttributeError: except KeyError or AttributeError:
pass pass
def register(): def register():
bpy.utils.register_class(SvIfcAddSpatialElement) bpy.utils.register_class(SvIfcAddSpatialElement)
+2 -3
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -105,4 +104,4 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_class(SvIfcApi) bpy.utils.unregister_class(SvIfcApi)
bpy.utils.unregister_class(SvIfcTooltip) bpy.utils.unregister_class(SvIfcTooltip)
+15 -27
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -21,13 +20,12 @@ import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcsverchok.helper import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty 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
import importlib import importlib
class SvIfcTooltip(bpy.types.Operator): class SvIfcTooltip(bpy.types.Operator):
bl_idname = "node.sv_ifc_tooltip" bl_idname = "node.sv_ifc_tooltip"
bl_label = "IFC Info" bl_label = "IFC Info"
@@ -43,12 +41,6 @@ class SvIfcTooltip(bpy.types.Operator):
class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
# def update_usecase(self, context):
# # update_usecase is not getting run rn
# module_usecase = self.get_module_usecase()
# if module_usecase:
# self.generate_node(*module_usecase)
bl_idname = "SvIfcApiWIP" bl_idname = "SvIfcApiWIP"
bl_label = "IFC API WIP" bl_label = "IFC API WIP"
tooltip: StringProperty(name="Tooltip") tooltip: StringProperty(name="Tooltip")
@@ -57,11 +49,13 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "usecase").prop_name = "usecase" self.inputs.new("SvStringsSocket", "usecase").prop_name = "usecase"
#input_socket.tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file'" # input_socket.tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file'"
self.outputs.new("SvVerticesSocket", "file") self.outputs.new("SvVerticesSocket", "file")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file" op = layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file"
# op.tooltip = self.tooltip # op.tooltip = self.tooltip
def process(self): def process(self):
@@ -71,11 +65,9 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
try: try:
module_usecase = self.get_module_usecase() module_usecase = self.get_module_usecase()
except: except:
raise Exception( raise Exception(f"Couldn't run generate_node(). Module usecase: {module_usecase}")
f"Couldn't run generate_node(). Module usecase: {module_usecase}" if ".".join(module_usecase) != self.current_usecase:
) self.generate_node(*module_usecase)
if '.'.join(module_usecase) != self.current_usecase:
self.generate_node(*module_usecase)
try: try:
for i in range(0, len(self.inputs)): for i in range(0, len(self.inputs)):
input = self.inputs[i].sv_get() input = self.inputs[i].sv_get()
@@ -85,8 +77,7 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
self.sv_input_names = [i.name for i in self.inputs] self.sv_input_names = [i.name for i in self.inputs]
super().process() # super().process() uses zip_long_repeat() which doesn't take objects like bmesh super().process() # super().process() uses zip_long_repeat() which doesn't take objects like bmesh
def get_module_usecase(self): def get_module_usecase(self):
usecase = self.inputs["usecase"].sv_get()[0][0] usecase = self.inputs["usecase"].sv_get()[0][0]
@@ -102,10 +93,10 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
node_inputs["file"] = None node_inputs["file"] = None
node_inputs.update(getattr(local_module.Usecase(local_module), "settings", {})) node_inputs.update(getattr(local_module.Usecase(local_module), "settings", {}))
# print("node inputs: ", node_inputs) # print("node inputs: ", node_inputs)
while len(self.inputs) > 1: while len(self.inputs) > 1:
self.inputs.remove(self.inputs[-1]) self.inputs.remove(self.inputs[-1])
if node_inputs: if node_inputs:
self.tooltip = "" self.tooltip = ""
for name, data in node_inputs.items(): for name, data in node_inputs.items():
@@ -116,11 +107,10 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
else: else:
self.tooltip = f"{name}: None\n" self.tooltip = f"{name}: None\n"
self.tooltip = self.tooltip.strip() self.tooltip = self.tooltip.strip()
self.current_usecase = '.'.join([module, usecase]) self.current_usecase = ".".join([module, usecase])
def process_ifc(self, usecase, *setting_values): def process_ifc(self, usecase, *setting_values):
if usecase and setting_values: if usecase and setting_values:
settings = dict(zip(self.sv_input_names[1:], setting_values)) settings = dict(zip(self.sv_input_names[1:], setting_values))
settings = {k: v for k, v in settings.items() if v != ""} settings = {k: v for k, v in settings.items() if v != ""}
@@ -133,8 +123,6 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
self.outputs["file"].sv_set([ifcopenshell.api.run(usecase, **settings)]) self.outputs["file"].sv_set([ifcopenshell.api.run(usecase, **settings)])
except: except:
raise Exception(f"Couldn't run usecase.") raise Exception(f"Couldn't run usecase.")
def register(): def register():
@@ -144,4 +132,4 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_class(SvIfcApiWIP) bpy.utils.unregister_class(SvIfcApiWIP)
bpy.utils.unregister_class(SvIfcTooltip) bpy.utils.unregister_class(SvIfcTooltip)
+100 -55
View File
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -28,18 +28,20 @@ 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
from sverchok.data_structure import zip_long_repeat, node_id from sverchok.data_structure import zip_long_repeat, node_id
from sverchok.core.socket_data import sv_get_socket 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
""" """
bl_idname = "SvIfcBMeshToIfcRepr" bl_idname = "SvIfcBMeshToIfcRepr"
bl_label = "IFC Blender Mesh to IFC Repr" bl_label = "IFC Blender Mesh to IFC Repr"
node_dict = {} node_dict = {}
@@ -54,61 +56,81 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
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),
('Plan', 'Plan', 'Context type: Plan', 1), ("Plan", "Plan", "Context type: Plan", 1),
] ]
context_identifiers = [ context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0), ("Body", "Body", "Context identifier: Body", 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1), ("Annotation", "Annotation", "Context identifier: Annotation", 1),
('Box', 'Box', 'Context identifier: Box', 2), ("Box", "Box", "Context identifier: Box", 2),
('Axis', 'Axis', 'Context identifier: Axis', 3), ("Axis", "Axis", "Context identifier: Axis", 3),
] ]
target_views = [ target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0), ("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1), ("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2), ("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3), ("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) blender_objects: PointerProperty(
context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode) name="Blender Mesh(es)", description="Blender Mesh Object(s)", update=updateNode, type=bpy.types.Object
context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode) )
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode) context_type: EnumProperty(
name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode
)
context_identifier: EnumProperty(
name="Context Identifier",
description="Default: Body",
default="Body",
items=context_identifiers,
update=updateNode,
)
target_view: EnumProperty(
name="Target View",
description="Default: MODEL VIEW",
default="MODEL_VIEW",
items=target_views,
update=updateNode,
)
tooltip: StringProperty(name="Tooltip") tooltip: StringProperty(name="Tooltip")
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("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries." layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries."
row = layout.row(align=True) row = layout.row(align=True)
row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True) row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH') row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self): def process(self):
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["blender_objects"].sv_get()[0]: if not self.inputs["blender_objects"].sv_get()[0]:
return return
edit = False edit = False
for i in range(len(self.inputs)): for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=True) input = self.inputs[i].sv_get(deepcopy=True)
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name]
):
edit = True edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input.copy() self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
blender_objects = self.inputs["blender_objects"].sv_get() blender_objects = self.inputs["blender_objects"].sv_get()
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
@@ -124,8 +146,7 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
representations = SvIfcStore.id_map[self.node_id]["Representations"] representations = SvIfcStore.id_map[self.node_id]["Representations"]
locations = SvIfcStore.id_map[self.node_id]["Locations"] locations = SvIfcStore.id_map[self.node_id]["Locations"]
print("representations: ", representations) # print("representations: ", representations)
print("locations: ", locations)
self.outputs["Representations"].sv_set(representations) self.outputs["Representations"].sv_set(representations)
self.outputs["Locations"].sv_set(locations) self.outputs["Locations"].sv_set(locations)
@@ -134,41 +155,63 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
representations_ids = [] representations_ids = []
locations = [] locations = []
for blender_object in blender_objects: for blender_object in blender_objects:
if blender_object.type == 'MESH': if blender_object.type == "MESH":
bpy.ops.object.mode_set(mode='OBJECT') try:
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.mode_set(mode="OBJECT")
except:
pass
bpy.ops.object.select_all(action="DESELECT")
blender_object.select_set(True) blender_object.select_set(True)
bpy.ops.object.mode_set(mode='EDIT') try:
bpy.ops.mesh.separate(type='LOOSE') bpy.ops.object.mode_set(mode="EDIT")
except:
pass
bpy.ops.mesh.separate(type="LOOSE")
representations_ids_obj = []
locations_obj = []
for obj in bpy.context.selected_objects: for obj in bpy.context.selected_objects:
representation = ifcopenshell.api.run("geometry.add_representation", self.file, should_run_listeners=False,blender_object = obj, geometry=obj.data, context = self.get_context()) representation = ifcopenshell.api.run(
"geometry.add_representation",
self.file,
should_run_listeners=False,
blender_object=obj,
geometry=obj.data,
context=self.get_context(),
)
if not representation: if not representation:
raise Exception("Couldn't create representation. Possibly wrong context.") raise Exception("Couldn't create representation. Possibly wrong context.")
representations_ids.append(representation.id())
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id()) representations_ids_obj.append(representation.id())
locations.append(blender_object.matrix_world) locations_obj.append(obj.matrix_world)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(blender_object.matrix_world) representations_ids.append(representations_ids_obj)
bpy.ops.object.mode_set(mode='OBJECT') locations.append(locations_obj)
bpy.ops.object.select_all(action='DESELECT') 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:
pass
bpy.ops.object.select_all(action="DESELECT")
return representations_ids, locations return representations_ids, locations
def edit(self): def edit(self):
if "Representations" not in SvIfcStore.id_map[self.node_id]: if "Representations" not in SvIfcStore.id_map[self.node_id]:
return return
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id)) for step_id in obj:
ifcopenshell.api.run(
"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"]
return return
def get_existing_element(self):
results = []
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
results.append(self.file.by_id(step_id))
return results
def get_context(self): def get_context(self):
context = ifcopenshell.util.representation.get_context(self.file, self.context_type, self.context_identifier, self.target_view) context = ifcopenshell.util.representation.get_context(
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:
@@ -184,13 +227,15 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
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):
try: try:
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]: if "Representations" in SvIfcStore.id_map[self.node_id]:
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id)) for step_id in obj:
ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
if "Contexts" in SvIfcStore.id_map[self.node_id]: if "Contexts" in SvIfcStore.id_map[self.node_id]:
for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]: for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]:
@@ -202,11 +247,11 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
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]
del self.node_dict[hash(self)] del self.node_dict[hash(self)]
print('Node was deleted') # print('Node was deleted')
except KeyError or AttributeError: except KeyError or AttributeError:
pass pass
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+10 -6
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -17,8 +16,8 @@
# 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 bpy import bpy
import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
from bpy.props import StringProperty from bpy.props import StringProperty
@@ -29,24 +28,29 @@ from sverchok.data_structure import updateNode, flatten_data
class SvIfcById(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcById(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcById" bl_idname = "SvIfcById"
bl_label = "IFC By Id" bl_label = "IFC By Id"
id: StringProperty(name="Id(s)", update=updateNode, ) id: StringProperty(
name="Id(s)",
update=updateNode,
)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "id").prop_name = "id" self.inputs.new("SvStringsSocket", "id").prop_name = "id"
self.outputs.new("SvStringsSocket", "Entities") self.outputs.new("SvStringsSocket", "Entities")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Get IFC element by step id. Takes one or multiple step ids." layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Get IFC element by step id. Takes one or multiple step ids."
def process(self): def process(self):
self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1) self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1)
print(self.ids)
if not self.ids[0]: if not self.ids[0]:
return return
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
self.entities = [self.file.by_id(int(step_id)) for step_id in self.ids] self.entities = [self.file.by_id(int(step_id)) for step_id in self.ids]
self.outputs["Entities"].sv_set(self.entities) self.outputs["Entities"].sv_set(self.entities)
def register(): def register():
bpy.utils.register_class(SvIfcById) bpy.utils.register_class(SvIfcById)
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+23 -10
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -23,8 +22,8 @@ import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty from bpy.props import StringProperty, EnumProperty
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data from sverchok.data_structure import updateNode
from sverchok.utils.handle_blender_data import keep_enum_reference
def get_ifc_products(self, context): def get_ifc_products(self, context):
ifc_products = getattr(self, "ifc_products", []) ifc_products = getattr(self, "ifc_products", [])
@@ -57,6 +56,7 @@ def update_ifc_products(self, context):
if hasattr(self, "ifc_classes"): if hasattr(self, "ifc_classes"):
self.ifc_classes.clear() self.ifc_classes.clear()
def get_ifc_classes(self, context): def get_ifc_classes(self, context):
ifc_classes = getattr(self, "ifc_classes", []) ifc_classes = getattr(self, "ifc_classes", [])
if ifc_classes: if ifc_classes:
@@ -83,9 +83,18 @@ def get_ifc_classes(self, context):
class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcByType" bl_idname = "SvIfcByType"
bl_label = "IFC By Type" bl_label = "IFC By Type"
ifc_product: EnumProperty(items=get_ifc_products, name="IfcProduct", description="Pick an IfcProduct from drop-down.", update=update_ifc_products) ifc_product: EnumProperty(
ifc_class: EnumProperty(items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode) items=get_ifc_products,
custom_ifc_class: StringProperty(name="Custom IfcClass", description="Give the name of your custom IfcClass.", update=updateNode) name="IfcProduct",
description="Pick an IfcProduct from drop-down.",
update=update_ifc_products,
)
ifc_class: EnumProperty(
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
)
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"
@@ -93,9 +102,13 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class" self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class"
self.outputs.new("SvStringsSocket", "Entity") self.outputs.new("SvStringsSocket", "Entity")
self.width = 200 self.width = 200
def draw_buttons(self, context, layout): 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." 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."
)
def process(self): def process(self):
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
@@ -119,4 +132,4 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_class(SvIfcByType) bpy.utils.unregister_class(SvIfcByType)
+78 -44
View File
@@ -1,20 +1,30 @@
# IfcSverchok - IFC Sverchok extension
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
# IfcSverchok is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcSverchok is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
from mathutils import Matrix, Vector from mathutils import Matrix
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
# import ifcsverchok.ifc_store from bpy.props import StringProperty, BoolProperty
# from bpy.props import StringProperty
# from sverchok.node_tree import SverchCustomTreeNode
# from sverchok.data_structure import updateNode
import bpy
import ifcopenshell
from bpy.props import StringProperty, EnumProperty, IntProperty, 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 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):
@@ -43,32 +53,33 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
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")
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 = "Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used." layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used."
row = layout.row(align=True) row = layout.row(align=True)
row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True) row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH') row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self): def process(self):
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.inputs["Descriptions"].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.representations = flatten_data(self.inputs["Representations"].sv_get(), target_level=1) self.representations = ensure_min_nesting(self.inputs["Representations"].sv_get(), 2)
self.locations = flatten_data(self.inputs["Locations"].sv_get(default=[]), target_level=1) self.representations = flatten_data(self.representations, target_level=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]:
@@ -76,18 +87,24 @@ 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 isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name]
):
edit = True edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input.copy() self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
if self.refresh_local: if self.refresh_local:
edit = True edit = True
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
if self.representations[0]: if self.representations[0][0]:
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.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))
@@ -102,9 +119,8 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
entities = self.edit() entities = self.edit()
else: else:
entities = SvIfcStore.id_map[self.node_id] entities = SvIfcStore.id_map[self.node_id]
print("Entities: ", entities)
# print("Entities: ", entities)
self.outputs["Entities"].sv_set(entities) self.outputs["Entities"].sv_set(entities)
def create(self, index=None): def create(self, index=None):
@@ -114,20 +130,32 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
iterator = [index] iterator = [index]
for i in iterator: for i in iterator:
try: try:
entity = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=self.ifc_class, name=self.names[i], description=self.descriptions[i]) entity = ifcopenshell.api.run(
"root.create_entity",
self.file,
ifc_class=self.ifc_class,
name=self.names[i],
description=self.descriptions[i],
)
try: try:
if self.representations[i]: for repr in self.representations[i]:
ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i]) if self.representations[i]:
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr
)
except IndexError: except IndexError:
pass pass
try: try:
if isinstance(self.locations[i], Matrix): for loc in self.locations[i]:
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i]) if isinstance(self.locations[i], Matrix):
ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=entity, matrix=loc
)
except IndexError: except IndexError:
pass pass
entities_ids.append(entity.id()) entities_ids.append(entity.id())
SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id()) SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id())
except Exception as e: except Exception as e:
raise Exception("Something went wrong. Cannot create entity.", e) raise Exception("Something went wrong. Cannot create entity.", e)
return entities_ids return entities_ids
@@ -146,15 +174,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
entity.Description = self.descriptions[i] entity.Description = self.descriptions[i]
try: try:
if self.representations[i] and self.representations[i].is_a('IfcProductDefinitionShape'): for repr in self.representations[i]:
entity.Representation = self.representations[i] if repr and repr.is_a("IfcProductDefinitionShape"):
elif self.representations[i]: entity.Representation = repr
ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i]) elif repr:
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr
)
except IndexError: except IndexError:
pass pass
try: try:
if isinstance(self.locations[i], Matrix): for loc in self.locations[i]:
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i]) if isinstance(loc, Matrix):
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:
@@ -163,21 +195,23 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
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())
if id_map_copy>entities_ids: if id_map_copy > entities_ids:
SvIfcStore.id_map[self.node_id] = entities_ids SvIfcStore.id_map[self.node_id] = entities_ids
return entities_ids return entities_ids
def repeat_input_unique(self, input, count): def repeat_input_unique(self, input, count):
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 = [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 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 return input
def sv_free(self): def sv_free(self):
try: try:
del SvIfcStore.id_map[self.node_id] del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)] del self.node_dict[hash(self)]
print('Node was deleted') # print('Node was deleted')
except KeyError or AttributeError: except KeyError or AttributeError:
pass pass
+1 -1
View File
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+11 -12
View File
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -19,10 +19,8 @@
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
# from ifcopenshell import template
class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcCreateProject" bl_idname = "SvIfcCreateProject"
@@ -36,25 +34,26 @@ class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe
self.outputs.new("SvVerticesSocket", "file") self.outputs.new("SvVerticesSocket", "file")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Adds project, unit and context to IFC file" op = layout.operator(
#op.tooltip = self.tooltip "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Adds project, unit and context to IFC file"
# op.tooltip = self.tooltip
def process(self): def process(self):
#file # file
file = self.inputs["file"].sv_get()[0][0] file = self.inputs["file"].sv_get()[0][0]
if file: if file:
schema_name = file.wrapped_data.schema schema_name = file.wrapped_data.schema
else: else:
schema_name = "IFC4" schema_name = "IFC4"
#project name # project name
project_name = self.inputs["project_name"].sv_get()[0][0] project_name = self.inputs["project_name"].sv_get()[0][0]
self.process_ifc(file, project_name) self.process_ifc(file, project_name)
def process_ifc(self, file, project_name): def process_ifc(self, file, project_name):
# create project # create project
project = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcProject", name=str(project_name)) project = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcProject", name=str(project_name))
lengthunit = ifcopenshell.api.run("unit.add_si_unit", file, unit_type="LENGTHUNIT", name="METRE") lengthunit = ifcopenshell.api.run("unit.add_si_unit", file, unit_type="LENGTHUNIT", name="METRE")
ifcopenshell.api.run("unit.assign_unit", file, units=[lengthunit]) ifcopenshell.api.run("unit.assign_unit", file, units=[lengthunit])
+12 -24
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -28,29 +27,16 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data from sverchok.data_structure import updateNode, flatten_data
# class SvIfcCreateShapeRefresh(bpy.types.Operator):
# bl_idname = "node.sv_ifc_create_shape_refresh"
# bl_label = "IFC Create Shape Refresh"
# bl_options = {"UNDO"}
# tree_name: StringProperty(default="")
# node_name: StringProperty(default="")
# def execute(self, context):
# node = bpy.data.node_groups[self.tree_name].nodes[self.node_name]
# node.process()
# return {"FINISHED"}
class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
""" """
Triggers: Ifc create shape by entity Triggers: Ifc create shape by entity
Tooltip: Create Blender shape by Ifc Entity Tooltip: Create Blender shape by Ifc Entity
""" """
is_scene_dependent = True is_scene_dependent = True
is_interactive = False is_interactive = False
node_dict = {} node_dict = {}
def refresh_node(self, context): def refresh_node(self, context):
if self.refresh_local: if self.refresh_local:
self.process() self.process()
@@ -61,22 +47,23 @@ 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="Entities", 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"
self.outputs.new('SvStringsSocket', "Object(s)") self.outputs.new("SvStringsSocket", "Object(s)")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
row = layout.row(align=True) 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." row.operator(
row.prop(self, 'refresh_local', icon='FILE_REFRESH') "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Create Blender shape from IfcEntity ID. Takes one or multiple IfcEntity IDs."
row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self): def process(self):
self.entities = flatten_data(self.inputs["Entities"].sv_get(), target_level = 1) self.entities = flatten_data(self.inputs["Entities"].sv_get(), target_level=1)
if not self.entities[0]: if not self.entities[0]:
return return
if self.refresh_local or hash(self) not in self.node_dict: if self.refresh_local or hash(self) not in self.node_dict:
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
try: try:
@@ -87,7 +74,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
self.node_dict[hash(self)] = blender_objects self.node_dict[hash(self)] = blender_objects
else: else:
blender_objects = self.node_dict[hash(self)] blender_objects = self.node_dict[hash(self)]
self.outputs["Object(s)"].sv_set(blender_objects) self.outputs["Object(s)"].sv_set(blender_objects)
def create(self): def create(self):
@@ -110,6 +97,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
raise Exception("Entity could not be converted into a shape. Entity: {}".format(entity)) raise Exception("Entity could not be converted into a shape. Entity: {}".format(entity))
return blender_objects return blender_objects
def register(): def register():
# bpy.utils.register_class(SvIfcCreateShapeRefresh) # bpy.utils.register_class(SvIfcCreateShapeRefresh)
bpy.utils.register_class(SvIfcCreateShape) bpy.utils.register_class(SvIfcCreateShape)
+1 -4
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -20,9 +19,7 @@
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
class SvIfcGenerateGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcGenerateGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+13 -6
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -20,11 +19,12 @@
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcsverchok.helper import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty from bpy.props import EnumProperty
from ifcsverchok.ifcstore import SvIfcStore from ifcsverchok.ifcstore import SvIfcStore
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode
def get_ifc_products(self, context): def get_ifc_products(self, context):
ifc_products = getattr(self, "ifc_products", []) ifc_products = getattr(self, "ifc_products", [])
file = SvIfcStore.get_file() file = SvIfcStore.get_file()
@@ -83,15 +83,22 @@ def get_ifc_classes(self, context):
class SvIfcPickIfcClass(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcPickIfcClass(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcPickIfcClass" bl_idname = "SvIfcPickIfcClass"
bl_label = "IFC Class Picker" bl_label = "IFC Class Picker"
ifc_product: EnumProperty(items=get_ifc_products, name="IfcProduct", description="Pick an IfcProduct from drop-down.", update=update_ifc_products) ifc_product: EnumProperty(
ifc_class: EnumProperty(items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode) items=get_ifc_products,
name="IfcProduct",
description="Pick an IfcProduct from drop-down.",
update=update_ifc_products,
)
ifc_class: EnumProperty(
items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", 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.outputs.new("SvStringsSocket", "IfcClass") self.outputs.new("SvStringsSocket", "IfcClass")
self.width = 200 self.width = 200
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 Class Picker" layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Ifc Class Picker"
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>. # along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from email.mime import application from email.mime import application
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -25,6 +26,7 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode
from ifcopenshell import template from ifcopenshell import template
class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcQuickProjectSetup" bl_idname = "SvIfcQuickProjectSetup"
bl_label = "IFC Quick Project Setup" bl_label = "IFC Quick Project Setup"
@@ -33,7 +35,6 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
application: StringProperty(name="application", update=updateNode) application: StringProperty(name="application", update=updateNode)
application_version: StringProperty(name="application_version", update=updateNode) application_version: StringProperty(name="application_version", update=updateNode)
timestamp: StringProperty(name="timestamp", update=updateNode) timestamp: StringProperty(name="timestamp", update=updateNode)
def sv_init(self, context): def sv_init(self, context):
input_socket = self.inputs.new("SvStringsSocket", "filename") input_socket = self.inputs.new("SvStringsSocket", "filename")
@@ -59,8 +60,10 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.outputs.new("SvVerticesSocket", "file") self.outputs.new("SvVerticesSocket", "file")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Quick Project Setup: creates Ifc file and sets up a basic project" op = layout.operator(
#op.tooltip = self.tooltip "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Quick Project Setup: creates Ifc file and sets up a basic project"
# op.tooltip = self.tooltip
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]
@@ -70,17 +73,17 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
settings = dict(zip(self.sv_input_names, setting_values)) settings = dict(zip(self.sv_input_names, setting_values))
settings = {k: v for k, v in settings.items() if v != ""} settings = {k: v for k, v in settings.items() if v != ""}
file = template.create( file = template.create(
filename=settings['filename'], filename=settings["filename"],
timestring=settings['timestring'], timestring=settings["timestring"],
organization=settings['organization'], organization=settings["organization"],
creator=settings['creator'], creator=settings["creator"],
schema_identifier=settings['schema_identifier'], schema_identifier=settings["schema_identifier"],
application_version=settings['application_version'], application_version=settings["application_version"],
timestamp=settings['timestamp'], timestamp=settings["timestamp"],
application=settings['application'], application=settings["application"],
project_globalid=settings['project_globalid'], project_globalid=settings["project_globalid"],
project_name=settings['project_name'], project_name=settings["project_name"],
) )
self.outputs["file"].sv_set([[file]]) self.outputs["file"].sv_set([[file]])
+2 -3
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -63,7 +62,7 @@ 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, file, entity): def process_ifc(self, entity):
self.outputs["id"].sv_set([[entity.id()]]) self.outputs["id"].sv_set([[entity.id()]])
self.outputs["is_a"].sv_set([[entity.is_a()]]) self.outputs["is_a"].sv_set([[entity.is_a()]])
for i in range(0, self.entity_schema.attribute_count()): for i in range(0, self.entity_schema.attribute_count()):
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+1 -2
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020, 2021, 2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
+90 -66
View File
@@ -1,5 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -15,7 +15,7 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>. # along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from copy import deepcopy from copy import deepcopy
import bpy import bpy
import ifcopenshell import ifcopenshell
@@ -26,124 +26,146 @@ import blenderbim.tool as tool
import blenderbim.core.geometry as core import blenderbim.core.geometry as core
from bpy.props import StringProperty, EnumProperty, IntProperty, FloatVectorProperty from bpy.props import StringProperty, EnumProperty, IntProperty, FloatVectorProperty
from sverchok.node_tree import SverchCustomTreeNode from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode from sverchok.data_structure import updateNode, 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
""" """
bl_idname = "SvIfcSverchokToIfcRepr" bl_idname = "SvIfcSverchokToIfcRepr"
bl_label = "IFC Sverchok to IFC Repr" bl_label = "IFC Sverchok to IFC Repr"
node_dict = {} node_dict = {}
n_id: StringProperty() n_id: StringProperty()
context_types = [ context_types = [
('Model', 'Model', 'Context type: Model', 0), ("Model", "Model", "Context type: Model", 0),
('Plan', 'Plan', 'Context type: Plan', 1), ("Plan", "Plan", "Context type: Plan", 1),
] ]
context_identifiers = [ context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0), ("Body", "Body", "Context identifier: Body", 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1), ("Annotation", "Annotation", "Context identifier: Annotation", 1),
('Box', 'Box', 'Context identifier: Box', 2), ("Box", "Box", "Context identifier: Box", 2),
('Axis', 'Axis', 'Context identifier: Axis', 3), ("Axis", "Axis", "Context identifier: Axis", 3),
] ]
target_views = [ target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0), ("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1), ("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2), ("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3), ("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3),
] ]
context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode) context_type: EnumProperty(
context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode) name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode) )
context_identifier: EnumProperty(
name="Context Identifier",
description="Default: Body",
default="Body",
items=context_identifiers,
update=updateNode,
)
target_view: EnumProperty(
name="Target View",
description="Default: MODEL VIEW",
default="MODEL_VIEW",
items=target_views,
update=updateNode,
)
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")
self.inputs.new("SvStringsSocket", "Faces") self.inputs.new("SvStringsSocket", "Faces")
self.outputs.new("SvVerticesSocket", "Representation(s)") self.outputs.new("SvVerticesSocket", "Representation(s)")
self.width = 210 self.width = 210
self.node_dict[hash(self)] = {} self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
op = layout.operator( op = layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries." ).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries."
def process(self): def process(self):
if not any(socket.is_linked for socket in self.inputs): if not any(socket.is_linked for socket in self.inputs):
return return
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
self.sv_input_names = [i.name for i in self.inputs] self.sv_input_names = [i.name for i in self.inputs]
if 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))
edit = False edit = False
for i in range(len(self.inputs)): for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=False) input = self.inputs[i].sv_get(deepcopy=False)
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name]
):
edit = True edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input self.node_dict[hash(self)][self.inputs[i].name] = input
self.vertices = self.inputs["Vertices"].sv_get(deepcopy=False) self.vertices = ensure_min_nesting(self.inputs["Vertices"].sv_get(deepcopy=False), 4)
self.edges = self.inputs["Edges"].sv_get(deepcopy=False) self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4)
self.faces = self.inputs["Faces"].sv_get(deepcopy=False) self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
geo_data = list(zip(self.vertices, self.edges, self.faces)) data = list(zip(self.vertices, self.edges, self.faces))
objects = []
for object in data:
objects.append(list(zip(object[0], object[1], object[2])))
if self.node_id not in SvIfcStore.id_map: if self.node_id not in SvIfcStore.id_map:
representations = self.create(objects)
representations = self.create(geo_data)
else: else:
if edit is True: if edit is True:
self.edit() self.edit()
representations = self.create(geo_data) representations = self.create(objects)
else: else:
# representations = self.get_existing_element()
representations = SvIfcStore.id_map[self.node_id]["Representations"] representations = SvIfcStore.id_map[self.node_id]["Representations"]
self.outputs["Representation(s)"].sv_set(representations) self.outputs["Representation(s)"].sv_set(representations)
def create(self, geo_data): def create(self, geo_data):
representations_ids = [] representations_ids = []
self.context = self.get_context() self.context = self.get_context()
for item in geo_data: for obj in geo_data:
representation = ifcopenshell.api.run( representations_ids_obj = []
"geometry.add_sverchok_representation", for item in obj:
self.file, representation = ifcopenshell.api.run(
should_run_listeners=False, "geometry.add_sverchok_representation",
context=self.context, self.file,
vertices=[item[0]], should_run_listeners=False,
edges=[item[1]], context=self.context,
faces=[item[2]], vertices=[list(map(tuple, item[0]))],
edges=[list(map(tuple, item[1]))],
faces=[list(map(tuple, item[2]))],
)
if not representation:
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
) )
if not representation:
raise Exception("Couldn't create representation. Possibly wrong context.")
representations_ids.append(representation.id())
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id())
return representations_ids return representations_ids
def edit(self): def edit(self):
# results = self.get_existing_element()
if "Representations" not in SvIfcStore.id_map[self.node_id]: if "Representations" not in SvIfcStore.id_map[self.node_id]:
return return
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run( 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]["Representations"]
return return
def get_context(self): def get_context(self):
context = ifcopenshell.util.representation.get_context( context = ifcopenshell.util.representation.get_context(
self.file, self.context_type, self.context_identifier, self.target_view self.file, self.context_type, self.context_identifier, self.target_view
@@ -162,13 +184,15 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
) )
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):
try: try:
self.file = SvIfcStore.get_file() self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]: if "Representations" in SvIfcStore.id_map[self.node_id]:
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id)) ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
if "Contexts" in SvIfcStore.id_map[self.node_id]: if "Contexts" in SvIfcStore.id_map[self.node_id]:
for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]: for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]:
@@ -180,18 +204,18 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
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]
del self.node_dict[hash(self)] del self.node_dict[hash(self)]
print('Node was deleted') # print('Node was deleted')
except KeyError or AttributeError: except KeyError or AttributeError:
pass pass
def register(): def register():
bpy.utils.register_class(SvIfcSverchokToIfcRepr) bpy.utils.register_class(SvIfcSverchokToIfcRepr)
def unregister(): def unregister():
bpy.utils.unregister_class(SvIfcSverchokToIfcRepr) bpy.utils.unregister_class(SvIfcSverchokToIfcRepr)
+27 -17
View File
@@ -1,6 +1,5 @@
# IfcSverchok - IFC Sverchok extension # IfcSverchok - IFC Sverchok extension
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
# #
# This file is part of IfcSverchok. # This file is part of IfcSverchok.
# #
@@ -32,29 +31,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
Triggers: Ifc write to file Triggers: Ifc write to file
Tooltip: Write active Sverchok Ifc file to path Tooltip: Write active Sverchok Ifc file to path
""" """
def refresh_node_local(self, context): def refresh_node_local(self, context):
if self.refresh_local: if self.refresh_local:
self.process() self.process()
self.refresh_local = False self.refresh_local = False
# out = ""
refresh_local: BoolProperty(name="Write", description="Write to file", update=refresh_node_local) refresh_local: BoolProperty(name="Write", description="Write to file", update=refresh_node_local)
bl_idname = "SvIfcWriteFile" bl_idname = "SvIfcWriteFile"
bl_label = "IFC Write File" bl_label = "IFC Write File"
path: StringProperty(name="path", description="File path to write to. Can be relative.", update=updateNode) path: StringProperty(name="path", description="File path to write to. Can be relative.", update=updateNode)
def sv_init(self, context): def sv_init(self, context):
self.inputs.new("SvStringsSocket", "path").prop_name = "path" self.inputs.new("SvStringsSocket", "path").prop_name = "path"
self.outputs.new("SvStringsSocket", "output") self.outputs.new("SvStringsSocket", "output")
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
row = layout.row(align=True) row = layout.row(align=True)
row.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file.\n N.B.! It's recommended to create a fresh IFC File using the 're-run all nodes' button in IfcSverchok panel before saving." row.operator(
row.prop(self, 'refresh_local', icon='FILE_REFRESH') "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file.\n N.B.! It's recommended to create a fresh IFC File using the 're-run all nodes' button in IfcSverchok panel before saving."
row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self): def process(self):
path = flatten_data(self.inputs["path"].sv_get(), target_level = 1)[0] path = flatten_data(self.inputs["path"].sv_get(), target_level=1)[0]
if not path: if not path:
return return
path = abspath(path) path = abspath(path)
@@ -66,7 +67,7 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
self.ensure_hirarchy(file) self.ensure_hirarchy(file)
file.write(path) file.write(path)
self.outputs["output"].sv_set(f"File written successfully to: {path}.") self.outputs["output"].sv_set(f"File written successfully to: {path}.")
def ensure_hirarchy(self, file): def ensure_hirarchy(self, file):
elements_in_buildings = [] elements_in_buildings = []
if not 0 <= 0 < len(file.by_type("IfcBuilding")): if not 0 <= 0 < len(file.by_type("IfcBuilding")):
@@ -77,10 +78,12 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
elements = ifcopenshell.util.element.get_decomposition(building) elements = ifcopenshell.util.element.get_decomposition(building)
elements_in_buildings.extend(elements) elements_in_buildings.extend(elements)
for spatial in (file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement")): for spatial in file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement"):
if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)): if not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings):
elements = ifcopenshell.util.element.get_decomposition(spatial) elements = ifcopenshell.util.element.get_decomposition(spatial)
ifcopenshell.api.run("aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]) ifcopenshell.api.run(
"aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]
)
elements_in_buildings_after = [] elements_in_buildings_after = []
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
@@ -90,24 +93,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
elements = file.by_type("IfcElement") elements = file.by_type("IfcElement")
for element in elements: for element in elements:
if element not in elements_in_buildings: if element not in elements_in_buildings:
ifcopenshell.api.run("spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]) ifcopenshell.api.run(
"spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]
)
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
elements = ifcopenshell.util.element.get_decomposition(building) elements = ifcopenshell.util.element.get_decomposition(building)
if not building.Decomposes: if not building.Decomposes:
if not 0 <= 0 < len(file.by_type("IfcSite")): if not 0 <= 0 < len(file.by_type("IfcSite")):
ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site")
ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]) ifcopenshell.api.run(
"aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]
)
try: try:
if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"): if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"):
continue continue
except IndexError: except IndexError:
pass pass
ifcopenshell.api.run("aggregate.assign_object", file, product=file.by_type("IfcSite")[0], relating_object=file.by_type("IfcProject")[0]) ifcopenshell.api.run(
"aggregate.assign_object",
file,
product=file.by_type("IfcSite")[0],
relating_object=file.by_type("IfcProject")[0],
)
self.file = file self.file = file
return return
def register(): def register():