fix(polyline): render fill mode boundaries

Use kernel-produced band outlines when FILLMODE is off. Preserve centerline linetype stations through inserts, clipping, projection, and PDF export.
This commit is contained in:
Hakan Seven committed 2026-08-24 22:18:44 +03:00
commit 4209c35ba3
60 files changed
+1620 -575

No files matched your search

+58 -4
View File
@@ -246,8 +246,17 @@ impl Scene {
continue;
}
let clipped =
clip_polyline_to_rect(&projected_pts, vp_x0, vp_y0, vp_x1, vp_y1, pcz);
let stationed = wire.pattern_stations.len() > wire.points.len();
let source_length = stationed.then(|| wire.pattern_stations[wire.points.len()]);
let (clipped, mut clipped_stations) = clip_polyline_to_rect(
&projected_pts,
stationed.then_some(&wire.pattern_stations[..wire.points.len()]),
vp_x0,
vp_y0,
vp_x1,
vp_y1,
pcz,
);
if clipped.is_empty() && projected_text.is_empty() {
continue;
}
@@ -312,6 +321,15 @@ impl Scene {
}
let mut out = wire.clone();
out.points = clipped;
if let Some(source_length) = source_length {
for station in &mut clipped_stations {
*station *= scale;
}
clipped_stations.push(source_length * scale);
out.pattern_stations = clipped_stations;
} else {
out.pattern_stations.clear();
}
out.text_verts = projected_text;
// Paper coordinates are small sheet units — no relative-to-eye
// residual is needed, and keeping the model wire's points_low
@@ -980,14 +998,16 @@ fn cs_clip(
/// Returns a new points vec with proper NaN separators at clip boundaries.
fn clip_polyline_to_rect(
pts: &[[f32; 3]],
stations: Option<&[f32]>,
xmin: f32,
ymin: f32,
xmax: f32,
ymax: f32,
z: f32,
) -> Vec<[f32; 3]> {
) -> (Vec<[f32; 3]>, Vec<f32>) {
const NAN3: [f32; 3] = [f32::NAN, f32::NAN, f32::NAN];
let mut result: Vec<[f32; 3]> = Vec::new();
let mut result_stations = Vec::new();
let mut i = 0;
while i < pts.len() {
@@ -1016,19 +1036,50 @@ fn clip_polyline_to_rect(
pen_down = false;
}
Some((cx0, cy0, cx1, cy1)) => {
let parameter = |x: f32, y: f32| {
let dx = x1 - x0;
let dy = y1 - y0;
if dx.abs() >= dy.abs() && dx.abs() > 1e-12 {
(x - x0) / dx
} else if dy.abs() > 1e-12 {
(y - y0) / dy
} else {
0.0
}
};
let station = |t: f32| {
stations.map_or(0.0, |values| {
let start_station = values[start + j];
start_station
+ (values[start + j + 1] - start_station) * t
})
};
if !pen_down {
if !result.is_empty() {
result.push(NAN3);
if stations.is_some() {
result_stations.push(0.0);
}
}
result.push([cx0, cy0, z]);
if stations.is_some() {
result_stations.push(station(parameter(cx0, cy0)));
}
pen_down = true;
} else if let Some(&[lx, ly, _]) = result.last() {
if (lx - cx0).abs() > 1e-4 || (ly - cy0).abs() > 1e-4 {
result.push(NAN3);
result.push([cx0, cy0, z]);
if stations.is_some() {
result_stations.push(0.0);
result_stations.push(station(parameter(cx0, cy0)));
}
}
}
result.push([cx1, cy1, z]);
if stations.is_some() {
result_stations.push(station(parameter(cx1, cy1)));
}
// If the exit point was clipped, lift pen.
if (cx1 - x1).abs() > 1e-4 || (cy1 - y1).abs() > 1e-4 {
pen_down = false;
@@ -1044,6 +1095,9 @@ fn clip_polyline_to_rect(
.unwrap_or(false)
{
result.pop();
if stations.is_some() {
result_stations.pop();
}
}
result
(result, result_stations)
}