Deterministic plane-local basis derivation for arbitrary-normal section
planes (issue #243).
The cap renderer (Section2DOverlayRenderer) lifts 2D cut polygons back
to 3D using tangent + bitangent as the in-plane axes. The 2D cutter
(SectionCutter) projects 3D triangle-plane intersections to 2D using
the SAME pair. Without a single shared derivation the two ends would
disagree on the basis, the cap polygons would land off the cutting
plane, and the hatch pattern would visibly rotate as soon as the
basis changed (e.g. between renderer init and a re-derive). This module
is the single source of truth.
Convention:
• The renderer/world is Y-up. World-Y is the reference axis for every
normal except exactly ±Y, where the cross product vanishes and we
fall back to world-X. tangent is therefore horizontal and
bitangent never points downward, so a face-picked elevation comes
out upright (#2714).
• For the cardinal Y-axis plane (normal = [0,1,0]) the resulting
basis is tangent = [0,0,-1], bitangent = [1,0,0]. That matches
the cardinal-axis cap projection ('down' axis maps (x, z) → (2D.x, 2D.y) with z mirrored on flip), so face-picking a perfectly
horizontal floor reproduces the same hatch orientation as the
"Down" preset — verified by the unit tests in this file's neighbour.
Deterministic plane-local basis derivation for arbitrary-normal section planes (issue #243).
The cap renderer (
Section2DOverlayRenderer) lifts 2D cut polygons back to 3D usingtangent+bitangentas the in-plane axes. The 2D cutter (SectionCutter) projects 3D triangle-plane intersections to 2D using the SAME pair. Without a single shared derivation the two ends would disagree on the basis, the cap polygons would land off the cutting plane, and the hatch pattern would visibly rotate as soon as the basis changed (e.g. between renderer init and a re-derive). This module is the single source of truth.Convention: • The renderer/world is Y-up. World-Y is the reference axis for every normal except exactly ±Y, where the cross product vanishes and we fall back to world-X.
tangentis therefore horizontal andbitangentnever points downward, so a face-picked elevation comes out upright (#2714). • For the cardinal Y-axis plane (normal = [0,1,0]) the resulting basis istangent = [0,0,-1],bitangent = [1,0,0]. That matches the cardinal-axis cap projection ('down'axis maps(x, z) → (2D.x, 2D.y)with z mirrored on flip), so face-picking a perfectly horizontal floor reproduces the same hatch orientation as the "Down" preset — verified by the unit tests in this file's neighbour.