fix(dimension): custom arrow blocks keep their polyline width

The width of a wide polyline lives on the wire as a GPU band, which the
custom-arrow extraction dropped, so the arrow drew as a hairline.

Fixes #1130

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-28 18:49:26 +03:00
1 parent a94d1cfd17
commit 805979ea36
1 file changed
+49 -6
+49 -6
View File
@@ -2658,12 +2658,19 @@ fn append_custom_arrow_leaf(
true,
);
for wire in wires {
append_custom_wire_points(
&wire.points,
&wire.points_low,
codec::types::Vector3::ZERO,
lines,
);
// A wide polyline's width rides on the wire as a GPU band; an arrow
// keeps only geometry, so turn the band into fill or it draws hairline.
// (#1130)
if wire.world_width > 0.0 || wire.taper_widths.iter().any(|width| *width > 0.0) {
append_custom_band(&wire, fill);
} else {
append_custom_wire_points(
&wire.points,
&wire.points_low,
codec::types::Vector3::ZERO,
lines,
);
}
append_custom_fill_points(
&wire.fill_tris,
&wire.fill_tris_low,
@@ -2760,6 +2767,42 @@ fn append_custom_hatch_geometry(
);
}
/// Triangles covering a wide polyline's band, one quad per segment.
// ponytail: no join wedges at corners; add miters if a thick arrow shows notches.
fn append_custom_band(wire: &WireModel, fill: &mut Vec<[f32; 3]>) {
let at = |index: usize| {
let point = wire.points[index];
let low = wire.points_low.get(index).copied().unwrap_or([0.0; 3]);
(!point[0].is_nan()).then(|| {
[
point[0] as f64 + low[0] as f64,
point[1] as f64 + low[1] as f64,
point[2] as f64 + low[2] as f64,
]
})
};
let half = |index: usize| {
wire.taper_widths.get(index).copied().unwrap_or(wire.world_width).max(0.0) as f64 * 0.5
};
for index in 0..wire.points.len().saturating_sub(1) {
let (Some(a), Some(b)) = (at(index), at(index + 1)) else {
continue;
};
let (dx, dy) = (b[0] - a[0], b[1] - a[1]);
let length = dx.hypot(dy);
if length <= 0.0 {
continue;
}
let (nx, ny) = (-dy / length, dx / length);
let (ha, hb) = (half(index), half(index + 1));
let corner = |p: [f64; 3], h: f64, side: f64| {
[(p[0] + nx * h * side) as f32, (p[1] + ny * h * side) as f32, p[2] as f32]
};
let quad = [corner(a, ha, 1.0), corner(a, ha, -1.0), corner(b, hb, -1.0), corner(b, hb, 1.0)];
fill.extend([quad[0], quad[1], quad[2], quad[0], quad[2], quad[3]]);
}
}
fn append_custom_wire_points(
points: &[[f32; 3]],
points_low: &[[f32; 3]],