Skip to content

Commit 402b3f5

Browse files
committed
Fix ElevationDecorator arrow direction in drawing camera views
The elevation tag's local -Z axis is intentionally parallel to its drawing camera's view direction, making screen-space projection of that axis always degenerate (zero XY delta). Fall through to the tag's local +X axis, which lies in the camera plane and rotates correctly as the user adjusts the tag's orientation. Also fix a zero-length vector crash in svgwriter when the same degenerate case occurs during SVG export.
1 parent 3f67620 commit 402b3f5

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

src/bonsai/bonsai/bim/module/drawing/decoration.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,20 @@ def decorate(self, context, obj):
14971497
"output_edges": output_edges,
14981498
}
14991499

1500+
# Determine the arrow direction in camera-image-plane (XY) space.
1501+
# The elevation tag's local -Z is intentionally parallel to the drawing
1502+
# camera's view direction, so projecting it always gives a near-zero XY
1503+
# delta. Fall through to local +X (which is perpendicular to the view
1504+
# and rotates visibly when the user spins the tag).
1505+
view_mat = context.region_data.view_matrix
1506+
edge_dir_2d = Vector((1.0, 0.0)) # final fallback
1507+
for local_axis in (Vector((0, 0, -1)), Vector((1, 0, 0)), Vector((0, 1, 0))):
1508+
world_axis = obj.matrix_world.to_3x3() @ local_axis
1509+
cam_xy = (view_mat.to_3x3() @ world_axis).xy
1510+
if cam_xy.length > 1e-6:
1511+
edge_dir_2d = cam_xy.normalized()
1512+
break
1513+
15001514
# process edges
15011515
for edge in edges_original:
15021516
v0, v1 = winspace_verts[edge[0]], winspace_verts[edge[1]]
@@ -1505,7 +1519,7 @@ def decorate(self, context, obj):
15051519
circle_head = get_circle_head(circle_size)
15061520
start_i = add_verts_sequence(add_offsets(v0, circle_head), start_i, **out_kwargs, closed=True)
15071521

1508-
edge_dir = (v1 - v0).normalized()
1522+
edge_dir = edge_dir_2d.to_3d()
15091523
side = (edge_dir.yx * Vector((1, -1))).to_3d()
15101524
triangle_head = get_triangle_head(side, edge_dir, triangle_length, triangle_width)
15111525
start_i = add_verts_sequence(add_offsets(v0, triangle_head), start_i, **out_kwargs, closed=True)

src/bonsai/bonsai/bim/module/drawing/svgwriter.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,11 @@ def draw_elevation_annotation(self, obj: bpy.types.Object) -> None:
872872

873873
v1 = self.project_point_onto_camera(obj.matrix_world @ Vector((0, 0, 0)))
874874
v2 = self.project_point_onto_camera(obj.matrix_world @ Vector((0, 0, -1)))
875-
angle = -math.degrees((v2 - v1).xy.angle_signed(Vector((0, 1))))
875+
delta = (v2 - v1).xy
876+
if delta.length <= 1e-6:
877+
v2 = self.project_point_onto_camera(obj.matrix_world @ Vector((1, 0, 0)))
878+
delta = (v2 - v1).xy
879+
angle = -math.degrees(delta.angle_signed(Vector((0, 1)))) if delta.length > 1e-6 else 90.0
876880

877881
transform = "rotate({}, {}, {})".format(angle, *symbol_position_svg.xy)
878882

0 commit comments

Comments
 (0)