mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-10 12:30:16 -06:00
* Hit tests don't lay out dashes: moving the mouse over a block stays smooth (#1285) Every mouse move hit-tests the block references under the cursor, and hit_polylines built them with a full-detail display list, one primitive per dash. A fine pattern on long lines in a block inserted at 0.001 made millions of dashes per move. Options::linetypes off draws every line whole and continuous, and hit_polylines uses it for blocks, dimensions and multileaders. A dashed line in a block is now hit across its gaps, as one outside a block already was. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * render: with linetypes off, a lightweight polyline is one continuous stroke Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Steffen <camperking@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
74 lines
2.7 KiB
Rust
74 lines
2.7 KiB
Rust
//! Multilines: each element in its style colour and linetype (ByLayer and ByBlock elements
|
|
//! follow the multiline's own), caps and joints in the multiline's properties, and the fill.
|
|
|
|
use super::{Builder, Ctx, Ink, fill, ink, linetype, resolve_common};
|
|
use cadcraft_color::Color;
|
|
use cadcraft_doc::{Entity, MLine};
|
|
use cadcraft_geom::Vec2;
|
|
|
|
pub(super) fn draw(b: &mut Builder, ctx: &Ctx, e: &Entity, m: &MLine, rgb: Ink, lw: f32, tol: f64) {
|
|
let g = m.geometry();
|
|
if let Some(fc) = m.def.fill
|
|
&& b.opts.fill
|
|
&& !g.fill.is_empty()
|
|
{
|
|
let c = match fc {
|
|
Color::ByLayer | Color::ByBlock => rgb,
|
|
c => ink(c, Color::Index(7), ctx.block_color),
|
|
};
|
|
b.tris(ctx, c, &fill::triangulate_evenodd(&g.fill));
|
|
}
|
|
let min = b.opts.min_dash / ctx.xf.scale_factor().max(1e-12);
|
|
// One look per element: colour, lineweight, linetype and its scale.
|
|
let looks: Vec<_> = m
|
|
.def
|
|
.elements
|
|
.iter()
|
|
.map(|el| {
|
|
let mut c = e.common.clone();
|
|
if !matches!(el.color, Color::ByLayer | Color::ByBlock) {
|
|
c.color = el.color;
|
|
}
|
|
let lt = el.linetype.trim();
|
|
if !lt.is_empty() && !lt.eq_ignore_ascii_case("bylayer") && !lt.eq_ignore_ascii_case("byblock") {
|
|
c.linetype = lt.to_string();
|
|
}
|
|
let (rgb, w, lt, scale, _, _) = resolve_common(ctx, &c, b.plotting);
|
|
let lt = match b.styles.and_then(|s| s.linetype(rgb, b.named)) {
|
|
Some(over) => over,
|
|
None => lt,
|
|
};
|
|
(rgb, if b.opts.lineweights { w } else { 0.0 }, lt, scale)
|
|
})
|
|
.collect();
|
|
for (i, a, z) in &g.lines {
|
|
let Some((rgb, w, lt, scale)) = looks.get(*i) else { continue };
|
|
stroke(b, ctx, *rgb, *w, lt.as_ref(), *scale, min, &[*a, *z]);
|
|
}
|
|
let own = resolve_common(ctx, &e.common, b.plotting);
|
|
let lt = match b.styles.and_then(|s| s.linetype(rgb, b.named)) {
|
|
Some(over) => over,
|
|
None => own.2,
|
|
};
|
|
for s in &g.caps {
|
|
let mut pts = Vec::new();
|
|
s.tessellate(tol, &mut pts);
|
|
stroke(b, ctx, rgb, lw, lt.as_ref(), own.3, min, &pts);
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn stroke(b: &mut Builder, ctx: &Ctx, rgb: Ink, lw: f32, lt: Option<&cadcraft_doc::Linetype>, scale: f64, min: f64, pts: &[Vec2]) {
|
|
match lt.filter(|_| b.opts.linetypes) {
|
|
Some(lt) => {
|
|
for dash in linetype::apply(pts, lt, scale, min) {
|
|
match dash.as_slice() {
|
|
[p] => b.point(ctx, rgb, *p),
|
|
_ => b.polyline(ctx, rgb, lw, &dash),
|
|
}
|
|
}
|
|
}
|
|
None => b.polyline(ctx, rgb, lw, pts),
|
|
}
|
|
}
|