fix(wipeout): use real clip vertices, correct image-pixel→WCS mapping
acadrust's DWG reader read the wipeout/raster-image clip boundary points only to advance the bit cursor and then discarded them, so every wipeout fell back to `Wipeout::new()`'s default placeholder rectangle (`-0.5..0.5`). For files that store the real polygon mask in clip vertices (anteen.dwg's `DIMBLOCK` style: u_vector ≈ 643k, size = (1, 1), clip polygon ~0.0016×0.0033 in pixel space), the wipeout rendered at the full image bbox — hundreds of thousands of units wide — instead of the intended ~1000×2000 mask. Pinned to the new `fix/wipeout-clip-vertices` acadrust branch (carries the upstream parser fix). On the H7CAD side, the polygon mapping now follows the DXF convention: x_off = (clip.x + size.x/2) × u_vec y_off = (size.y/2 − clip.y) × v_vec (image-Y points down) …in `wipeout_boundary_2d` (fill), `Wipeout::to_truck` (border line), and `Wipeout::grips` (vertex handles) so all three stay in sync. The fill path also explicitly closes the polygon loop — without it the GPU `in_polygon` ray-cast skipped the v(n-1)→v(0) edge and the solid mask bled far past the boundary. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
2357b39a1d
commit
8e6491d4a8
4 changed files with 49 additions and 25 deletions
|
|
@ -2744,16 +2744,35 @@ impl Scene {
|
|||
if is_polygon {
|
||||
let ox = (wo.insertion_point.x - wox) as f32;
|
||||
let oy = (wo.insertion_point.y - woy) as f32;
|
||||
wo.clip_boundary_vertices
|
||||
// DXF clip vertices live in image-pixel space, centred on the
|
||||
// image (range −size/2 … +size/2). Image-bottom-left → insertion,
|
||||
// image-y-axis points DOWN (per the DXF "v_vector points down the
|
||||
// image" convention), so map:
|
||||
// x_off = (clip.x + size.x/2) × u_vec
|
||||
// y_off = (size.y/2 − clip.y) × v_vec ← y flipped
|
||||
let cx_of = |v: &acadrust::types::Vector2| v.x + wo.size.x * 0.5;
|
||||
let cy_of = |v: &acadrust::types::Vector2| wo.size.y * 0.5 - v.y;
|
||||
let mut poly: Vec<[f32; 2]> = wo
|
||||
.clip_boundary_vertices
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let wx =
|
||||
(wo.u_vector.x * v.x * wo.size.x + wo.v_vector.x * v.y * wo.size.y) as f32;
|
||||
let wy =
|
||||
(wo.u_vector.y * v.x * wo.size.x + wo.v_vector.y * v.y * wo.size.y) as f32;
|
||||
let cx = cx_of(v);
|
||||
let cy = cy_of(v);
|
||||
let wx = (wo.u_vector.x * cx + wo.v_vector.x * cy) as f32;
|
||||
let wy = (wo.u_vector.y * cx + wo.v_vector.y * cy) as f32;
|
||||
[ox + wx, oy + wy]
|
||||
})
|
||||
.collect()
|
||||
.collect();
|
||||
// Close the loop: the GPU `in_polygon` ray-cast walks
|
||||
// sequential pairs and doesn't wrap, so without an explicit
|
||||
// closing vertex the last edge (vN-1 → v0) is never tested and
|
||||
// the fill bleeds far past the boundary.
|
||||
if let Some(&first) = poly.first() {
|
||||
if poly.last() != Some(&first) {
|
||||
poly.push(first);
|
||||
}
|
||||
}
|
||||
poly
|
||||
} else {
|
||||
// Rectangular boundary from 4 corners.
|
||||
let ox = (wo.insertion_point.x - wox) as f32;
|
||||
|
|
|
|||
Loading…
Reference in a new issue