Skeleton operator to regenerate distribution elements recursively

This commit is contained in:
Dion Moult
2023-08-04 17:20:50 +10:00
parent 945836f578
commit cc53744c29
2 changed files with 62 additions and 0 deletions
@@ -107,6 +107,7 @@ classes = (
space.GenerateSpacesFromWalls,
space.ToggleSpaceVisibility,
mep.FitFlowSegments,
mep.RegenerateDistributionElement,
prop.BIMModelProperties,
prop.BIMArrayProperties,
prop.BIMStairProperties,
@@ -22,6 +22,7 @@ import bmesh
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.unit
import ifcopenshell.util.system
import ifcopenshell.util.element
import ifcopenshell.util.representation
import mathutils.geometry
@@ -39,6 +40,66 @@ V = lambda *x: Vector([float(i) for i in x])
float_is_zero = lambda f: 0.0001 >= f >= -0.0001
class RegenerateDistributionElement(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.regenerate_distribution_element"
bl_description = (
"Regenerates the positions and segment lengths of a distribution element and all connected elements."
)
bl_label = "Regenerate Distribution Element"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
current_element = tool.Ifc.get_entity(bpy.context.active_object)
processed_elements = set()
# The goal is to regenerate all recursively connected elements that
# minimise movement as much as possible.
# A queue is a list of branches. A branch is a list of elements in
# sequence, each one connecting to another element. An element in a
# branch may have a child queue. The queue and child queues are
# acyclic.
def extend_branch(element, branch, predecessor=None):
processed_elements.add(element)
branch_element = {"element": element, "children": [], "predecessor": predecessor}
branch.append(branch_element)
connected = {e for e in ifcopenshell.util.system.get_connected_to(element) if e not in processed_elements}
connected.update(
[e for e in ifcopenshell.util.system.get_connected_from(element) if e not in processed_elements]
)
if len(connected) == 1:
extend_branch(list(connected)[0], branch, element)
else:
for connected_element in connected:
branch_element["children"].append(extend_branch(connected_element, [], element))
return branch
queue = extend_branch(current_element, [])[0]["children"]
# import pprint
# pprint.pprint(queue)
def process_branch(branch):
for branch_element in branch:
element = branch_element["element"]
print('processing', element)
predecessor = branch_element["predecessor"]
if False: # If the element does not need to be transformed, return early.
return
# Perform the extend, translate, rotate, etc the element as necessary based on the predecessor.
# For segments, prioritise extensions instead of translations.
# For everything else, only translate. No rotation.
for child_branch in branch_element["children"]:
process_branch(child_branch)
for branch in queue:
process_branch(branch)
class FitFlowSegments(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.fit_flow_segments"
bl_description = "Add a fitting based on currently selected elements and cursor"