Skip to content

Commit cc53744

Browse files
committed
Skeleton operator to regenerate distribution elements recursively
1 parent 945836f commit cc53744

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

src/blenderbim/blenderbim/bim/module/model/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
space.GenerateSpacesFromWalls,
108108
space.ToggleSpaceVisibility,
109109
mep.FitFlowSegments,
110+
mep.RegenerateDistributionElement,
110111
prop.BIMModelProperties,
111112
prop.BIMArrayProperties,
112113
prop.BIMStairProperties,

src/blenderbim/blenderbim/bim/module/model/mep.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import ifcopenshell
2323
import ifcopenshell.api
2424
import ifcopenshell.util.unit
25+
import ifcopenshell.util.system
2526
import ifcopenshell.util.element
2627
import ifcopenshell.util.representation
2728
import mathutils.geometry
@@ -39,6 +40,66 @@
3940
float_is_zero = lambda f: 0.0001 >= f >= -0.0001
4041

4142

43+
class RegenerateDistributionElement(bpy.types.Operator, tool.Ifc.Operator):
44+
bl_idname = "bim.regenerate_distribution_element"
45+
bl_description = (
46+
"Regenerates the positions and segment lengths of a distribution element and all connected elements."
47+
)
48+
bl_label = "Regenerate Distribution Element"
49+
bl_options = {"REGISTER", "UNDO"}
50+
51+
def _execute(self, context):
52+
current_element = tool.Ifc.get_entity(bpy.context.active_object)
53+
processed_elements = set()
54+
55+
# The goal is to regenerate all recursively connected elements that
56+
# minimise movement as much as possible.
57+
58+
# A queue is a list of branches. A branch is a list of elements in
59+
# sequence, each one connecting to another element. An element in a
60+
# branch may have a child queue. The queue and child queues are
61+
# acyclic.
62+
63+
def extend_branch(element, branch, predecessor=None):
64+
processed_elements.add(element)
65+
branch_element = {"element": element, "children": [], "predecessor": predecessor}
66+
branch.append(branch_element)
67+
68+
connected = {e for e in ifcopenshell.util.system.get_connected_to(element) if e not in processed_elements}
69+
connected.update(
70+
[e for e in ifcopenshell.util.system.get_connected_from(element) if e not in processed_elements]
71+
)
72+
73+
if len(connected) == 1:
74+
extend_branch(list(connected)[0], branch, element)
75+
else:
76+
for connected_element in connected:
77+
branch_element["children"].append(extend_branch(connected_element, [], element))
78+
79+
return branch
80+
81+
queue = extend_branch(current_element, [])[0]["children"]
82+
83+
# import pprint
84+
# pprint.pprint(queue)
85+
86+
def process_branch(branch):
87+
for branch_element in branch:
88+
element = branch_element["element"]
89+
print('processing', element)
90+
predecessor = branch_element["predecessor"]
91+
if False: # If the element does not need to be transformed, return early.
92+
return
93+
# Perform the extend, translate, rotate, etc the element as necessary based on the predecessor.
94+
# For segments, prioritise extensions instead of translations.
95+
# For everything else, only translate. No rotation.
96+
for child_branch in branch_element["children"]:
97+
process_branch(child_branch)
98+
99+
for branch in queue:
100+
process_branch(branch)
101+
102+
42103
class FitFlowSegments(bpy.types.Operator, tool.Ifc.Operator):
43104
bl_idname = "bim.fit_flow_segments"
44105
bl_description = "Add a fitting based on currently selected elements and cursor"

0 commit comments

Comments
 (0)