forked from 1b-agent/opencadstudio-upstream
fix(solid): keep SOLID fills placed on UTM-scale drawings
`solid_hatch_model` cast each corner from absolute WCS straight to f32 and left `world_origin` at [0, 0]. At UTM magnitudes (~1e6) f32's 24-bit mantissa resolves to ~0.06 units, so the quad snapped to a grid and the fill drifted off its own outline. Hold the corners in f64 until the AABB centre is known, then store each as a small f32 offset from it — the same precision-preserving anchor `hatch_model_from_dxf` already uses for real HATCH entities. All nine callers feed through this one function, and every reader of `boundary` already adds `world_origin` back, so they go from adding zero to adding the real anchor. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
c10e8dae44
commit
ca253c2777
1 file changed
+37
-18
+37
-18
@@ -1740,24 +1740,43 @@ impl Scene {
|
||||
/// DXF SOLID corners are in "Z-order": p0-p1 top, p2-p3 bottom.
|
||||
/// Visual quad is p0→p1→p3→p2 (closed).
|
||||
pub(super) fn solid_hatch_model(solid: &DxfSolid, color: [f32; 4]) -> HatchModel {
|
||||
let boundary = vec![
|
||||
[
|
||||
(solid.first_corner.x) as f32,
|
||||
(solid.first_corner.y) as f32,
|
||||
],
|
||||
[
|
||||
(solid.second_corner.x) as f32,
|
||||
(solid.second_corner.y) as f32,
|
||||
],
|
||||
[
|
||||
(solid.fourth_corner.x) as f32,
|
||||
(solid.fourth_corner.y) as f32,
|
||||
],
|
||||
[
|
||||
(solid.third_corner.x) as f32,
|
||||
(solid.third_corner.y) as f32,
|
||||
],
|
||||
// Keep the corners in f64 until the AABB centre is known, then store
|
||||
// each as a small f32 offset from it — same precision-preserving anchor
|
||||
// `hatch_model_from_dxf` uses. Casting the absolute WCS corner straight
|
||||
// to f32 costs ~0.06 units of resolution at UTM magnitudes (~1e6), so
|
||||
// the quad snapped to a grid and the fill drifted off its outline.
|
||||
let corners: [[f64; 2]; 4] = [
|
||||
[solid.first_corner.x, solid.first_corner.y],
|
||||
[solid.second_corner.x, solid.second_corner.y],
|
||||
[solid.fourth_corner.x, solid.fourth_corner.y],
|
||||
[solid.third_corner.x, solid.third_corner.y],
|
||||
];
|
||||
let mut min = [f64::INFINITY; 2];
|
||||
let mut max = [f64::NEG_INFINITY; 2];
|
||||
for c in &corners {
|
||||
for i in 0..2 {
|
||||
if c[i] < min[i] {
|
||||
min[i] = c[i];
|
||||
}
|
||||
if c[i] > max[i] {
|
||||
max[i] = c[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
let world_origin = if min[0].is_finite() && min[1].is_finite() {
|
||||
[(min[0] + max[0]) * 0.5, (min[1] + max[1]) * 0.5]
|
||||
} else {
|
||||
[0.0, 0.0]
|
||||
};
|
||||
let boundary = corners
|
||||
.iter()
|
||||
.map(|c| {
|
||||
[
|
||||
(c[0] - world_origin[0]) as f32,
|
||||
(c[1] - world_origin[1]) as f32,
|
||||
]
|
||||
})
|
||||
.collect();
|
||||
HatchModel {
|
||||
boundary: std::sync::Arc::new(boundary),
|
||||
boundary_wcs: None,
|
||||
@@ -1766,7 +1785,7 @@ impl Scene {
|
||||
color,
|
||||
angle_offset: 0.0,
|
||||
scale: 1.0,
|
||||
world_origin: [0.0; 2],
|
||||
world_origin,
|
||||
vp_scissor: None,
|
||||
draw_depth: 0.0,
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user