forked from 1b-agent/opencadstudio-upstream
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the entity (e.g. a length of 2000.8 committed as 2000.8020), worsening with magnitude. The interaction point layer was all glam::Vec3 (f32). Two-layer fix: 1. Coordinate backbone -> f64. last_point, last_cursor_world, dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord, the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance paths, command-line coordinate entry and the coordinate readout all compute in f64. Screen/GPU/alignment stays f32 (snap engine, render geometry, projection, UCS-icon/viewcube drawing) with casts only at those boundaries. 2. Per-command committed storage -> DVec3. on_point already received a DVec3, but many command impls narrowed it back to f32 (let pt = pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN, INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud, wipeout, attdef, table, tolerance, array center, mview, plot_window, plus the QDIM_PLACE handler and qdim_collect_points. Preview, hit-test and rubber-band paths keep f32 at the boundary. Hatch manual boundaries are left for a follow-up: HatchModel.boundary is structurally Arc<Vec<[f32;2]>> and needs a model-level widen. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
8ed10ceb2a
commit
57710eec2b
47 files changed
+699
-606
No files matched your search
+19
-19
@@ -468,7 +468,7 @@ impl OpenCADStudio {
|
||||
// dimension-line point and the gathered geometry now selected. Build
|
||||
// a continuous chain of linear dimensions across the endpoints.
|
||||
cmd if cmd.starts_with("QDIM_PLACE ") => {
|
||||
let nums: Vec<f32> = cmd
|
||||
let nums: Vec<f64> = cmd
|
||||
.split_whitespace()
|
||||
.skip(1)
|
||||
.filter_map(|s| s.parse().ok())
|
||||
@@ -476,14 +476,14 @@ impl OpenCADStudio {
|
||||
if nums.len() < 3 {
|
||||
return Some(Task::none());
|
||||
}
|
||||
let place = glam::Vec3::new(nums[0], nums[1], nums[2]);
|
||||
let place = glam::DVec3::new(nums[0], nums[1], nums[2]);
|
||||
let handles: Vec<acadrust::Handle> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.iter()
|
||||
.map(|(h, _)| *h)
|
||||
.collect();
|
||||
let mut pts: Vec<glam::Vec3> = Vec::new();
|
||||
let mut pts: Vec<glam::DVec3> = Vec::new();
|
||||
for h in &handles {
|
||||
if let Some(e) = self.tabs[i].scene.document.get_entity(*h) {
|
||||
qdim_collect_points(e, &mut pts);
|
||||
@@ -498,10 +498,10 @@ impl OpenCADStudio {
|
||||
// span dimensions horizontally (ordered by X), else vertically.
|
||||
let (minx, maxx) = pts
|
||||
.iter()
|
||||
.fold((f32::MAX, f32::MIN), |(a, b), p| (a.min(p.x), b.max(p.x)));
|
||||
.fold((f64::MAX, f64::MIN), |(a, b), p| (a.min(p.x), b.max(p.x)));
|
||||
let (miny, maxy) = pts
|
||||
.iter()
|
||||
.fold((f32::MAX, f32::MIN), |(a, b), p| (a.min(p.y), b.max(p.y)));
|
||||
.fold((f64::MAX, f64::MIN), |(a, b), p| (a.min(p.y), b.max(p.y)));
|
||||
let horizontal = (maxx - minx) >= (maxy - miny);
|
||||
if horizontal {
|
||||
pts.sort_by(|a, b| a.x.total_cmp(&b.x));
|
||||
@@ -516,8 +516,8 @@ impl OpenCADStudio {
|
||||
return Some(Task::none());
|
||||
}
|
||||
self.push_undo_snapshot(i, "QDIM");
|
||||
let v = |p: glam::Vec3| {
|
||||
acadrust::types::Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
let v = |p: glam::DVec3| {
|
||||
acadrust::types::Vector3::new(p.x, p.y, p.z)
|
||||
};
|
||||
let mut made = 0usize;
|
||||
for w in pts.windows(2) {
|
||||
@@ -530,9 +530,9 @@ impl OpenCADStudio {
|
||||
};
|
||||
// Dim line passes through the picked perpendicular position.
|
||||
let def = if horizontal {
|
||||
glam::Vec3::new((p1.x + p2.x) * 0.5, place.y, 0.0)
|
||||
glam::DVec3::new((p1.x + p2.x) * 0.5, place.y, 0.0)
|
||||
} else {
|
||||
glam::Vec3::new(place.x, (p1.y + p2.y) * 0.5, 0.0)
|
||||
glam::DVec3::new(place.x, (p1.y + p2.y) * 0.5, 0.0)
|
||||
};
|
||||
dim.definition_point = v(def);
|
||||
dim.base.definition_point = v(def);
|
||||
@@ -1124,9 +1124,9 @@ fn find_last_linear_dim(
|
||||
|
||||
/// Collect candidate dimension endpoints from an entity for QDIM — line ends,
|
||||
/// polyline vertices, arc endpoints — in world space.
|
||||
fn qdim_collect_points(e: &acadrust::EntityType, out: &mut Vec<glam::Vec3>) {
|
||||
fn qdim_collect_points(e: &acadrust::EntityType, out: &mut Vec<glam::DVec3>) {
|
||||
use acadrust::EntityType as ET;
|
||||
let p = |v: &acadrust::types::Vector3| glam::Vec3::new(v.x as f32, v.y as f32, v.z as f32);
|
||||
let p = |v: &acadrust::types::Vector3| glam::DVec3::new(v.x, v.y, v.z);
|
||||
match e {
|
||||
ET::Line(l) => {
|
||||
out.push(p(&l.start));
|
||||
@@ -1134,10 +1134,10 @@ fn qdim_collect_points(e: &acadrust::EntityType, out: &mut Vec<glam::Vec3>) {
|
||||
}
|
||||
ET::LwPolyline(pl) => {
|
||||
for v in &pl.vertices {
|
||||
out.push(glam::Vec3::new(
|
||||
v.location.x as f32,
|
||||
v.location.y as f32,
|
||||
pl.elevation as f32,
|
||||
out.push(glam::DVec3::new(
|
||||
v.location.x,
|
||||
v.location.y,
|
||||
pl.elevation,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1148,10 +1148,10 @@ fn qdim_collect_points(e: &acadrust::EntityType, out: &mut Vec<glam::Vec3>) {
|
||||
}
|
||||
ET::Arc(a) => {
|
||||
for &ang in &[a.start_angle, a.end_angle] {
|
||||
out.push(glam::Vec3::new(
|
||||
(a.center.x + a.radius * ang.cos()) as f32,
|
||||
(a.center.y + a.radius * ang.sin()) as f32,
|
||||
a.center.z as f32,
|
||||
out.push(glam::DVec3::new(
|
||||
a.center.x + a.radius * ang.cos(),
|
||||
a.center.y + a.radius * ang.sin(),
|
||||
a.center.z,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,13 +282,9 @@ impl OpenCADStudio {
|
||||
let current = self.tabs[i].active_ucs.as_ref();
|
||||
let origin = current
|
||||
.map(|u| {
|
||||
glam::Vec3::new(
|
||||
u.origin.x as f32,
|
||||
u.origin.y as f32,
|
||||
u.origin.z as f32,
|
||||
)
|
||||
glam::DVec3::new(u.origin.x, u.origin.y, u.origin.z)
|
||||
})
|
||||
.unwrap_or(glam::Vec3::ZERO);
|
||||
.unwrap_or(glam::DVec3::ZERO);
|
||||
let mut new_ucs = ucs_rotated_z(origin, rad);
|
||||
// If already had axes, compose rotation on top
|
||||
if let Some(ref ucs) = self.tabs[i].active_ucs {
|
||||
@@ -302,7 +298,7 @@ impl OpenCADStudio {
|
||||
ucs.y_axis.y as f32,
|
||||
ucs.y_axis.z as f32,
|
||||
);
|
||||
let z_ax = ucs_z_axis(ucs);
|
||||
let z_ax = ucs_z_axis(ucs).as_vec3();
|
||||
let rot = glam::Quat::from_axis_angle(z_ax, rad);
|
||||
let nx = rot * old_x;
|
||||
let ny = rot * old_y;
|
||||
|
||||
Reference in new issue
Block a user