fix(commands): migrate inquiry + fillet/align/lengthen picks to world XY (#54)

These commands still read the cursor / entity coordinate with the old
"Y-up XZ" assumption (world Z = DXF Y), which is wrong now that the
drawing plane is world XY: ID/DIST/AREA reported swapped Y↔Z values and
zero-area, and fillet/align/lengthen picked against a constant-elevation
axis. Read the drawing-plane coordinate from .y (elevation stays on .z),
matching the central transform and the entity builders.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-04 10:32:38 +03:00
1 parent 3e493969b6
commit c04bdcf846
6 files changed
+21 -21

No files matched your search

+2 -2
View File
@@ -41,14 +41,14 @@ impl CadCommand for AreaCommand {
if self.points.len() < 3 {
return CmdResult::Cancel;
}
// Shoelace formula in the XZ plane (Y-up world)
// Shoelace formula in the world XY plane.
let n = self.points.len();
let mut area_sum = 0.0f32;
let mut perimeter = 0.0f32;
for idx in 0..n {
let a = self.points[idx];
let b = self.points[(idx + 1) % n];
area_sum += a.x * b.z - b.x * a.z;
area_sum += a.x * b.y - b.x * a.y;
perimeter += (b - a).length();
}
let area = (area_sum * 0.5).abs();
+3 -3
View File
@@ -33,10 +33,10 @@ impl CadCommand for DistCommand {
let delta = pt - p1;
let dist = delta.length();
let dx = delta.x;
let dy = delta.z; // Y-up world: Z is the "drawing Y"
let dz = delta.y; // Y-up world: Y is elevation
let dy = delta.y; // drawing plane is world XY
let dz = delta.z; // elevation
// Angle in XY plane (XZ in world coords) — degrees from +X
// Angle in XY plane — degrees from +X
let angle_xy = dy.atan2(dx).to_degrees();
// Angle from XY plane toward Z (elevation angle)
let dist_xy = dx.hypot(dy);
+3 -3
View File
@@ -22,10 +22,10 @@ impl CadCommand for IdCommand {
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
// Y-up world: X stays X, Z→drawing Y, Y→elevation Z
// Drawing plane is world XY (z = elevation).
let x = pt.x;
let y = pt.z;
let z = pt.y;
let y = pt.y;
let z = pt.z;
let msg = format!("X = {x:.4}, Y = {y:.4}, Z = {z:.4}");
CmdResult::Measurement(msg)
}
+3 -3
View File
@@ -167,9 +167,9 @@ impl AlignCommand {
);
}
// Angle from src_vec to dst_vec in XZ plane
let src_angle = src_vec.z.atan2(src_vec.x);
let dst_angle = dst_vec.z.atan2(dst_vec.x);
// Angle from src_vec to dst_vec in the world XY plane
let src_angle = src_vec.y.atan2(src_vec.x);
let dst_angle = dst_vec.y.atan2(dst_vec.x);
let angle = dst_angle - src_angle;
let scale_factor = if with_scale { dst_len / src_len } else { 1.0 };
+2 -2
View File
@@ -1246,7 +1246,7 @@ impl CadCommand for FilletCommand {
if handle.is_null() {
return CmdResult::NeedPoint;
}
let click = [pt.x as f64, pt.z as f64]; // Y-up: world Z = DXF Y
let click = [pt.x as f64, pt.y as f64]; // drawing plane is world XY
match &self.step {
FilletStep::WaitingForRadius => return CmdResult::NeedPoint,
@@ -1324,7 +1324,7 @@ impl CadCommand for FilletCommand {
if handle.is_null() {
return vec![];
}
let click = [pt.x as f64, pt.z as f64];
let click = [pt.x as f64, pt.y as f64];
match &self.step {
FilletStep::WaitingForRadius => vec![],
+8 -8
View File
@@ -150,9 +150,9 @@ pub fn lengthen_entity(entity: &EntityType, pick_pt: Vec3, mode: &LenMode) -> Op
}
fn lengthen_line(line: &LineEnt, pick_pt: Vec3, mode: &LenMode) -> Option<EntityType> {
let s = Vec3::new(line.start.x as f32, line.start.z as f32, 0.0);
let e = Vec3::new(line.end.x as f32, line.end.z as f32, 0.0);
let p = Vec3::new(pick_pt.x, pick_pt.z, 0.0);
let s = Vec3::new(line.start.x as f32, line.start.y as f32, 0.0);
let e = Vec3::new(line.end.x as f32, line.end.y as f32, 0.0);
let p = Vec3::new(pick_pt.x, pick_pt.y, 0.0);
let current_len = (e - s).length() as f64;
if current_len < 1e-10 {
@@ -187,7 +187,7 @@ fn lengthen_line(line: &LineEnt, pick_pt: Vec3, mode: &LenMode) -> Option<Entity
fn lengthen_arc(arc: &ArcEnt, pick_pt: Vec3, mode: &LenMode) -> Option<EntityType> {
let cx = arc.center.x as f32;
let cy = arc.center.z as f32; // Y-up: DXF Y → world Z
let cy = arc.center.y as f32;
// Current arc span
let span = arc_span_rad(arc.start_angle, arc.end_angle);
@@ -290,7 +290,7 @@ fn lengthen_ellipse(ell: &EllipseEnt, pick_pt: Vec3, mode: &LenMode) -> Option<E
// Determine which end is closer to pick_pt (use DXF XY plane).
let p_x = pick_pt.x as f64;
let p_y = pick_pt.z as f64; // Y-up: world Z → DXF Y
let p_y = pick_pt.y as f64; // Y-up: world Z → DXF Y
let pt_start_x = ell.center.x + a * t0.cos() * nx - b * t0.sin() * ny;
let pt_start_y = ell.center.y + a * t0.cos() * ny + b * t0.sin() * nx;
let pt_end_x = ell.center.x + a * t1.cos() * nx - b * t1.sin() * ny;
@@ -339,7 +339,7 @@ fn lengthen_lwpoly(poly: &LwPolyline, pick_pt: Vec3, mode: &LenMode) -> Option<E
// Determine which end is closer to the pick point (DXF XY: pick_pt.x, pick_pt.z).
let px = pick_pt.x as f64;
let py = pick_pt.z as f64; // Y-up: world Z = DXF Y
let py = pick_pt.y as f64; // Y-up: world Z = DXF Y
let first = &poly.vertices[0];
let last = &poly.vertices[n - 1];
@@ -428,8 +428,8 @@ fn lengthen_spline(spl: &SplineEnt, pick_pt: Vec3, mode: &LenMode) -> Option<Ent
// Determine which end (start or end) is closer to pick_pt.
let p_start = bs.subs(t0);
let p_end = bs.subs(t1);
let dist_start = (p_start.x - pick_pt.x as f64).hypot(p_start.y - pick_pt.z as f64);
let dist_end = (p_end.x - pick_pt.x as f64).hypot(p_end.y - pick_pt.z as f64);
let dist_start = (p_start.x - pick_pt.x as f64).hypot(p_start.y - pick_pt.y as f64);
let dist_end = (p_end.x - pick_pt.x as f64).hypot(p_end.y - pick_pt.y as f64);
let extend_end = dist_end <= dist_start;
// Find the parameter `t_new` such that the arc length from the fixed end to t_new = new_len.