fix(linetype): render dotted and dash-dot patterns (#149)
A dot in an LTYPE pattern is a zero-length element. The pattern resolver encoded it as a tiny `0.01 * scale` world-length dash, which had two bad effects: it was sub-pixel at normal zoom so the dash LOD saw the pattern's smallest feature drop below one pixel and collapsed the whole line to solid, and at larger LTSCALE it left only invisible sub-pixel dots between big gaps. Either way dotted and dash-dot linetypes were never visible; only plain dashed (no zero elements) worked. Keep dots as literal 0.0 so they no longer drag `min_elem` down, and render each as a fixed ~1.5 px mark in the wire shader (pixel-snapped via world_per_pixel, mirroring the hatch shader's dot handling). The shader tells a real dot from trailing array padding by element count — the index of the last non-zero element plus one — so no producer needs a sentinel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ce2365e8f9
commit
fcb97b12da
2 changed files with 39 additions and 14 deletions
|
|
@ -889,17 +889,22 @@ pub(crate) fn resolve_pattern(
|
|||
return solid;
|
||||
}
|
||||
|
||||
// Keep dots (element length exactly 0) as 0.0 so the shader can render
|
||||
// them as a fixed ~1 px mark; trailing array slots stay 0.0 padding and
|
||||
// the shader tells the two apart by position (a 0.0 before the last
|
||||
// non-zero element is a dot, trailing 0.0s are padding). The old code
|
||||
// encoded dots as `0.01 * scale` — a tiny world-length dash that went
|
||||
// sub-pixel at normal zoom and dragged the pattern's `min_elem` below one
|
||||
// pixel, so the dash LOD collapsed dotted / dash-dot lines to solid (or,
|
||||
// at larger LTSCALE, left only invisible sub-pixel dots between big
|
||||
// gaps). (#149)
|
||||
let mut pat = [0.0f32; 8];
|
||||
let mut pat_len = 0.0f32;
|
||||
for (i, el) in lt.elements.iter().take(8).enumerate() {
|
||||
let raw = el.length as f32 * scale;
|
||||
let encoded = if raw == 0.0 {
|
||||
0.01 * scale.max(0.01)
|
||||
} else {
|
||||
raw
|
||||
};
|
||||
pat[i] = encoded;
|
||||
pat_len += encoded.abs();
|
||||
// positive = dash, negative = gap, exactly 0 = dot.
|
||||
let v = el.length as f32 * scale;
|
||||
pat[i] = v;
|
||||
pat_len += v.abs();
|
||||
}
|
||||
if pat_len < 1e-6 {
|
||||
return solid;
|
||||
|
|
|
|||
Loading…
Reference in a new issue