mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
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:
+39
-35
@@ -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,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
@@ -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,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,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,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,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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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) 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,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) 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)
|
||||
|
||||
@@ -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,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.
|
||||
#
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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,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,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.
|
||||
#
|
||||
|
||||
@@ -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]])
|
||||
|
||||
|
||||
@@ -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,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.
|
||||
#
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user