system decorations to show flow direction

This commit is contained in:
Andrej730
2023-09-26 11:44:46 +05:00
parent 779fc35228
commit e975eac4a7
2 changed files with 76 additions and 3 deletions
@@ -111,10 +111,12 @@ class SystemDecorator:
roof_angle_edges = []
preview_edges = []
# NOTE: using .data here doesn't allow having live viewport orientation for the calculations
# but not using .data seems to be performance heavy
if not SystemDecorationData.is_loaded:
SystemDecorationData.load()
decoration_data = SystemDecorationData.data["decoration_data"]
all_vertices = decoration_data["all_vertices"]
preview_edges = decoration_data["preview_edges"]
special_vertices = decoration_data["special_vertices"]
+73 -2
View File
@@ -22,6 +22,7 @@ import blenderbim.core.tool
import blenderbim.tool as tool
from blenderbim.bim import import_ifc
import re
from math import pi, cos, sin
from mathutils import Matrix, Vector
@@ -191,6 +192,15 @@ class System(blenderbim.core.tool.System):
selected_edges = []
selected_vertices = []
view3d_space = tool.Blender.get_viewport_context()["space_data"].region_3d
viewport_matrix = view3d_space.view_matrix.inverted()
viewport_y_axis = viewport_matrix.col[1].to_3d().normalized()
camera_pos = viewport_matrix.translation
dir_to_camera = lambda x: (camera_pos - x).normalized()
def most_aligned_vector(a, vectors):
return max(vectors, key=lambda v: abs(a.dot(v)))
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
start_vert_i = 0
@@ -216,15 +226,76 @@ class System(blenderbim.core.tool.System):
if not cls.is_mep_element(element):
continue
selected_element = element in selected_elements
ports = tool.System.get_ports(element)
verts_pos = []
for port in ports:
position = tool.Model.get_element_matrix(port).translation * si_conversion
all_vertices.append(position)
verts_pos.append(position)
verts = range(start_vert_i, start_vert_i + len(ports))
edges = [(i, i + 1) for i in range(start_vert_i, start_vert_i + len(ports) - 1)]
if element in selected_elements:
def get_flow_direction(ports):
# diagram - https://i.imgur.com/ioYL7bZ.png
flow_dirs = [p.FlowDirection for p in ports]
unique = set(flow_dirs)
if len(unique) == 1:
return 0
elif flow_dirs[0] == "SOURCE":
return -1
elif flow_dirs[0] == "SINK":
return 1
elif flow_dirs[1] == "SOURCE":
return 1
elif flow_dirs[1] == "SINK":
return -1
return 0
if len(ports) == 2 and selected_element and (flow_direction := get_flow_direction(ports)):
edge_verts = verts_pos.copy()
edge_verts = edge_verts[::flow_direction]
# create direction lines
direction_lines_offset = 0.4
direction_lines_width = 0.05
base_vert = edge_verts[0]
edge = edge_verts[1] - edge_verts[0]
edge_length = edge.length
edge_dir = edge.normalized()
# edge_ortho = most_aligned_vector(
# viewport_y_axis, (
# obj.matrix_world.col[0].to_3d().normalized(),
# obj.matrix_world.col[1].to_3d().normalized(),
# ))
# for now it's hardcoded to local Y axis to avoid using viewport data
# for performance reasons
edge_ortho = obj.matrix_world.col[1].to_3d().normalized()
second_ortho = edge_dir.cross(edge_ortho)
edge_ortho = second_ortho.cross(edge_dir)
# direction lines should be around the edge center
n_direction_lines, start_offset = divmod(edge_length, direction_lines_offset)
n_direction_lines = int(n_direction_lines) + 1
start_offset /= 2
start_offset = edge_dir * start_offset + base_vert
cur_vert_index = start_vert_i + len(ports)
for i in range(n_direction_lines):
cur_offset = start_offset + edge_dir * i * direction_lines_offset
arrow_base = cur_offset - edge_dir * direction_lines_width
verts_pos.append(arrow_base + edge_ortho * direction_lines_width)
verts_pos.append(cur_offset)
verts_pos.append(arrow_base - edge_ortho * direction_lines_width)
edges.append((cur_vert_index, cur_vert_index + 1))
edges.append((cur_vert_index + 1, cur_vert_index + 2))
cur_vert_index += 3
all_vertices.extend(verts_pos)
if selected_element:
selected_vertices.extend(verts)
selected_edges.extend(edges)
else: