wip(f64): convert command layer to DVec3 (in progress)
Migrate the command/snap/grip/cursor chain from f32 Vec3 to f64 DVec3 so picked points, snaps and grip drags stay precise at UTM-scale coordinates (f32 quantizes to ~0.5 m there). Done so far: - command/mod.rs: EntityTransform, CmdResult points, CadCommand point methods, TangentObject already DVec3 (radius f64). - snap: SnapResult.world DVec3; world_to_screen/try_pt DVec3. - GripApply -> DVec3; grip find/state (GripEdit) f64; camera pick_on_plane_f64 / pick_on_target_plane_f64; scene paper_to_model_f64. - update.rs click + mouse-move + grip-drag pipelines route precise DVec3 to on_point/on_preview_wires/on_entity_pick; ortho/polar cast at the UcsXform boundary only. - cmd_result dispatch, transform helpers, dimension/arc/circle/multileader apply_grip, circle/arc/ellipse/shapes draw commands, array modify. Tree does NOT compile yet (~236 errors remain across modify/annotate/ insert command files + entity apply_grip impls); committed at user request to checkpoint progress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
96aaf2a293
commit
3da71698b1
18 changed files with 626 additions and 587 deletions
|
|
@ -3594,6 +3594,11 @@ impl Scene {
|
|||
/// geometry of the currently active viewport. Returns the input unchanged
|
||||
/// when there is no active viewport.
|
||||
pub fn paper_to_model(&self, paper_pt: glam::Vec3) -> glam::Vec3 {
|
||||
self.paper_to_model_f64(paper_pt.as_dvec3()).as_vec3()
|
||||
}
|
||||
|
||||
/// f64 variant of [`paper_to_model`] — preserves UTM-scale precision.
|
||||
pub fn paper_to_model_f64(&self, paper_pt: glam::DVec3) -> glam::DVec3 {
|
||||
let vp_handle = match self.active_viewport {
|
||||
Some(h) => h,
|
||||
None => return paper_pt,
|
||||
|
|
@ -3602,16 +3607,15 @@ impl Scene {
|
|||
Some(acadrust::EntityType::Viewport(vp)) => vp,
|
||||
_ => return paper_pt,
|
||||
};
|
||||
let scale =
|
||||
vp_effective_scale(vp.custom_scale, vp.view_height, vp.height) as f32;
|
||||
let scale = vp_effective_scale(vp.custom_scale, vp.view_height, vp.height);
|
||||
if scale.abs() < 1e-9 {
|
||||
return paper_pt;
|
||||
}
|
||||
let tx = vp.view_target.x as f32;
|
||||
let ty = vp.view_target.y as f32;
|
||||
let pcx = vp.center.x as f32;
|
||||
let pcy = vp.center.y as f32;
|
||||
glam::Vec3::new(
|
||||
let tx = vp.view_target.x;
|
||||
let ty = vp.view_target.y;
|
||||
let pcx = vp.center.x;
|
||||
let pcy = vp.center.y;
|
||||
glam::DVec3::new(
|
||||
(paper_pt.x - pcx) / scale + tx,
|
||||
(paper_pt.y - pcy) / scale + ty,
|
||||
paper_pt.z,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Shared value types used by the dispatch and grip systems.
|
||||
|
||||
use acadrust::types::{Color as AcadColor, LineWeight};
|
||||
use glam::Vec3;
|
||||
use glam::{DVec3, Vec3};
|
||||
|
||||
/// The kind of value held by a property row.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
@ -96,9 +96,9 @@ pub struct GripDef {
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum GripApply {
|
||||
/// Move a specific vertex to this absolute world position.
|
||||
Absolute(Vec3),
|
||||
Absolute(DVec3),
|
||||
/// Translate the whole object by this delta vector.
|
||||
Translate(Vec3),
|
||||
Translate(DVec3),
|
||||
}
|
||||
|
||||
/// One entry in the hover-popup menu that opens when the cursor dwells
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! OpenCADStudio-style grip editing.
|
||||
|
||||
use acadrust::Handle;
|
||||
use glam::Vec3;
|
||||
use glam::{DVec3, Vec3};
|
||||
use iced::{Point, Rectangle};
|
||||
|
||||
use crate::scene::model::object::{GripDef, GripShape};
|
||||
|
|
@ -23,9 +23,9 @@ pub struct GripEdit {
|
|||
/// `true` → midpoint / translate grip; `false` → endpoint / absolute grip.
|
||||
pub is_translate: bool,
|
||||
/// World-space position of the grip when the drag started (ortho/polar base).
|
||||
pub origin_world: Vec3,
|
||||
pub origin_world: DVec3,
|
||||
/// Last world-space cursor position (needed for incremental delta on translate drags).
|
||||
pub last_world: Vec3,
|
||||
pub last_world: DVec3,
|
||||
}
|
||||
|
||||
// ── Screen-space helpers ───────────────────────────────────────────────────
|
||||
|
|
@ -83,9 +83,9 @@ pub fn find_hit_grip_paper(
|
|||
half_w: f32,
|
||||
half_h: f32,
|
||||
bounds: Rectangle,
|
||||
) -> Option<(usize, bool, Vec3)> {
|
||||
) -> Option<(usize, bool, DVec3)> {
|
||||
let mut best_dist = GRIP_THRESHOLD_PX;
|
||||
let mut best: Option<(usize, bool, Vec3)> = None;
|
||||
let mut best: Option<(usize, bool, DVec3)> = None;
|
||||
|
||||
for g in grips {
|
||||
let screen = Point::new(
|
||||
|
|
@ -97,7 +97,7 @@ pub fn find_hit_grip_paper(
|
|||
let d = (dx * dx + dy * dy).sqrt();
|
||||
if d < best_dist {
|
||||
best_dist = d;
|
||||
best = Some((g.id, g.is_midpoint, g.world.as_vec3()));
|
||||
best = Some((g.id, g.is_midpoint, g.world));
|
||||
}
|
||||
}
|
||||
best
|
||||
|
|
@ -110,9 +110,9 @@ pub fn find_hit_grip(
|
|||
grips: &[GripDef],
|
||||
camera: &crate::scene::view::camera::Camera,
|
||||
bounds: Rectangle,
|
||||
) -> Option<(usize, bool, Vec3)> {
|
||||
) -> Option<(usize, bool, DVec3)> {
|
||||
let mut best_dist = GRIP_THRESHOLD_PX;
|
||||
let mut best: Option<(usize, bool, Vec3)> = None;
|
||||
let mut best: Option<(usize, bool, DVec3)> = None;
|
||||
|
||||
for g in grips {
|
||||
let Some(screen) = camera.project_f64(g.world, bounds) else {
|
||||
|
|
@ -124,7 +124,7 @@ pub fn find_hit_grip(
|
|||
let d = (dx * dx + dy * dy).sqrt();
|
||||
if d < best_dist {
|
||||
best_dist = d;
|
||||
best = Some((g.id, g.is_midpoint, g.world.as_vec3()));
|
||||
best = Some((g.id, g.is_midpoint, g.world));
|
||||
}
|
||||
}
|
||||
best
|
||||
|
|
|
|||
|
|
@ -233,9 +233,24 @@ impl Camera {
|
|||
}
|
||||
|
||||
pub fn pick_on_target_plane(&self, screen: Point, bounds: Rectangle) -> Vec3 {
|
||||
self.pick_on_target_plane_f64(screen, bounds).as_vec3()
|
||||
}
|
||||
|
||||
/// f64 variant of [`pick_on_plane`] — keeps the cursor precise at UTM-scale.
|
||||
pub fn pick_on_plane_f64(
|
||||
&self,
|
||||
screen: Point,
|
||||
bounds: Rectangle,
|
||||
plane_normal: Vec3,
|
||||
plane_point: glam::DVec3,
|
||||
) -> glam::DVec3 {
|
||||
self.unproject_on_plane_f64(screen, bounds, plane_normal, plane_point)
|
||||
}
|
||||
|
||||
/// f64 variant of [`pick_on_target_plane`].
|
||||
pub fn pick_on_target_plane_f64(&self, screen: Point, bounds: Rectangle) -> glam::DVec3 {
|
||||
let forward = (self.target.as_vec3() - self.eye()).normalize_or(Vec3::NEG_Z);
|
||||
self.unproject_on_plane_f64(screen, bounds, forward, self.target)
|
||||
.as_vec3()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use acadrust::types::{Transform, Vector3};
|
||||
use glam::Vec3;
|
||||
use glam::DVec3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
|
||||
#[inline]
|
||||
fn to_v3(v: Vec3) -> Vector3 {
|
||||
Vector3::new(v.x as f64, v.y as f64, v.z as f64)
|
||||
fn to_v3(v: DVec3) -> Vector3 {
|
||||
Vector3::new(v.x, v.y, v.z)
|
||||
}
|
||||
|
||||
pub fn apply_standard_transform<T>(entity: &mut T, center: Vec3, angle_rad: f32)
|
||||
pub fn apply_standard_transform<T>(entity: &mut T, center: DVec3, angle_rad: f32)
|
||||
where
|
||||
T: acadrust::Entity,
|
||||
{
|
||||
|
|
@ -19,7 +19,7 @@ where
|
|||
entity.apply_transform(&t);
|
||||
}
|
||||
|
||||
pub fn apply_standard_scale<T>(entity: &mut T, center: Vec3, factor: f32)
|
||||
pub fn apply_standard_scale<T>(entity: &mut T, center: DVec3, factor: f32)
|
||||
where
|
||||
T: acadrust::Entity,
|
||||
{
|
||||
|
|
@ -31,7 +31,7 @@ where
|
|||
pub fn apply_standard_entity_transform<T, F>(entity: &mut T, t: &EntityTransform, mirror: F)
|
||||
where
|
||||
T: acadrust::Entity,
|
||||
F: FnOnce(&mut T, Vec3, Vec3),
|
||||
F: FnOnce(&mut T, DVec3, DVec3),
|
||||
{
|
||||
match t {
|
||||
EntityTransform::Translate(d) => entity.translate(to_v3(*d)),
|
||||
|
|
@ -47,7 +47,7 @@ where
|
|||
/// `Transform`, for delegating MIRROR to acadrust's entity-aware
|
||||
/// `apply_transform` paths (which handle direction flags, stored-angle
|
||||
/// conventions and bulges themselves). Degenerate line → identity.
|
||||
pub fn reflection_about_xy_line(p1: Vec3, p2: Vec3) -> acadrust::types::Transform {
|
||||
pub fn reflection_about_xy_line(p1: DVec3, p2: DVec3) -> acadrust::types::Transform {
|
||||
use acadrust::types::{Matrix4, Transform};
|
||||
let dx = (p2.x - p1.x) as f64;
|
||||
let dy = (p2.y - p1.y) as f64;
|
||||
|
|
@ -63,7 +63,7 @@ pub fn reflection_about_xy_line(p1: Vec3, p2: Vec3) -> acadrust::types::Transfor
|
|||
Transform::from_matrix(m)
|
||||
}
|
||||
|
||||
pub fn reflect_xy_point(x: &mut f64, y: &mut f64, p1: Vec3, p2: Vec3) {
|
||||
pub fn reflect_xy_point(x: &mut f64, y: &mut f64, p1: DVec3, p2: DVec3) {
|
||||
let ax = (p2.x - p1.x) as f64;
|
||||
let ay = (p2.y - p1.y) as f64;
|
||||
let len2 = ax * ax + ay * ay;
|
||||
|
|
@ -79,7 +79,7 @@ pub fn reflect_xy_point(x: &mut f64, y: &mut f64, p1: Vec3, p2: Vec3) {
|
|||
*y = p1.y as f64 + my;
|
||||
}
|
||||
|
||||
pub fn mirror_xy_line(line: &mut acadrust::entities::Line, p1: Vec3, p2: Vec3) {
|
||||
pub fn mirror_xy_line(line: &mut acadrust::entities::Line, p1: DVec3, p2: DVec3) {
|
||||
reflect_xy_point(&mut line.start.x, &mut line.start.y, p1, p2);
|
||||
reflect_xy_point(&mut line.end.x, &mut line.end.y, p1, p2);
|
||||
}
|
||||
|
|
@ -171,8 +171,8 @@ mod mirror_delegation_tests {
|
|||
|
||||
// Mirror across the vertical line x = 5.
|
||||
h.apply_transform(&EntityTransform::Mirror {
|
||||
p1: Vec3::new(5.0, 0.0, 0.0),
|
||||
p2: Vec3::new(5.0, 1.0, 0.0),
|
||||
p1: DVec3::new(5.0, 0.0, 0.0),
|
||||
p2: DVec3::new(5.0, 1.0, 0.0),
|
||||
});
|
||||
|
||||
let edges = &h.paths[0].edges;
|
||||
|
|
|
|||
Loading…
Reference in a new issue