feat(xclip): draw the clip boundary frame when XCLIPFRAME is on
Clipped INSERTs cut their content correctly but never showed the boundary itself. When the header XCLIPFRAME is 1 or 2 (visible), a closed ring over the world-space clip polygon now rides the insert's resolved colour and line weight. The frame is deliberately not clipped — it is the boundary — and carries no snap points. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0a3862c54b
commit
f407835543
2 changed files with 59 additions and 0 deletions
|
|
@ -1052,6 +1052,17 @@ pub(crate) fn tessellate_entity(
|
||||||
if let Some(sf) = pick::xclip::insert_spatial_filter(document, ins) {
|
if let Some(sf) = pick::xclip::insert_spatial_filter(document, ins) {
|
||||||
let poly = pick::xclip::world_clip_polygon_f64(sf, ins);
|
let poly = pick::xclip::world_clip_polygon_f64(sf, ins);
|
||||||
pick::xclip::clip_wires(&mut wires, &poly);
|
pick::xclip::clip_wires(&mut wires, &poly);
|
||||||
|
// XCLIPFRAME 1/2 shows the boundary itself on screen
|
||||||
|
// (2 = shown but not plotted).
|
||||||
|
if document.header.xclip_frame != 0 && poly.len() >= 3 {
|
||||||
|
wires.push(pick::xclip::frame_wire(
|
||||||
|
&poly,
|
||||||
|
format!("{}_xclipframe", h.value()),
|
||||||
|
ins_color,
|
||||||
|
sel,
|
||||||
|
ins_lw_px,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-INSERT attribute values. The block defn carries the
|
// Per-INSERT attribute values. The block defn carries the
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,54 @@ fn split_ds(v: f64) -> (f32, f32) {
|
||||||
(high, (v - high as f64) as f32)
|
(high, (v - high as f64) as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build the visible clip-boundary frame (XCLIPFRAME 1/2) as a closed ring
|
||||||
|
/// over the world-space boundary polygon. The frame is display chrome for the
|
||||||
|
/// clipped INSERT: it rides the insert's resolved colour / line weight and is
|
||||||
|
/// deliberately NOT clipped — it *is* the boundary.
|
||||||
|
pub fn frame_wire(
|
||||||
|
poly: &[[f64; 2]],
|
||||||
|
name: String,
|
||||||
|
color: [f32; 4],
|
||||||
|
selected: bool,
|
||||||
|
line_weight_px: f32,
|
||||||
|
) -> WireModel {
|
||||||
|
let mut hi = Vec::with_capacity(poly.len() + 1);
|
||||||
|
let mut lo = Vec::with_capacity(poly.len() + 1);
|
||||||
|
for &[x, y] in poly.iter().chain(std::iter::once(&poly[0])) {
|
||||||
|
let (hx, lx) = split_ds(x);
|
||||||
|
let (hy, ly) = split_ds(y);
|
||||||
|
hi.push([hx, hy, 0.0]);
|
||||||
|
lo.push([lx, ly, 0.0]);
|
||||||
|
}
|
||||||
|
WireModel {
|
||||||
|
taper_widths: Vec::new(),
|
||||||
|
world_width: 0.0,
|
||||||
|
depth_override: None,
|
||||||
|
fill_is_3d: false,
|
||||||
|
pick_tris: Vec::new(),
|
||||||
|
pick_tris_low: Vec::new(),
|
||||||
|
dash_from_start: false,
|
||||||
|
dash_align_end: None,
|
||||||
|
text_verts: Vec::new(),
|
||||||
|
name,
|
||||||
|
points: hi,
|
||||||
|
points_low: lo,
|
||||||
|
color,
|
||||||
|
selected,
|
||||||
|
aci: 0,
|
||||||
|
pattern_length: 0.0,
|
||||||
|
pattern: [0.0; 8],
|
||||||
|
line_weight_px,
|
||||||
|
snap_pts: vec![],
|
||||||
|
tangent_geoms: vec![],
|
||||||
|
key_vertices: vec![],
|
||||||
|
aabb: WireModel::UNBOUNDED_AABB,
|
||||||
|
plinegen: true,
|
||||||
|
fill_tris: vec![],
|
||||||
|
fill_tris_low: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Clip a hatch fill boundary to `poly`.
|
/// Clip a hatch fill boundary to `poly`.
|
||||||
///
|
///
|
||||||
/// `boundary` is a hatch's NaN-separated loops in f32 offsets from
|
/// `boundary` is a hatch's NaN-separated loops in f32 offsets from
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue