Bug fixes and changed behaviour of create_entity, so it creates an entity pr. each representation

This commit is contained in:
martinaCodes
2022-11-13 15:56:33 +01:00
committed by Dion Moult
parent 421f861e46
commit 0ab0213dea
5 changed files with 196 additions and 144 deletions
@@ -18,6 +18,8 @@
import bpy
from itertools import chain
import ifcopenshell
import ifcsverchok.helper
from ifcsverchok.ifcstore import SvIfcStore
@@ -99,7 +101,8 @@ class SvIfcAddSpatialElement(
0
]
self.elements = ensure_min_nesting(self.inputs["Elements"].sv_get(), 2)
self.elements = flatten_data(self.elements, target_level=2)
if isinstance(self.elements[0][0], list):
self.elements = [list(chain.from_iterable(el)) for el in self.elements]
if not self.elements[0][0]:
raise Exception('Mandatory input "Element(s)" is missing.')
return
+41 -39
View File
@@ -142,7 +142,7 @@ class SvIfcBMeshToIfcRepr(
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]:
if not self.inputs["blender_objects"].sv_get(deepcopy=True)[0]:
return
edit = False
for i in range(len(self.inputs)):
@@ -154,7 +154,7 @@ class SvIfcBMeshToIfcRepr(
edit = True
self.node_dict[hash(self)][self.inputs[i].name] = input.copy()
blender_objects = self.inputs["blender_objects"].sv_get()
blender_objects = self.inputs["blender_objects"].sv_get(deepcopy=True)
self.file = SvIfcStore.get_file()
if self.refresh_local:
@@ -169,60 +169,63 @@ class SvIfcBMeshToIfcRepr(
representations = SvIfcStore.id_map[self.node_id]["Representations"]
locations = SvIfcStore.id_map[self.node_id]["Locations"]
# print("representations: ", representations)
self.outputs["Representations"].sv_set(representations)
self.outputs["Locations"].sv_set(locations)
def create(self, blender_objects):
representations_ids = []
locations = []
context = self.get_context()
for blender_object in blender_objects:
if blender_object.type == "MESH":
try:
bpy.ops.object.mode_set(mode="OBJECT")
except Exception as e:
print(e)
pass
bpy.ops.object.select_all(action="DESELECT")
try:
bpy.ops.object.mode_set(mode="EDIT")
except Exception as e:
print(e)
pass
blender_object.select_set(True)
bpy.ops.mesh.separate(type="LOOSE")
representations_ids_obj = []
locations_obj = []
for obj in bpy.context.selected_objects:
bpy.context.view_layer.objects.active = blender_object
try:
bpy.ops.object.mode_set(mode="OBJECT")
except Exception as e:
print(e)
pass
bpy.ops.object.select_all(action="DESELECT")
blender_object.select_set(True)
try:
bpy.ops.object.mode_set(mode="EDIT")
except Exception as e:
print(e)
pass
bpy.ops.mesh.separate(
type="LOOSE"
) # This isn't a great solution bc it creates new objects in the scene, thus changing the users model
representations_ids_obj = []
locations_obj = []
try:
bpy.ops.object.mode_set(mode="OBJECT")
except Exception as e:
print(e)
pass
for obj in bpy.context.selected_objects:
if blender_object.type == "MESH":
representation = ifcopenshell.api.run(
"geometry.add_representation",
self.file,
should_run_listeners=False,
blender_object=obj,
geometry=obj.data,
context=self.get_context(),
context=context,
)
if not representation:
raise Exception(
"Couldn't create representation. Possibly wrong context."
)
representations_ids_obj.append(representation.id())
locations_obj.append(obj.matrix_world)
representations_ids.append(representations_ids_obj)
locations.append(locations_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Representations", []
).append(representations_ids_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Locations", []
).append(locations_obj)
try:
bpy.ops.object.mode_set(mode="OBJECT")
except Exception as e:
print(e)
pass
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)
bpy.ops.object.select_all(action="DESELECT")
return representations_ids, locations
@@ -234,7 +237,7 @@ class SvIfcBMeshToIfcRepr(
ifcopenshell.api.run(
"geometry.remove_representation",
self.file,
representation=self.file.by_id(step_id),
representation=self.file.by_id(step_id[0]),
)
del SvIfcStore.id_map[self.node_id]["Representations"]
del SvIfcStore.id_map[self.node_id]["Locations"]
@@ -291,7 +294,6 @@ class SvIfcBMeshToIfcRepr(
ifcopenshell.api.run(
"context.remove_context", self.file, context=parent
)
# print("Removed context with step ID: ", context_id)
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
del SvIfcStore.id_map[self.node_id]
del self.node_dict[hash(self)]
+108 -90
View File
@@ -69,8 +69,8 @@ class SvIfcCreateEntity(
default="",
update=updateNode,
)
# Locations: FloatVectorProperty(name="Locations", default="", update=updateNode)
Properties: StringProperty(name="properties", update=updateNode)
# Locations: FloatVectorProperty(name="Locations", default="", subtype='MATRIX', update=updateNode)
# Properties: StringProperty(name="properties", update=updateNode)
def sv_init(self, context):
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
@@ -80,7 +80,7 @@ class SvIfcCreateEntity(
"SvStringsSocket", "Representations"
).prop_name = "Representations"
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False
self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
# self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
self.outputs.new("SvStringsSocket", "Entities")
self.node_dict[hash(self)] = {}
@@ -102,14 +102,15 @@ class SvIfcCreateEntity(
0
]
self.representations = ensure_min_nesting(
self.inputs["Representations"].sv_get(), 2
self.inputs["Representations"].sv_get(), 3
)
self.representations = flatten_data(self.representations, target_level=2)
self.representations = flatten_data(self.representations, target_level=3)
self.locations = ensure_min_nesting(
self.inputs["Locations"].sv_get(default=[]), 2
self.inputs["Locations"].sv_get(default=[]), 3
)
self.properties = self.inputs["Properties"].sv_get()
self.locations = flatten_data(self.locations, target_level=3)
# self.properties = self.inputs["Properties"].sv_get()
print("#" * 80, "\nCreate Entity", "\n", "#" * 80)
self.sv_input_names = [i.name for i in self.inputs]
if hash(self) not in self.node_dict:
@@ -138,22 +139,35 @@ class SvIfcCreateEntity(
self.file = SvIfcStore.get_file()
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 representation]
for representation in self.representations
]
except Exception as e:
raise
self.names = self.repeat_input_unique(self.names, len(self.representations))
self.descriptions = self.repeat_input_unique(
self.descriptions, len(self.representations)
)
elif not self.representations[0][0]:
representations = []
names = []
descriptions = []
for group in self.representations:
try:
group_representations = [
[self.file.by_id(step_id) for step_id in representation]
for representation in group
]
representations.append(group_representations)
except Exception as e:
raise
names.append(
self.repeat_input_unique(self.names, len(group_representations))
)
descriptions.append(
self.repeat_input_unique(
self.descriptions, len(group_representations)
)
)
self.representations = representations
self.names = names
self.descriptions = descriptions
elif not self.representations[0][0][0]:
self.descriptions = self.repeat_input_unique(
self.descriptions, len(self.names)
)
self.names = ensure_min_nesting(self.names, 3)
self.descriptions = ensure_min_nesting(self.descriptions, 3)
if self.node_id not in SvIfcStore.id_map:
entities = self.create()
@@ -163,26 +177,75 @@ class SvIfcCreateEntity(
else:
entities = SvIfcStore.id_map[self.node_id]
# print("Entities: ", entities)
self.outputs["Entities"].sv_set(entities)
def create(self, index=None):
entities_ids = []
iterator = range(len(self.names))
if index is not None:
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],
)
for i, group in enumerate(self.names):
group_entities_ids = []
iterator = range(len(group))
if index is not None:
iterator = [index]
for j in iterator:
try:
for repr in self.representations[i]:
if repr:
entity = ifcopenshell.api.run(
"root.create_entity",
self.file,
ifc_class=self.ifc_class,
name=self.names[i][j],
description=self.descriptions[i][j],
)
try:
for repr in self.representations[i][j]:
if repr:
ifcopenshell.api.run(
"geometry.assign_representation",
self.file,
product=entity,
representation=repr,
)
except IndexError:
pass
try:
for loc in self.locations[i][j]:
print("Location: ", loc)
if isinstance(loc, Matrix):
ifcopenshell.api.run(
"geometry.edit_object_placement",
self.file,
product=entity,
matrix=loc,
)
except IndexError:
pass
group_entities_ids.append(entity.id())
except Exception as e:
raise Exception("Something went wrong. Cannot create entity.", e)
SvIfcStore.id_map.setdefault(self.node_id, []).append(group_entities_ids)
entities_ids.append(group_entities_ids)
return entities_ids
def edit(self):
entities_ids = []
id_map_copy = SvIfcStore.id_map[self.node_id].copy()
for i, group in enumerate(self.names):
group_entities_ids = []
for j, _ in enumerate(group):
try:
step_id = id_map_copy[i][j]
except IndexError:
id = self.create(index=j)
group_entities_ids.append(id[0])
continue
entity = self.file.by_id(step_id)
entity.Name = self.names[i][j]
entity.Description = self.descriptions[i][j]
try:
for repr in self.representations[i][j]:
if repr and repr.is_a("IfcProductDefinitionShape"):
entity.Representation = repr
elif repr:
ifcopenshell.api.run(
"geometry.assign_representation",
self.file,
@@ -192,7 +255,7 @@ class SvIfcCreateEntity(
except IndexError:
pass
try:
for loc in self.locations[i]:
for loc in self.locations[i][j]:
if isinstance(loc, Matrix):
ifcopenshell.api.run(
"geometry.edit_object_placement",
@@ -202,60 +265,15 @@ class SvIfcCreateEntity(
)
except IndexError:
pass
entities_ids.append(entity.id())
SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id())
except Exception as e:
raise Exception("Something went wrong. Cannot create entity.", e)
return entities_ids
if entity.is_a() != self.ifc_class:
SvIfcStore.id_map[self.node_id][i].remove(step_id)
entity = ifcopenshell.util.schema.reassign_class(
self.file, entity, self.ifc_class
)
group_entities_ids.append(entity.id())
entities_ids.append(group_entities_ids)
def edit(self):
entities_ids = []
id_map_copy = SvIfcStore.id_map[self.node_id].copy()
for i, _ in enumerate(self.names):
try:
step_id = id_map_copy[i]
except IndexError:
id = self.create(index=i)
entities_ids.append(id[0])
continue
entity = self.file.by_id(step_id)
entity.Name = self.names[i]
entity.Description = self.descriptions[i]
try:
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:
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:
SvIfcStore.id_map[self.node_id].remove(step_id)
entity = ifcopenshell.util.schema.reassign_class(
self.file, entity, self.ifc_class
)
SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id())
entities_ids.append(entity.id())
if id_map_copy > entities_ids:
SvIfcStore.id_map[self.node_id] = entities_ids
SvIfcStore.id_map[self.node_id] = entities_ids
return entities_ids
def repeat_input_unique(self, input, count):
+3 -3
View File
@@ -162,7 +162,7 @@ class SvIfcSverchokToIfcRepr(
raise Exception(
"Couldn't create representation. Possibly wrong context."
)
representations_ids_obj.append(representation.id())
representations_ids_obj.append([representation.id()])
representations_ids.append(representations_ids_obj)
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
"Representations", []
@@ -177,7 +177,7 @@ class SvIfcSverchokToIfcRepr(
ifcopenshell.api.run(
"geometry.remove_representation",
self.file,
representation=self.file.by_id(step_id),
representation=self.file.by_id(step_id[0]),
)
del SvIfcStore.id_map[self.node_id]["Representations"]
return
@@ -215,7 +215,7 @@ class SvIfcSverchokToIfcRepr(
ifcopenshell.api.run(
"geometry.remove_representation",
self.file,
representation=self.file.by_id(step_id),
representation=self.file.by_id(step_id[0]),
)
if "Contexts" in SvIfcStore.id_map[self.node_id]:
+40 -11
View File
@@ -26,7 +26,9 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, flatten_data
class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
class SvIfcWriteFile(
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
):
"""
Triggers: Ifc write to file
Tooltip: Write active Sverchok Ifc file to path
@@ -37,11 +39,17 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
self.process()
self.refresh_local = False
refresh_local: BoolProperty(name="Write", description="Write to file", update=refresh_node_local)
refresh_local: BoolProperty(
name="Write", description="Write to file", update=refresh_node_local
)
bl_idname = "SvIfcWriteFile"
bl_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"
@@ -71,18 +79,27 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
def ensure_hirarchy(self, file):
elements_in_buildings = []
if not 0 <= 0 < len(file.by_type("IfcBuilding")):
my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building")
my_building = ifcopenshell.api.run(
"root.create_entity", file, ifc_class="IfcBuilding", name="My Building"
)
elements = ifcopenshell.util.element.get_decomposition(my_building)
else:
for building in file.by_type("IfcBuilding"):
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]
"aggregate.assign_object",
file,
product=spatial,
relating_object=file.by_type("IfcBuilding")[0],
)
elements_in_buildings_after = []
@@ -94,19 +111,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
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]
"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(
"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]
"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"):
if (
file.by_type("IfcSite")[0]
.Decomposes[0]
.RelatingObject.is_a("IfcProject")
):
continue
except IndexError:
pass