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
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
@@ -28,21 +28,18 @@ bl_info = {
"warning": "",
}
import sys
import importlib
import nodeitems_utils
import sverchok
from sverchok.core import sv_registration_utils, make_node_list
from sverchok.core import make_node_list
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 (
register_extra_category_provider,
unregister_extra_category_provider,
)
from sverchok.ui.nodeview_space_menu import make_extra_category_menus
from sverchok.utils.logging import info, debug
import asyncio
import time
def nodes_index():
return [
@@ -73,8 +70,7 @@ def nodes_index():
("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcRepr"),
("ifc.sverchok_to_ifc", "SvIfcSverchokToIfcRepr"),
("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
import bpy
import os
from os.path import abspath, splitext
from os.path import splitext
import ifcopenshell
from ifcsverchok.ifcstore import SvIfcStore
from sverchok.data_structure import flatten_data
class IFC_Sv_UpdateCurrent(bpy.types.Operator):
"""Update current Sverchok node tree"""
bl_idname = "ifc.sverchok_update_current"
bl_label = "Update current node tree"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
node_group: bpy.props.StringProperty(default="")
force_mode: bpy.props.BoolProperty(default=False)
def execute(self, context):
print("#"*10, "Update current node tree")
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
if node_tree:
if self.force_mode or node_tree.sv_process:
@@ -125,7 +118,8 @@ class IFC_Sv_UpdateCurrent(bpy.types.Operator):
finally:
bpy.context.window.cursor_set("DEFAULT")
self.report({"INFO"}, "Node tree updated.")
return {'FINISHED'}
return {"FINISHED"}
class IFC_Sv_write_file(bpy.types.Operator):
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())
def ensure_hirarchy(self, file):
elements_in_buildings = []
if not 0 <= 0 < len(file.by_type("IfcBuilding")):
elements_in_buildings = set()
if len(file.by_type("IfcBuilding")) == 0:
my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building")
elements = ifcopenshell.util.element.get_decomposition(my_building)
else:
for building in file.by_type("IfcBuilding"):
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")):
if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)):
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):
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"):
elements = ifcopenshell.util.element.get_decomposition(building)
elements_in_buildings_after.extend(elements)
elements_in_buildings.update(elements)
elements = file.by_type("IfcElement")
for element in elements:
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"):
elements = ifcopenshell.util.element.get_decomposition(building)
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("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:
if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"):
continue
except IndexError:
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
return
@@ -198,6 +201,7 @@ class IFC_Sv_write_file(bpy.types.Operator):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class IFC_PT_write_file_panel(bpy.types.Panel):
bl_idname = "IFC_PT_write_file_panel"
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.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")
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():
node_modules = make_node_list()
@@ -281,9 +287,7 @@ def register():
auto_gather_node_classes(extra_nodes)
menu = make_menu()
menu_category_provider = SvExCategoryProvider("IFCSVERCHOK", menu)
register_extra_category_provider(
menu_category_provider
) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories:
register_extra_category_provider(menu_category_provider) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories:
nodeitems_utils.register_node_categories("IFCSVERCHOK", menu)
our_menu_classes = make_extra_category_menus()
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+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 uuid
# import hashlib
# import zipfile
# import tempfile
import ifcopenshell
from ifcopenshell import template
# import blenderbim.bim.handler
# from pathlib import Path
class SvIfcStore:
path = ""
@@ -52,7 +64,6 @@ class SvIfcStore:
SvIfcStore.future = []
SvIfcStore.schema_identifiers = ["IFC4", "IFC2X3"]
@staticmethod
def create_boilerplate():
@@ -61,11 +72,10 @@ class SvIfcStore:
organization=None,
creator=None,
project_name="IfcSverchokDemoProject",
)
if bpy.context.scene.unit_settings.system == 'IMPERIAL':
#TODO change units to imperial
)
if bpy.context.scene.unit_settings.system == "IMPERIAL":
# TODO change units to imperial
pass
# model = ifcopenshell.api.run("context.add_context", file, context_type="Model")
model = ifcopenshell.util.representation.get_context(file, context="Model")
print("model: ", model)
context = ifcopenshell.api.run(
@@ -76,22 +86,9 @@ class SvIfcStore:
target_view="MODEL_VIEW",
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
return SvIfcStore.file
@staticmethod
def get_file():
+1 -3
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -16,4 +15,3 @@
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
+1 -3
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -16,4 +15,3 @@
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+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 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 ifcopenshell
@@ -13,7 +31,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
bl_idname = "SvIfcAddSpatialElement"
bl_label = "IFC Add Spatial Element"
node_dict = {}
Names: StringProperty(name="Name(s)", update=updateNode)
IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace")
Elements: StringProperty(name="Elements", update=updateNode)
@@ -24,14 +42,14 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements"
self.outputs.new("SvStringsSocket", "Entities")
self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Ifc entity by type."
def process(self):
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
@@ -40,8 +58,11 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
edit = False
edit_elements = False
for i in range(len(self.inputs)):
input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default =[])
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]:
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]
):
edit = True
if self.inputs[i].name == "Elements":
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"):
ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result)
else:
ifcopenshell.api.run("spatial.assign_container", self.file, product=items, relating_structure=result)
ifcopenshell.api.run(
"spatial.assign_container", self.file, product=items, relating_structure=result
)
SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id())
spatial_ids.append(result.id())
return spatial_ids
@@ -106,15 +129,25 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
for element in self.elements[i]:
element_set = set([element])
for removed_element in subelements - element_set:
if removed_element.is_a("IfcSpatialElement") or removed_element.is_a("IfcSpatialStructureElement"):
ifcopenshell.api.run("aggregate.unassign_object", self.file, product=removed_element, relating_object=result)
if removed_element.is_a("IfcSpatialElement") or removed_element.is_a(
"IfcSpatialStructureElement"
):
ifcopenshell.api.run(
"aggregate.unassign_object", self.file, product=removed_element, relating_object=result
)
else:
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:
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:
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())
SvIfcStore.id_map[self.node_id] = spatial_ids
return spatial_ids
@@ -129,17 +162,20 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
def repeat_input_unique(self, input, count):
input = repeat_last_for_length(input, count, deepcopy=False)
if input[0]:
input = [a if not (s:=sum(j == a for j in input[:i])) else f'{a}-{s+1}' for i, a in enumerate(input)] # add number to duplicates
input = [
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(input)
] # add number to duplicates
return input
def sv_free(self):
try:
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
# print('Node was deleted')
except KeyError or AttributeError:
pass
def register():
bpy.utils.register_class(SvIfcAddSpatialElement)
+2 -3
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -105,4 +104,4 @@ def register():
def unregister():
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
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
@@ -21,13 +20,12 @@ import bpy
import ifcopenshell
import ifcopenshell.api
import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
import importlib
class SvIfcTooltip(bpy.types.Operator):
bl_idname = "node.sv_ifc_tooltip"
bl_label = "IFC Info"
@@ -43,12 +41,6 @@ class SvIfcTooltip(bpy.types.Operator):
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_label = "IFC API WIP"
tooltip: StringProperty(name="Tooltip")
@@ -57,11 +49,13 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
def sv_init(self, context):
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")
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
def process(self):
@@ -71,11 +65,9 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
try:
module_usecase = self.get_module_usecase()
except:
raise Exception(
f"Couldn't run generate_node(). Module usecase: {module_usecase}"
)
if '.'.join(module_usecase) != self.current_usecase:
self.generate_node(*module_usecase)
raise Exception(f"Couldn't run generate_node(). Module usecase: {module_usecase}")
if ".".join(module_usecase) != self.current_usecase:
self.generate_node(*module_usecase)
try:
for i in range(0, len(self.inputs)):
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]
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):
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.update(getattr(local_module.Usecase(local_module), "settings", {}))
# print("node inputs: ", node_inputs)
while len(self.inputs) > 1:
self.inputs.remove(self.inputs[-1])
if node_inputs:
self.tooltip = ""
for name, data in node_inputs.items():
@@ -116,11 +107,10 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
else:
self.tooltip = f"{name}: None\n"
self.tooltip = self.tooltip.strip()
self.current_usecase = '.'.join([module, usecase])
self.current_usecase = ".".join([module, usecase])
def process_ifc(self, usecase, *setting_values):
if usecase and setting_values:
settings = dict(zip(self.sv_input_names[1:], setting_values))
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)])
except:
raise Exception(f"Couldn't run usecase.")
def register():
@@ -144,4 +132,4 @@ def register():
def unregister():
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
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
# Copyright (C) 2022 Martina Jakubowska <martina@jakubowska.dk>
#
# This file is part of IfcSverchok.
#
@@ -28,18 +28,20 @@ import blenderbim.tool as tool
import blenderbim.core.geometry as core
from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, PointerProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import (updateNode, flatten_data, fixed_iter, flat_iter)
from sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter
from blenderbim.bim.module.root.prop import get_contexts
from sverchok.data_structure import zip_long_repeat, node_id
from sverchok.core.socket_data import sv_get_socket
from itertools import chain, cycle
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
"""
Triggers: BMesh to Ifc Repr
Tooltip: Blender mesh to Ifc Shape Representation
"""
bl_idname = "SvIfcBMeshToIfcRepr"
bl_label = "IFC Blender Mesh to IFC Repr"
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)
context_types = [
('Model', 'Model', 'Context type: Model', 0),
('Plan', 'Plan', 'Context type: Plan', 1),
("Model", "Model", "Context type: Model", 0),
("Plan", "Plan", "Context type: Plan", 1),
]
context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1),
('Box', 'Box', 'Context identifier: Box', 2),
('Axis', 'Axis', 'Context identifier: Axis', 3),
("Body", "Body", "Context identifier: Body", 0),
("Annotation", "Annotation", "Context identifier: Annotation", 1),
("Box", "Box", "Context identifier: Box", 2),
("Axis", "Axis", "Context identifier: Axis", 3),
]
target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3),
("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0),
("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1),
("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2),
("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3),
]
blender_objects: PointerProperty(name="Blender Mesh(es)", description="Blender Mesh Object(s)",update=updateNode, type=bpy.types.Object)
context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode)
context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode)
target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode)
blender_objects: PointerProperty(
name="Blender Mesh(es)", description="Blender Mesh Object(s)", update=updateNode, type=bpy.types.Object
)
context_type: EnumProperty(
name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode
)
context_identifier: EnumProperty(
name="Context Identifier",
description="Default: Body",
default="Body",
items=context_identifiers,
update=updateNode,
)
target_view: EnumProperty(
name="Target View",
description="Default: MODEL VIEW",
default="MODEL_VIEW",
items=target_views,
update=updateNode,
)
tooltip: StringProperty(name="Tooltip")
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" #no prop for now
self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" # no prop for now
self.outputs.new("SvVerticesSocket", "Representations")
self.outputs.new("SvMatrixSocket", "Locations")
def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries."
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.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH')
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self):
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
if not self.inputs["blender_objects"].sv_get()[0]:
return
edit = False
for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=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
self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
blender_objects = self.inputs["blender_objects"].sv_get()
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"]
locations = SvIfcStore.id_map[self.node_id]["Locations"]
print("representations: ", representations)
print("locations: ", locations)
# print("representations: ", representations)
self.outputs["Representations"].sv_set(representations)
self.outputs["Locations"].sv_set(locations)
@@ -134,41 +155,63 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
representations_ids = []
locations = []
for blender_object in blender_objects:
if blender_object.type == 'MESH':
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
if blender_object.type == "MESH":
try:
bpy.ops.object.mode_set(mode="OBJECT")
except:
pass
bpy.ops.object.select_all(action="DESELECT")
blender_object.select_set(True)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.separate(type='LOOSE')
try:
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:
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:
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())
locations.append(blender_object.matrix_world)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(blender_object.matrix_world)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
representations_ids_obj.append(representation.id())
locations_obj.append(obj.matrix_world)
representations_ids.append(representations_ids_obj)
locations.append(locations_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(
representations_ids_obj
)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(locations_obj)
try:
bpy.ops.object.mode_set(mode="OBJECT")
except:
pass
bpy.ops.object.select_all(action="DESELECT")
return representations_ids, locations
def edit(self):
if "Representations" not in SvIfcStore.id_map[self.node_id]:
return
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))
for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj:
ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
del SvIfcStore.id_map[self.node_id]["Representations"]
del SvIfcStore.id_map[self.node_id]["Locations"]
return
def get_existing_element(self):
results = []
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
results.append(self.file.by_id(step_id))
return results
def get_context(self):
context = ifcopenshell.util.representation.get_context(self.file, self.context_type, self.context_identifier, self.target_view)
context = ifcopenshell.util.representation.get_context(
self.file, self.context_type, self.context_identifier, self.target_view
)
if not context:
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type)
if not parent:
@@ -184,13 +227,15 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id())
return context
def sv_free(self):
try:
self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]:
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run("geometry.remove_representation", self.file, representation=self.file.by_id(step_id))
for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj:
ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
if "Contexts" in SvIfcStore.id_map[self.node_id]:
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 not self.file.get_inverse(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)
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
# print('Node was deleted')
except KeyError or AttributeError:
pass
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+10 -6
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -17,8 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
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):
bl_idname = "SvIfcById"
bl_label = "IFC By Id"
id: StringProperty(name="Id(s)", update=updateNode, )
id: StringProperty(
name="Id(s)",
update=updateNode,
)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "id").prop_name = "id"
self.outputs.new("SvStringsSocket", "Entities")
def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Get IFC element by 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):
self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1)
print(self.ids)
if not self.ids[0]:
return
self.file = SvIfcStore.get_file()
self.entities = [self.file.by_id(int(step_id)) for step_id in self.ids]
self.outputs["Entities"].sv_set(self.entities)
def register():
bpy.utils.register_class(SvIfcById)
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+23 -10
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -23,8 +22,8 @@ import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty
from ifcsverchok.ifcstore import SvIfcStore
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data
from sverchok.utils.handle_blender_data import keep_enum_reference
from sverchok.data_structure import updateNode
def get_ifc_products(self, context):
ifc_products = getattr(self, "ifc_products", [])
@@ -57,6 +56,7 @@ def update_ifc_products(self, context):
if hasattr(self, "ifc_classes"):
self.ifc_classes.clear()
def get_ifc_classes(self, context):
ifc_classes = getattr(self, "ifc_classes", [])
if ifc_classes:
@@ -83,9 +83,18 @@ def get_ifc_classes(self, context):
class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcByType"
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_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)
ifc_product: EnumProperty(
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
)
custom_ifc_class: StringProperty(
name="Custom IfcClass", description="Give the name of your custom IfcClass.", update=updateNode
)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
@@ -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.outputs.new("SvStringsSocket", "Entity")
self.width = 200
def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
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):
self.file = SvIfcStore.get_file()
@@ -119,4 +132,4 @@ def register():
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
from mathutils import Matrix, Vector
from mathutils import Matrix
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
# import ifcsverchok.ifc_store
# from bpy.props import StringProperty
# from sverchok.node_tree import SverchCustomTreeNode
# from sverchok.data_structure import updateNode
import bpy
import ifcopenshell
from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty
from bpy.props import StringProperty, BoolProperty
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):
@@ -43,32 +53,33 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions"
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
self.inputs.new("SvStringsSocket", "Representations").prop_name = "Representations"
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory=False
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False
self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
self.outputs.new("SvStringsSocket", "Entities")
self.node_dict[hash(self)] = {}
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.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True)
row.prop(self, 'refresh_local', icon='FILE_REFRESH')
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
row.prop(self, "refresh_local", icon="FILE_REFRESH")
def process(self):
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1)
self.descriptions = flatten_data(self.inputs["Descriptions"].sv_get(), target_level=1)
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0]
self.representations = flatten_data(self.inputs["Representations"].sv_get(), target_level=1)
self.locations = flatten_data(self.inputs["Locations"].sv_get(default=[]), target_level=1)
self.representations = ensure_min_nesting(self.inputs["Representations"].sv_get(), 2)
self.representations = flatten_data(self.representations, target_level=2)
self.locations = ensure_min_nesting(self.inputs["Locations"].sv_get(default=[]), 2)
self.properties = self.inputs["Properties"].sv_get()
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
if not self.inputs["IfcClass"].sv_get()[0][0]:
@@ -76,18 +87,24 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
edit = False
for i in range(len(self.inputs)):
input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default =[])
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]:
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]
):
edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
if self.refresh_local:
edit = True
self.file = SvIfcStore.get_file()
if self.representations[0]:
if self.representations[0][0]:
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:
raise
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()
else:
entities = SvIfcStore.id_map[self.node_id]
print("Entities: ", entities)
# print("Entities: ", entities)
self.outputs["Entities"].sv_set(entities)
def create(self, index=None):
@@ -114,20 +130,32 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
iterator = [index]
for i in iterator:
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:
if self.representations[i]:
ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i])
for repr in self.representations[i]:
if self.representations[i]:
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr
)
except IndexError:
pass
try:
if isinstance(self.locations[i], Matrix):
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i])
for loc in self.locations[i]:
if isinstance(self.locations[i], Matrix):
ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=entity, matrix=loc
)
except IndexError:
pass
entities_ids.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)
return entities_ids
@@ -146,15 +174,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper
entity.Description = self.descriptions[i]
try:
if self.representations[i] and self.representations[i].is_a('IfcProductDefinitionShape'):
entity.Representation = self.representations[i]
elif self.representations[i]:
ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i])
for repr in self.representations[i]:
if repr and repr.is_a("IfcProductDefinitionShape"):
entity.Representation = repr
elif repr:
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=entity, representation=repr
)
except IndexError:
pass
try:
if isinstance(self.locations[i], Matrix):
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i])
for loc in self.locations[i]:
if isinstance(loc, Matrix):
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=loc)
except IndexError:
pass
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())
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
return entities_ids
def repeat_input_unique(self, input, count):
input = repeat_last_for_length(input, count, deepcopy=False)
if input[0]:
input = [a if not (s:=sum(j == a for j in input[:i])) else f'{a}-{s+1}' for i, a in enumerate(input)] # add number to duplicates
input = [
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(input)
] # add number to duplicates
return input
def sv_free(self):
try:
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
# print('Node was deleted')
except KeyError or AttributeError:
pass
+1 -1
View File
@@ -1,5 +1,5 @@
# 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.
#
+11 -12
View File
@@ -1,5 +1,5 @@
# 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.
#
@@ -19,10 +19,8 @@
import bpy
import ifcopenshell
import ifcsverchok.helper
from bpy.props import StringProperty
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):
bl_idname = "SvIfcCreateProject"
@@ -36,25 +34,26 @@ class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe
self.outputs.new("SvVerticesSocket", "file")
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.tooltip = self.tooltip
op = layout.operator(
"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):
#file
# file
file = self.inputs["file"].sv_get()[0][0]
if file:
schema_name = file.wrapped_data.schema
else:
schema_name = "IFC4"
#project name
# project name
project_name = self.inputs["project_name"].sv_get()[0][0]
self.process_ifc(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))
lengthunit = ifcopenshell.api.run("unit.add_si_unit", file, unit_type="LENGTHUNIT", name="METRE")
ifcopenshell.api.run("unit.assign_unit", file, units=[lengthunit])
+12 -24
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -28,29 +27,16 @@ from sverchok.node_tree import SverchCustomTreeNode
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):
"""
Triggers: Ifc create shape by entity
Tooltip: Create Blender shape by Ifc Entity
"""
is_scene_dependent = True
is_interactive = False
node_dict = {}
def refresh_node(self, context):
if self.refresh_local:
self.process()
@@ -61,22 +47,23 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
bl_idname = "SvIfcCreateShape"
bl_label = "IFC Create Blender Shape"
entity: StringProperty(name="Entities", update=updateNode)
def sv_init(self, context):
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):
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.prop(self, 'refresh_local', icon='FILE_REFRESH')
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.prop(self, "refresh_local", icon="FILE_REFRESH")
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]:
return
if self.refresh_local or hash(self) not in self.node_dict:
self.file = SvIfcStore.get_file()
try:
@@ -87,7 +74,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
self.node_dict[hash(self)] = blender_objects
else:
blender_objects = self.node_dict[hash(self)]
self.outputs["Object(s)"].sv_set(blender_objects)
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))
return blender_objects
def register():
# bpy.utils.register_class(SvIfcCreateShapeRefresh)
bpy.utils.register_class(SvIfcCreateShape)
+1 -4
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -20,9 +19,7 @@
import bpy
import ifcopenshell
import ifcsverchok.helper
from bpy.props import StringProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
class SvIfcGenerateGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+13 -6
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -20,11 +19,12 @@
import bpy
import ifcopenshell
import ifcsverchok.helper
from bpy.props import StringProperty, EnumProperty
from bpy.props import EnumProperty
from ifcsverchok.ifcstore import SvIfcStore
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
def get_ifc_products(self, context):
ifc_products = getattr(self, "ifc_products", [])
file = SvIfcStore.get_file()
@@ -83,15 +83,22 @@ def get_ifc_classes(self, context):
class SvIfcPickIfcClass(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcPickIfcClass"
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_class: EnumProperty(items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode)
ifc_product: EnumProperty(
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):
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
self.outputs.new("SvStringsSocket", "IfcClass")
self.width = 200
def draw_buttons(self, context, layout):
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Ifc Class Picker"
@@ -1,5 +1,5 @@
# 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.
#
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from email.mime import application
import bpy
import ifcopenshell
@@ -25,6 +26,7 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
from ifcopenshell import template
class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
bl_idname = "SvIfcQuickProjectSetup"
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_version: StringProperty(name="application_version", update=updateNode)
timestamp: StringProperty(name="timestamp", update=updateNode)
def sv_init(self, context):
input_socket = self.inputs.new("SvStringsSocket", "filename")
@@ -59,8 +60,10 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
self.outputs.new("SvVerticesSocket", "file")
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.tooltip = self.tooltip
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.tooltip = self.tooltip
def process(self):
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 = {k: v for k, v in settings.items() if v != ""}
file = template.create(
filename=settings['filename'],
timestring=settings['timestring'],
organization=settings['organization'],
creator=settings['creator'],
schema_identifier=settings['schema_identifier'],
application_version=settings['application_version'],
timestamp=settings['timestamp'],
application=settings['application'],
project_globalid=settings['project_globalid'],
project_name=settings['project_name'],
)
filename=settings["filename"],
timestring=settings["timestring"],
organization=settings["organization"],
creator=settings["creator"],
schema_identifier=settings["schema_identifier"],
application_version=settings["application_version"],
timestamp=settings["timestamp"],
application=settings["application"],
project_globalid=settings["project_globalid"],
project_name=settings["project_name"],
)
self.outputs["file"].sv_set([[file]])
+2 -3
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -63,7 +62,7 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S
self.outputs.new("SvStringsSocket", name).prop_name = name
self.current_ifc_class = ifc_class
def process_ifc(self, file, entity):
def process_ifc(self, entity):
self.outputs["id"].sv_set([[entity.id()]])
self.outputs["is_a"].sv_set([[entity.is_a()]])
for i in range(0, self.entity_schema.attribute_count()):
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
+1 -2
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -1,6 +1,5 @@
# 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.
#
+90 -66
View File
@@ -1,5 +1,5 @@
# 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.
#
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with IfcSverchok. If not, see <http://www.gnu.org/licenses/>.
from copy import deepcopy
import bpy
import ifcopenshell
@@ -26,124 +26,146 @@ import blenderbim.tool as tool
import blenderbim.core.geometry as core
from bpy.props import StringProperty, EnumProperty, IntProperty, FloatVectorProperty
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):
"""
Triggers: Sv to Ifc Repr
Tooltip: Sverchok geometry to Ifc Shape Representation
"""
bl_idname = "SvIfcSverchokToIfcRepr"
bl_label = "IFC Sverchok to IFC Repr"
node_dict = {}
n_id: StringProperty()
context_types = [
('Model', 'Model', 'Context type: Model', 0),
('Plan', 'Plan', 'Context type: Plan', 1),
("Model", "Model", "Context type: Model", 0),
("Plan", "Plan", "Context type: Plan", 1),
]
context_identifiers = [
('Body', 'Body', 'Context identifier: Body', 0),
('Annotation', 'Annotation', 'Context identifier: Annotation', 1),
('Box', 'Box', 'Context identifier: Box', 2),
('Axis', 'Axis', 'Context identifier: Axis', 3),
("Body", "Body", "Context identifier: Body", 0),
("Annotation", "Annotation", "Context identifier: Annotation", 1),
("Box", "Box", "Context identifier: Box", 2),
("Axis", "Axis", "Context identifier: Axis", 3),
]
target_views = [
('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0),
('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1),
('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2),
('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3),
("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0),
("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1),
("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2),
("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3),
]
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)
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,
)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
self.inputs.new("SvVerticesSocket", "Vertices")
self.inputs.new("SvStringsSocket", "Edges")
self.inputs.new("SvStringsSocket", "Faces")
self.inputs.new("SvStringsSocket", "Faces")
self.outputs.new("SvVerticesSocket", "Representation(s)")
self.width = 210
self.node_dict[hash(self)] = {}
def draw_buttons(self, context, layout):
op = layout.operator(
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries."
def process(self):
if not any(socket.is_linked for socket in self.inputs):
return
self.file = SvIfcStore.get_file()
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
self.node_dict[hash(self)] = {} #happens if node is already on canvas when blender loads
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
if not self.node_dict[hash(self)]:
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
edit = False
for i in range(len(self.inputs)):
input = self.inputs[i].sv_get(deepcopy=False)
if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]:
if (
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
and input != self.node_dict[hash(self)][self.inputs[i].name]
):
edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input
self.vertices = self.inputs["Vertices"].sv_get(deepcopy=False)
self.edges = self.inputs["Edges"].sv_get(deepcopy=False)
self.faces = self.inputs["Faces"].sv_get(deepcopy=False)
geo_data = list(zip(self.vertices, self.edges, self.faces))
self.vertices = ensure_min_nesting(self.inputs["Vertices"].sv_get(deepcopy=False), 4)
self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4)
self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
data = list(zip(self.vertices, self.edges, self.faces))
objects = []
for object in data:
objects.append(list(zip(object[0], object[1], object[2])))
if self.node_id not in SvIfcStore.id_map:
representations = self.create(geo_data)
representations = self.create(objects)
else:
if edit is True:
self.edit()
representations = self.create(geo_data)
representations = self.create(objects)
else:
# representations = self.get_existing_element()
representations = SvIfcStore.id_map[self.node_id]["Representations"]
self.outputs["Representation(s)"].sv_set(representations)
def create(self, geo_data):
representations_ids = []
self.context = self.get_context()
for item in geo_data:
representation = ifcopenshell.api.run(
"geometry.add_sverchok_representation",
self.file,
should_run_listeners=False,
context=self.context,
vertices=[item[0]],
edges=[item[1]],
faces=[item[2]],
for obj in geo_data:
representations_ids_obj = []
for item in obj:
representation = ifcopenshell.api.run(
"geometry.add_sverchok_representation",
self.file,
should_run_listeners=False,
context=self.context,
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
def edit(self):
# results = self.get_existing_element()
if "Representations" not in SvIfcStore.id_map[self.node_id]:
return
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
ifcopenshell.api.run(
for obj in SvIfcStore.id_map[self.node_id]["Representations"]:
for step_id in obj:
ifcopenshell.api.run(
"geometry.remove_representation", self.file, representation=self.file.by_id(step_id)
)
del SvIfcStore.id_map[self.node_id]["Representations"]
return
def get_context(self):
context = ifcopenshell.util.representation.get_context(
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())
return context
def sv_free(self):
try:
self.file = SvIfcStore.get_file()
if "Representations" in SvIfcStore.id_map[self.node_id]:
for step_id in SvIfcStore.id_map[self.node_id]["Representations"]:
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]:
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 not self.file.get_inverse(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)
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
print('Node was deleted')
# print('Node was deleted')
except KeyError or AttributeError:
pass
def register():
bpy.utils.register_class(SvIfcSverchokToIfcRepr)
def unregister():
bpy.utils.unregister_class(SvIfcSverchokToIfcRepr)
bpy.utils.unregister_class(SvIfcSverchokToIfcRepr)
+27 -17
View File
@@ -1,6 +1,5 @@
# 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.
#
@@ -32,29 +31,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
Triggers: Ifc write to file
Tooltip: Write active Sverchok Ifc file to path
"""
def refresh_node_local(self, context):
if self.refresh_local:
self.process()
self.refresh_local = False
# out = ""
refresh_local: BoolProperty(name="Write", description="Write to file", update=refresh_node_local)
bl_idname = "SvIfcWriteFile"
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):
self.inputs.new("SvStringsSocket", "path").prop_name = "path"
self.outputs.new("SvStringsSocket", "output")
def draw_buttons(self, context, layout):
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.prop(self, 'refresh_local', icon='FILE_REFRESH')
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.prop(self, "refresh_local", icon="FILE_REFRESH")
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:
return
path = abspath(path)
@@ -66,7 +67,7 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
self.ensure_hirarchy(file)
file.write(path)
self.outputs["output"].sv_set(f"File written successfully to: {path}.")
def ensure_hirarchy(self, file):
elements_in_buildings = []
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_in_buildings.extend(elements)
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)):
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):
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"):
@@ -90,24 +93,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
elements = file.by_type("IfcElement")
for element in elements:
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"):
elements = ifcopenshell.util.element.get_decomposition(building)
if not building.Decomposes:
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("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:
if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"):
continue
except IndexError:
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
return
def register():