feat(polyline): smooth per-segment taper for varying-width wide polylines
A wide polyline with per-vertex varying widths rendered at its widest edge (uniform-width ones were already exact). Draw the true taper instead. `WireModel.taper_widths` carries a per-point full band width. The wire instance (native slim + web fat) gains per-endpoint `world_hw_a/b`, and both wire shaders interpolate `mix(hw_a, hw_b, which_end)` so each segment's band narrows/widens linearly — depth-tested, and the linetype dash still applies. Alignment (widths must match the tessellated points) is solved by building both together: a new `TruckObject::TaperedLines(points, widths)`, filled by `common::tapered_band_points` (straight = endpoints, arc = 16 samples with the width lerped along it). to_truck routes a varying-width polyline here — LwPolyline before the PLINEGEN split, Polyline2D at its return — while a uniform-width one keeps the constant-band Contour path unchanged. `world_width` stays the widest edge as the PDF-stroke + zoom-floor fallback. Blocks fall back to the constant-widest band (`LocalWire` carries no taper_widths). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a8aece1909
commit
b3016ca892
48 changed files with 322 additions and 7 deletions
|
|
@ -326,9 +326,22 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
|||
}
|
||||
|
||||
let (fill_origin, fills) = wide_fills(pl);
|
||||
// A wide Polyline2D whose per-vertex widths VARY renders a smooth taper; a
|
||||
// uniform-width one keeps the constant-band Contour.
|
||||
let object = match tapered_band_verts_2d(pl) {
|
||||
Some(band_verts) => {
|
||||
let (pts, widths) = crate::entities::common::tapered_band_points(
|
||||
&band_verts,
|
||||
pl.is_closed(),
|
||||
&to_wcs,
|
||||
);
|
||||
TruckObject::TaperedLines(pts, widths)
|
||||
}
|
||||
None => TruckObject::Contour(edges.into_iter().collect::<Wire>()),
|
||||
};
|
||||
TruckEntity {
|
||||
pick_tris: crate::entities::common::wide_band_tris(fill_origin, &fills),
|
||||
object: TruckObject::Contour(edges.into_iter().collect::<Wire>()),
|
||||
object,
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
|
|
@ -336,6 +349,32 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
|||
}
|
||||
}
|
||||
|
||||
/// Per-vertex `(location, bulge, start_width, end_width)` band description for a
|
||||
/// wide Polyline2D whose width VARIES — `None` when the width is uniform.
|
||||
fn tapered_band_verts_2d(
|
||||
pl: &acadrust::entities::Polyline2D,
|
||||
) -> Option<Vec<([f64; 2], f64, f64, f64)>> {
|
||||
let d = pl.start_width.max(pl.end_width);
|
||||
let band: Vec<([f64; 2], f64, f64, f64)> = pl
|
||||
.vertices
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let sw = if v.start_width > 1e-9 { v.start_width } else { d };
|
||||
let ew = if v.end_width > 1e-9 { v.end_width } else { d };
|
||||
([v.location.x, v.location.y], v.bulge, sw, ew)
|
||||
})
|
||||
.collect();
|
||||
let w0 = band.first().map_or(0.0, |v| v.2);
|
||||
let varies = band
|
||||
.iter()
|
||||
.any(|&(_, _, sw, ew)| (sw - w0).abs() > 1e-9 || (ew - w0).abs() > 1e-9);
|
||||
if varies && w0.max(band.iter().map(|v| v.3).fold(0.0, f64::max)) > 1e-9 {
|
||||
Some(band)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Polyline2D {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(tessellate_polyline2d(self))
|
||||
|
|
|
|||
Loading…
Reference in a new issue