fix(plot): scale wide polyline band width into paper units through viewports

`viewport_content_wires` projects model-space wires into paper coordinates
for plotting: the points and the linetype stations are multiplied by the
viewport scale, but `world_width` (the band width of a wide polyline) was
copied unchanged. The PDF / print exporter strokes that band at
`world_width` in paper millimetres, so a 15-unit-wide bus bar seen through
a 1:100 viewport came out as a ~21 mm black blob instead of 0.15 mm, and
every single-line diagram sheet plotted as solid black shapes.

Scale `world_width` by the viewport scale alongside the points, and keep
the per-point taper widths in step (or drop them when clipping changed the
vertex count, so they cannot misalign). Negative (fixed pixel) and zero
(lineweight) widths are left untouched.

Adds a regression test that plots a 15-unit-wide polyline through a 1:10
viewport and expects a 1.5-unit band in the projected plot wires.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Chris YehandClaude Opus 5 committed 2026-09-21 17:28:09 +08:00
1 parent fd2062bdec
commit 52d766b488
2 files changed
+76

No files matched your search

+16
View File
@@ -321,6 +321,22 @@ impl Scene {
}
let mut out = wire.clone();
out.points = clipped;
// A wide polyline's band width is a geometric width in model
// units; the points were just projected into paper units, so
// the band (and any per-point taper) must follow the same
// scale or the PDF / print exporter strokes a 15-unit bus bar
// as 15 mm of paper. Negative values are fixed pixel widths
// and zero means "use the lineweight" — both stay as they are.
if out.world_width > 0.0 {
out.world_width = wire.world_width * scale;
if wire.taper_widths.len() == out.points.len() {
out.taper_widths = wire.taper_widths.iter().map(|w| w * scale).collect();
} else {
// Clipping changed the vertex count, so the per-point
// widths no longer line up; fall back to a constant band.
out.taper_widths.clear();
}
}
if let Some(source_length) = source_length {
for station in &mut clipped_stations {
*station *= scale;