From cd1d3bb619dfa983404ae9a202fe4650c8f15748 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 23 Jun 2026 22:10:29 +0300 Subject: [PATCH] refactor(snap): producers emit f64 snap points (world_offset removal P3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TruckEntity.snap_pts is now DVec3 and every entity producer builds snap candidates straight from the acadrust f64 coordinates instead of casting to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid, mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh, multileader, dimension, block-cache). offset_snap_pts stays f64 throughout. Still offset-relative (inert) — but snap precision is no longer capped at ~0.5 m by an early f32 cast, which fixes a latent UTM-scale snap error and sets up the absolute-coordinate switch. Co-Authored-By: Claude Opus 4.7 --- src/entities/arc.rs | 5 ++--- src/entities/attribute.rs | 3 +-- src/entities/circle.rs | 9 ++------- src/entities/ellipse.rs | 11 +++++------ src/entities/mesh.rs | 17 ++++++----------- src/entities/mline.rs | 7 +------ src/entities/mtext.rs | 9 ++++----- src/entities/multileader.rs | 11 ++--------- src/entities/ole2frame.rs | 3 +-- src/entities/point.rs | 3 +-- src/entities/shape.rs | 3 +-- src/entities/solid.rs | 14 +++++--------- src/entities/table.rs | 2 +- src/entities/text.rs | 3 +-- src/entities/tolerance.rs | 9 ++++----- src/entities/underlay.rs | 7 +++---- src/scene/convert/acad_to_truck.rs | 3 +-- src/scene/convert/tessellate.rs | 9 ++------- 18 files changed, 43 insertions(+), 85 deletions(-) diff --git a/src/entities/arc.rs b/src/entities/arc.rs index fd1bac1ea..b9aea0c15 100644 --- a/src/entities/arc.rs +++ b/src/entities/arc.rs @@ -1,5 +1,4 @@ use acadrust::entities::Arc; -use glam::Vec3; use truck_modeling::{builder, Point3}; use crate::command::EntityTransform; @@ -39,11 +38,11 @@ fn to_truck(arc: &Arc) -> TruckEntity { ) }; - let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32); + let cv = glam::DVec3::new(cwx, cwy, cwz); // Arc-length centre — one well-defined midpoint snap. Circles and // ellipses (closed curves) deliberately don't emit this; see #34. let mid_pt_3 = arc_pt(mid_a); - let mv = Vec3::new(mid_pt_3.x as f32, mid_pt_3.y as f32, mid_pt_3.z as f32); + let mv = glam::DVec3::new(mid_pt_3.x, mid_pt_3.y, mid_pt_3.z); let tangent = TangentGeom::Circle { center: [cwx as f32, cwy as f32, cwz as f32], radius: r as f32, diff --git a/src/entities/attribute.rs b/src/entities/attribute.rs index e3c5300d8..561d56942 100644 --- a/src/entities/attribute.rs +++ b/src/entities/attribute.rs @@ -3,7 +3,6 @@ use acadrust::entities::attribute_definition::{ }; use acadrust::entities::{AttributeDefinition, AttributeEntity}; use acadrust::types::Vector3; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, parse_f64, ro_prop as ro, square_grip}; @@ -111,7 +110,7 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) ), normal, ); - let snap_pt = Vec3::new(wsx as f32, wsy as f32, wsz as f32); + let snap_pt = glam::DVec3::new(wsx, wsy, wsz); let resolved = resolve_text_style(input.text_style, document); diff --git a/src/entities/circle.rs b/src/entities/circle.rs index 426bd0c62..be0928846 100644 --- a/src/entities/circle.rs +++ b/src/entities/circle.rs @@ -1,5 +1,4 @@ use acadrust::entities::Circle; -use glam::Vec3; use truck_modeling::{builder, Point3, Wire}; use crate::command::EntityTransform; @@ -35,14 +34,10 @@ fn to_truck(circle: &Circle) -> TruckEntity { let p_top = pt(ay, (0.0, 0.0, 0.0), r); let p_bot = pt((ay.0 * -1.0, ay.1 * -1.0, ay.2 * -1.0), (0.0, 0.0, 0.0), r); - let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32); + let cv = glam::DVec3::new(cwx, cwy, cwz); let rf = r as f32; let q = |d: (f64, f64, f64)| { - Vec3::new( - (cwx + r * d.0) as f32, - (cwy + r * d.1) as f32, - (cwz + r * d.2) as f32, - ) + glam::DVec3::new(cwx + r * d.0, cwy + r * d.1, cwz + r * d.2) }; let snap_pts = vec![ (cv, SnapHint::Center), diff --git a/src/entities/ellipse.rs b/src/entities/ellipse.rs index b6e80cb8e..ab8e99bdd 100644 --- a/src/entities/ellipse.rs +++ b/src/entities/ellipse.rs @@ -1,5 +1,4 @@ use acadrust::entities::Ellipse; -use glam::Vec3; use truck_modeling::{builder, BSplineCurve, Curve, Edge, KnotVec, Point3, Wire}; use crate::command::EntityTransform; @@ -41,7 +40,7 @@ fn to_truck(ell: &Ellipse) -> TruckEntity { // Minor axis direction: WCS_normal × u (both unit vectors, always perpendicular). let wcs_normal = glam::Vec3::new(nx as f32, ny as f32, nz as f32); let v_axis = wcs_normal.cross(u); - let center_v3 = Vec3::new(cwx as f32, cwy as f32, cwz as f32); + let center_v3 = glam::DVec3::new(cwx, cwy, cwz); let is_closed = (t1 - t0 - TAU).abs() < 1e-6; if is_closed { @@ -81,10 +80,10 @@ fn to_truck(ell: &Ellipse) -> TruckEntity { let wire: Wire = [edge_upper, edge_lower].into_iter().collect(); // Quadrant points at ±major and ±minor axis endpoints in WCS. let q = |lx: f64, lz: f64| { - Vec3::new( - (cwx + lx * u.x as f64 + lz * v_axis.x as f64) as f32, - (cwy + lx * u.y as f64 + lz * v_axis.y as f64) as f32, - (cwz + lx * u.z as f64 + lz * v_axis.z as f64) as f32, + glam::DVec3::new( + cwx + lx * u.x as f64 + lz * v_axis.x as f64, + cwy + lx * u.y as f64 + lz * v_axis.y as f64, + cwz + lx * u.z as f64 + lz * v_axis.z as f64, ) }; let snap_pts = vec![ diff --git a/src/entities/mesh.rs b/src/entities/mesh.rs index fbcb552ac..4c318ffef 100644 --- a/src/entities/mesh.rs +++ b/src/entities/mesh.rs @@ -69,10 +69,10 @@ impl TruckConvertible for Face3D { Some(TruckEntity { object: TruckObject::Lines(pts), snap_pts: vec![ - (Vec3::from(p0f), SnapHint::Node), - (Vec3::from(p1f), SnapHint::Node), - (Vec3::from(p2f), SnapHint::Node), - (Vec3::from(p3f), SnapHint::Node), + (Vec3::from(p0f).as_dvec3(), SnapHint::Node), + (Vec3::from(p1f).as_dvec3(), SnapHint::Node), + (Vec3::from(p2f).as_dvec3(), SnapHint::Node), + (Vec3::from(p3f).as_dvec3(), SnapHint::Node), ], tangent_geoms: vec![], key_vertices: vec![p0, p1, p2, p3], @@ -552,15 +552,10 @@ impl TruckConvertible for Mesh { } } - let snap_pts: Vec<(Vec3, SnapHint)> = self + let snap_pts: Vec<(glam::DVec3, SnapHint)> = self .vertices .iter() - .map(|v| { - ( - Vec3::new(v.x as f32, v.y as f32, v.z as f32), - SnapHint::Node, - ) - }) + .map(|v| (glam::DVec3::new(v.x, v.y, v.z), SnapHint::Node)) .collect(); let key_vertices: Vec<[f64; 3]> = self.vertices.iter().map(|v| [v.x, v.y, v.z]).collect(); diff --git a/src/entities/mline.rs b/src/entities/mline.rs index f5fa428b6..f761c4b39 100644 --- a/src/entities/mline.rs +++ b/src/entities/mline.rs @@ -1,5 +1,4 @@ use acadrust::entities::MLine; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip}; @@ -98,11 +97,7 @@ impl TruckConvertible for MLine { .iter() .map(|v| { ( - Vec3::new( - v.position.x as f32, - v.position.y as f32, - v.position.z as f32, - ), + glam::DVec3::new(v.position.x, v.position.y, v.position.z), SnapHint::Node, ) }) diff --git a/src/entities/mtext.rs b/src/entities/mtext.rs index 5083b026a..1233a9826 100644 --- a/src/entities/mtext.rs +++ b/src/entities/mtext.rs @@ -1,5 +1,4 @@ use acadrust::entities::{AttachmentPoint, DrawingDirection, MText}; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip, triangle_grip}; @@ -168,10 +167,10 @@ fn to_truck(t: &MText, document: &acadrust::CadDocument) -> TruckEntity { vertical_text: matches!(t.drawing_direction, DrawingDirection::TopToBottom), want_glyph_boxes: false, }); - let insertion = Vec3::new( - t.insertion_point.x as f32, - t.insertion_point.y as f32, - t.insertion_point.z as f32, + let insertion = glam::DVec3::new( + t.insertion_point.x, + t.insertion_point.y, + t.insertion_point.z, ); TruckEntity { object: TruckObject::Text(layout.strokes), diff --git a/src/entities/multileader.rs b/src/entities/multileader.rs index 985a3f364..4bc8646df 100644 --- a/src/entities/multileader.rs +++ b/src/entities/multileader.rs @@ -77,17 +77,10 @@ fn to_truck(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option = Vec::new(); let mut tangents: Vec = Vec::new(); let mut key_verts: Vec<[f64; 3]> = Vec::new(); - // This builds a TruckEntity (snap_pts in Vec3); tessellate's - // offset_snap_pts widens it to the f64 WireModel buffer afterwards. - let mut snap_pts: Vec<(Vec3, SnapHint)> = Vec::new(); + let mut snap_pts: Vec<(glam::DVec3, SnapHint)> = Vec::new(); let mut first = true; - let node = |arr: [f64; 3]| { - ( - Vec3::new(arr[0] as f32, arr[1] as f32, arr[2] as f32), - SnapHint::Node, - ) - }; + let node = |arr: [f64; 3]| (glam::DVec3::new(arr[0], arr[1], arr[2]), SnapHint::Node); // Text-side geometry, recomputed every frame so dragging the arrow or the // text re-mirrors the whole layout. The text block is centred on its grip diff --git a/src/entities/ole2frame.rs b/src/entities/ole2frame.rs index 078f431de..3af21b67d 100644 --- a/src/entities/ole2frame.rs +++ b/src/entities/ole2frame.rs @@ -1,5 +1,4 @@ use acadrust::entities::{Ole2Frame, OleObjectType}; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip}; @@ -45,7 +44,7 @@ fn to_truck(ole: &Ole2Frame) -> TruckEntity { [x1, y0, z], [x0, y1, z], ]; - let center = Vec3::new(cx as f32, cy as f32, z as f32); + let center = glam::DVec3::new(cx, cy, z); TruckEntity { object: TruckObject::Lines(pts), snap_pts: vec![(center, SnapHint::Center)], diff --git a/src/entities/point.rs b/src/entities/point.rs index 8aa9d2a09..479353321 100644 --- a/src/entities/point.rs +++ b/src/entities/point.rs @@ -1,6 +1,5 @@ use acadrust::entities::Point; use acadrust::EntityType; -use glam::Vec3; use truck_modeling::{builder, Point3}; use crate::command::EntityTransform; @@ -36,7 +35,7 @@ fn point_truck(pt: &Point, pdmode: i16, s: f64) -> TruckEntity { (pt.location.x, pt.location.y, pt.location.z), normal, ); - let snap = Vec3::new(wx as f32, wy as f32, wz as f32); + let snap = glam::DVec3::new(wx, wy, wz); if pdmode == 0 { // Default: a single vertex (driver handles the dot pixel). let p = Point3::new(wx, wy, wz); diff --git a/src/entities/shape.rs b/src/entities/shape.rs index 9d504c8d9..caebcfb9d 100644 --- a/src/entities/shape.rs +++ b/src/entities/shape.rs @@ -6,7 +6,6 @@ // gives a rough indication of the glyph orientation. use acadrust::entities::Shape; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip}; @@ -63,7 +62,7 @@ impl TruckConvertible for Shape { let oz = self.insertion_point.z; let size = self.size.abs().max(0.5); - let snap_pt = Vec3::new(ox as f32, oy as f32, oz as f32); + let snap_pt = glam::DVec3::new(ox, oy, oz); let pts = shape_marker( ox, oy, diff --git a/src/entities/solid.rs b/src/entities/solid.rs index 48d97230e..d376b69e5 100644 --- a/src/entities/solid.rs +++ b/src/entities/solid.rs @@ -5,7 +5,6 @@ // Grips: 4 corner grip points. use acadrust::entities::Solid; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, square_grip}; @@ -22,10 +21,6 @@ fn dvec3(v: &acadrust::types::Vector3) -> glam::DVec3 { glam::DVec3::new(v.x, v.y, v.z) } -fn v3f32(v: &acadrust::types::Vector3) -> [f32; 3] { - [v.x as f32, v.y as f32, v.z as f32] -} - impl TruckConvertible for Solid { fn to_truck(&self, _document: &acadrust::CadDocument) -> Option { let p0 = v3(&self.first_corner); @@ -50,11 +45,12 @@ impl TruckConvertible for Solid { p0, ]; + let dv = |c: &acadrust::types::Vector3| glam::DVec3::new(c.x, c.y, c.z); let snap = vec![ - (Vec3::from(v3f32(&self.first_corner)), SnapHint::Node), - (Vec3::from(v3f32(&self.second_corner)), SnapHint::Node), - (Vec3::from(v3f32(&self.third_corner)), SnapHint::Node), - (Vec3::from(v3f32(&self.fourth_corner)), SnapHint::Node), + (dv(&self.first_corner), SnapHint::Node), + (dv(&self.second_corner), SnapHint::Node), + (dv(&self.third_corner), SnapHint::Node), + (dv(&self.fourth_corner), SnapHint::Node), ]; Some(TruckEntity { diff --git a/src/entities/table.rs b/src/entities/table.rs index bfb6a2788..cdf992fb9 100644 --- a/src/entities/table.rs +++ b/src/entities/table.rs @@ -323,7 +323,7 @@ impl TruckConvertible for Table { .collect(); Some(TruckEntity { object: TruckObject::Lines(pts_f64), - snap_pts: vec![(v3(&self.insertion_point), SnapHint::Insertion)], + snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Insertion)], tangent_geoms: vec![], key_vertices: vec![], fill_tris: vec![], diff --git a/src/entities/text.rs b/src/entities/text.rs index 9feba96fd..6e6bada97 100644 --- a/src/entities/text.rs +++ b/src/entities/text.rs @@ -1,5 +1,4 @@ use acadrust::entities::{Text, TextHorizontalAlignment as HA, TextVerticalAlignment as VA}; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, parse_f64, square_grip}; @@ -58,7 +57,7 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity { ), normal, ); - let snap_pt = Vec3::new(wsx as f32, wsy as f32, wsz as f32); + let snap_pt = glam::DVec3::new(wsx, wsy, wsz); let resolved_style = resolve_text_style(&t.style, document); let font_name = resolved_style.font_name; // AutoCAD text geometry rule: the entity stores the FINAL width factor / diff --git a/src/entities/tolerance.rs b/src/entities/tolerance.rs index 20fdce7fa..71f63ec13 100644 --- a/src/entities/tolerance.rs +++ b/src/entities/tolerance.rs @@ -1,5 +1,4 @@ use acadrust::entities::Tolerance; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip}; @@ -234,10 +233,10 @@ impl TruckConvertible for Tolerance { return None; } - let snap_pt = Vec3::new( - self.insertion_point.x as f32, - self.insertion_point.y as f32, - self.insertion_point.z as f32, + let snap_pt = glam::DVec3::new( + self.insertion_point.x, + self.insertion_point.y, + self.insertion_point.z, ); // Build the feature-control frame in local space; origin stored as f64. diff --git a/src/entities/underlay.rs b/src/entities/underlay.rs index 5234c2595..2c1652a4a 100644 --- a/src/entities/underlay.rs +++ b/src/entities/underlay.rs @@ -5,7 +5,6 @@ // Props: position, scales, rotation, contrast, fade, flags. use acadrust::entities::{Underlay, UnderlayDisplayFlags}; -use glam::Vec3; use crate::command::EntityTransform; use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip}; @@ -41,7 +40,7 @@ fn cross_wire(origin: [f64; 3], size: f64) -> Vec<[f64; 3]> { impl TruckConvertible for Underlay { fn to_truck(&self, _document: &acadrust::CadDocument) -> Option { let origin = v3(&self.insertion_point); - let origin_f32 = v3f32(&self.insertion_point); + let _origin_f32 = v3f32(&self.insertion_point); if !self.clip_boundary_vertices.is_empty() { // Draw clip boundary polygon + close it. @@ -55,7 +54,7 @@ impl TruckConvertible for Underlay { let key: Vec<[f64; 3]> = pts.clone(); Some(TruckEntity { object: TruckObject::Lines(pts), - snap_pts: vec![(Vec3::from(origin_f32), SnapHint::Node)], + snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)], tangent_geoms: vec![], key_vertices: key, fill_tris: vec![], @@ -65,7 +64,7 @@ impl TruckConvertible for Underlay { let pts = cross_wire(origin, 1.0); Some(TruckEntity { object: TruckObject::Lines(pts), - snap_pts: vec![(Vec3::from(origin_f32), SnapHint::Node)], + snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)], tangent_geoms: vec![], key_vertices: vec![origin], fill_tris: vec![], diff --git a/src/scene/convert/acad_to_truck.rs b/src/scene/convert/acad_to_truck.rs index 4298f019a..60497fc83 100644 --- a/src/scene/convert/acad_to_truck.rs +++ b/src/scene/convert/acad_to_truck.rs @@ -1,7 +1,6 @@ // acadrust -> truck topology conversion layer. use acadrust::{CadDocument, EntityType}; -use glam::Vec3; use truck_modeling::{Edge, Solid, Vertex, Wire}; use crate::entities::traits::EntityTypeOps; @@ -40,7 +39,7 @@ pub enum TruckObject { pub struct TruckEntity { pub object: TruckObject, - pub snap_pts: Vec<(Vec3, SnapHint)>, + pub snap_pts: Vec<(glam::DVec3, SnapHint)>, pub tangent_geoms: Vec, /// Polyline vertex positions in WCS f64; converted to offset-relative f32 /// at the wire-model boundary. diff --git a/src/scene/convert/tessellate.rs b/src/scene/convert/tessellate.rs index 510d71bfa..fb859668e 100644 --- a/src/scene/convert/tessellate.rs +++ b/src/scene/convert/tessellate.rs @@ -863,17 +863,12 @@ pub(crate) fn add_polyline(points: &mut Vec<[f32; 3]>, polyline: &[Vec3]) { } pub(crate) fn offset_snap_pts( - pts: Vec<(Vec3, SnapHint)>, + pts: Vec<(glam::DVec3, SnapHint)>, off: [f64; 3], ) -> Vec<(glam::DVec3, SnapHint)> { let [ox, oy, oz] = off; pts.into_iter() - .map(|(p, h)| { - ( - glam::DVec3::new(p.x as f64 - ox, p.y as f64 - oy, p.z as f64 - oz), - h, - ) - }) + .map(|(p, h)| (glam::DVec3::new(p.x - ox, p.y - oy, p.z - oz), h)) .collect() }