feat(mline): GPU-dash multiline elements with shared A-type alignment

MLINE dashed elements were fully CPU-expanded (apply_along) — one wire per
dash — to keep the parallel lines in phase. Move pure-dash elements onto the
GPU dash shader and end-align every element to the multiline's centre-line so
they share one interior phase.

- wire_distances now accumulates arc-length from the double-single (high+low)
  points, so the dash phase stays precise at UTM coordinates. f32-high-only
  deltas quantised ~0.1 there and drifted the parallel lines apart — the
  original reason MLINE dashes were CPU-side.
- New WireModel.dash_align_end carries a shared begin/end dash length. The
  shader uses it as align_end for every parallel element (the interior phase
  depends on align_end, not the wire's own length) while align_total stays the
  element's own length, so each still ends on a dash at its own endpoint.
- MLINE tessellation derives that length once from the centre-line, routes
  pure dash/space/dot elements to the GPU pattern and text-bearing elements to
  apply_along.
- apply_along gained an "A"-type mode (shared reference length): a solid
  begin/end dash and a phased interior, so its dashes — and embedded text —
  line up with the GPU-dashed sibling elements instead of tiling from start.

Pure-dash MLINEs now cost one WireModel + pattern per element instead of N
segments; single (non-MLINE) entities keep the from-start tiling unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-17 02:59:11 +03:00
1 parent 743dc1026d
commit 5bd683cf4e
41 files changed
+263 -14

No files matched your search

+5
View File
@@ -1353,6 +1353,7 @@ fn tessellate_dimension_inner(
if !ext1.is_empty() {
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: ext1,
@@ -1376,6 +1377,7 @@ fn tessellate_dimension_inner(
if !ext2.is_empty() {
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: ext2,
@@ -1399,6 +1401,7 @@ fn tessellate_dimension_inner(
} else {
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: geom.ext_lines,
@@ -1423,6 +1426,7 @@ fn tessellate_dimension_inner(
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: geom.dim_lines,
@@ -1463,6 +1467,7 @@ fn tessellate_dimension_inner(
};
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: vec![],
+2
View File
@@ -590,6 +590,7 @@ impl LeaderTess for Leader {
if verts.len() < 2 {
return WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name,
points: vec![],
@@ -693,6 +694,7 @@ impl LeaderTess for Leader {
WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name,
points,
+4
View File
@@ -1400,6 +1400,7 @@ impl MultiLeaderTess for MultiLeader {
let mut wires: Vec<WireModel> = Vec::new();
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points,
@@ -1684,6 +1685,7 @@ impl MultiLeaderTess for MultiLeader {
}
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: sdf_verts,
name: name.clone(),
points: vec![],
@@ -1748,6 +1750,7 @@ impl MultiLeaderTess for MultiLeader {
];
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points: vec![],
@@ -1780,6 +1783,7 @@ impl MultiLeaderTess for MultiLeader {
];
wires.push(WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name,
points: frame_points,
+1
View File
@@ -749,6 +749,7 @@ pub fn tessellate_table(
|color: [f32; 4], points: Vec<[f32; 3]>, fill_tris: Vec<[f32; 3]>, lw: f32| -> WireModel {
WireModel {
dash_from_start: false,
dash_align_end: None,
text_verts: Vec::new(),
name: name.clone(),
points,