From 6c993ba91915675ce82e8c3a2f7493e794d1edbb Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Tue, 7 Apr 2026 13:28:08 -0500 Subject: [PATCH] Fix depth check to use camera direction instead of face normal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same-plane check projected vertices onto the dominant face normal (n_a) to determine if two elements span the same depth range. This correctly rejected slabs stacked along their normal axis but broke for elements whose largest face is perpendicular to the camera (e.g. X-normal boxes in plan view) — projection onto X produces zero overlap for legitimate side-by-side pairs. Replace n_a projection with projection onto _cam_look. Elements at the same camera depth produce overlapping ranges and are joined; elements separated in camera depth produce disjoint ranges and are correctly rejected regardless of the orientation of their faces. Generated with the assistance of an AI coding tool. --- .../bonsai/bim/module/drawing/operator.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 73701f889f..d190734290 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -1729,7 +1729,8 @@ class CreateDrawing(bpy.types.Operator): return False return True - if aabb_contains(corners_a, corners_b) or aabb_contains(corners_b, corners_a): + contained = aabb_contains(corners_a, corners_b) or aabb_contains(corners_b, corners_a) + if contained: adjacency_cache[key] = True return True # Coplanarity check: use the largest-face normal for each object. @@ -1750,13 +1751,15 @@ class CreateDrawing(bpy.types.Operator): if dot <= 1.0 - 3.8e-5: # ~0.5° tolerance adjacency_cache[key] = False return False - # Normals are parallel — also verify the elements share a face plane. - # Project all vertices onto n_a to get the 1-D depth range of each - # element along the normal axis. Side-by-side elements span the same - # depth range (overlap > tol). Elements stacked end-to-end only touch - # at a single interface point (overlap ≈ 0) and must not be joined. - projs_a = [v.dot(n_a) for v in verts_a] - projs_b = [v.dot(n_a) for v in verts_b] + # Check whether both elements are at the same depth relative to the + # camera. Project vertices onto the camera look direction: elements + # at the same camera depth have overlapping ranges; depth-stacked + # elements (one in front of the other) have separated ranges. + # Using the camera direction rather than n_a is critical — n_a may + # be perpendicular to the camera (e.g. X-normal boxes in plan view) + # which would produce zero overlap for legitimate side-by-side pairs. + projs_a = [v.dot(_cam_look) for v in verts_a] + projs_b = [v.dot(_cam_look) for v in verts_b] range_a = (min(projs_a), max(projs_a)) range_b = (min(projs_b), max(projs_b)) overlap = min(range_a[1], range_b[1]) - max(range_a[0], range_b[0])