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
@@ -3,7 +3,7 @@
|
||||
use acadrust::entities::{Dimension, DimensionAligned};
|
||||
use acadrust::types::Vector3;
|
||||
use acadrust::EntityType;
|
||||
use glam::{DVec3, Vec3};
|
||||
use glam::DVec3;
|
||||
|
||||
use crate::command::{CadCommand, CmdResult};
|
||||
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
||||
@@ -22,8 +22,8 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
First,
|
||||
Second(Vec3),
|
||||
DimLine { p1: Vec3, p2: Vec3 },
|
||||
Second(DVec3),
|
||||
DimLine { p1: DVec3, p2: DVec3 },
|
||||
}
|
||||
|
||||
pub struct AlignedDimensionCommand {
|
||||
@@ -73,7 +73,7 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::First => {
|
||||
self.step = Step::Second(pt);
|
||||
@@ -174,7 +174,7 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let (p1, p2) = match self.step {
|
||||
Step::First => return None,
|
||||
Step::Second(p1) => (p1, pt),
|
||||
@@ -182,6 +182,9 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
return Some(preview_aligned(p1, p2, pt));
|
||||
}
|
||||
};
|
||||
// Preview WireModel points are screen/GPU-side: downcast to f32.
|
||||
let p1 = p1.as_vec3();
|
||||
let p2 = p2.as_vec3();
|
||||
Some(WireModel {
|
||||
text_verts: Vec::new(),
|
||||
name: "dimaligned_preview".into(),
|
||||
@@ -205,8 +208,8 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
/// Dimension-line endpoints: the baseline `p1`–`p2` shifted to pass through
|
||||
@@ -214,16 +217,21 @@ fn v3(p: Vec3) -> Vector3 {
|
||||
/// it matches the committed entity's renderer (and DIMLINEAR). The old
|
||||
/// preview used an XZ-plane perpendicular, drawing the offset in the wrong
|
||||
/// spatial direction. (#150)
|
||||
fn dim_line_endpoints(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> (Vec3, Vec3) {
|
||||
fn dim_line_endpoints(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> (DVec3, DVec3) {
|
||||
let axis = (p2 - p1).normalize_or_zero();
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
||||
let offset = (dim_pt - p1).dot(perp);
|
||||
(p1 + perp * offset, p2 + perp * offset)
|
||||
}
|
||||
|
||||
fn preview_aligned(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> WireModel {
|
||||
fn preview_aligned(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> WireModel {
|
||||
// Show ext lines + dim line.
|
||||
let (d1, d2) = dim_line_endpoints(p1, p2, dim_pt);
|
||||
// Preview WireModel points are screen/GPU-side: downcast to f32.
|
||||
let p1 = p1.as_vec3();
|
||||
let p2 = p2.as_vec3();
|
||||
let d1 = d1.as_vec3();
|
||||
let d2 = d2.as_vec3();
|
||||
WireModel {
|
||||
text_verts: Vec::new(),
|
||||
name: "dimaligned_preview".into(),
|
||||
|
||||
@@ -20,15 +20,15 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
Vertex,
|
||||
FirstRay(Vec3),
|
||||
FirstRay(DVec3),
|
||||
SecondRay {
|
||||
vertex: Vec3,
|
||||
first: Vec3,
|
||||
vertex: DVec3,
|
||||
first: DVec3,
|
||||
},
|
||||
ArcPoint {
|
||||
vertex: Vec3,
|
||||
first: Vec3,
|
||||
second: Vec3,
|
||||
vertex: DVec3,
|
||||
first: DVec3,
|
||||
second: DVec3,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ impl CadCommand for AngularDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::Vertex => {
|
||||
self.step = Step::FirstRay(pt);
|
||||
@@ -98,28 +98,34 @@ impl CadCommand for AngularDimensionCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let pt = pt.as_vec3();
|
||||
match self.step {
|
||||
Step::Vertex => None,
|
||||
Step::FirstRay(vertex) => Some(preview_wire(vec![vertex, pt])),
|
||||
Step::FirstRay(vertex) => Some(preview_wire(vec![vertex.as_vec3(), pt])),
|
||||
Step::SecondRay { vertex, first } => Some(preview_wire(vec![
|
||||
vertex,
|
||||
first,
|
||||
vertex.as_vec3(),
|
||||
first.as_vec3(),
|
||||
Vec3::new(f32::NAN, f32::NAN, f32::NAN),
|
||||
vertex,
|
||||
vertex.as_vec3(),
|
||||
pt,
|
||||
])),
|
||||
Step::ArcPoint {
|
||||
vertex,
|
||||
first,
|
||||
second,
|
||||
} => Some(preview_wire(angular_preview(vertex, first, second, pt))),
|
||||
} => Some(preview_wire(angular_preview(
|
||||
vertex.as_vec3(),
|
||||
first.as_vec3(),
|
||||
second.as_vec3(),
|
||||
pt,
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(pt: Vec3) -> Vector3 {
|
||||
Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64)
|
||||
fn v3(pt: DVec3) -> Vector3 {
|
||||
Vector3::new(pt.x, pt.y, pt.z)
|
||||
}
|
||||
|
||||
fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
|
||||
@@ -22,8 +22,8 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
CenterPoint,
|
||||
ArcPoint(Vec3),
|
||||
TextPoint { center: Vec3, arc_pt: Vec3 },
|
||||
ArcPoint(DVec3),
|
||||
TextPoint { center: DVec3, arc_pt: DVec3 },
|
||||
}
|
||||
|
||||
pub struct DiameterDimensionCommand {
|
||||
@@ -71,7 +71,7 @@ impl CadCommand for DiameterDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::CenterPoint => {
|
||||
self.step = Step::ArcPoint(pt);
|
||||
@@ -86,7 +86,7 @@ impl CadCommand for DiameterDimensionCommand {
|
||||
dim.base.definition_point = v3(arc_pt);
|
||||
dim.base.text_middle_point = v3(pt);
|
||||
dim.base.insertion_point = v3(pt);
|
||||
dim.leader_length = arc_pt.distance(pt) as f64;
|
||||
dim.leader_length = arc_pt.distance(pt);
|
||||
dim.base.actual_measurement = dim.measurement();
|
||||
dim.base.user_text = self.text_override.clone();
|
||||
// An explicit text angle overrides the default rotation.
|
||||
@@ -161,20 +161,21 @@ impl CadCommand for DiameterDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let pt = pt.as_vec3();
|
||||
match self.step {
|
||||
Step::CenterPoint => None,
|
||||
Step::ArcPoint(center) => Some(preview_line(center, pt)),
|
||||
Step::ArcPoint(center) => Some(preview_line(center.as_vec3(), pt)),
|
||||
Step::TextPoint { center, arc_pt } => {
|
||||
let far = center + (center - arc_pt); // opposite point on circle
|
||||
Some(preview_line(far, pt))
|
||||
Some(preview_line(far.as_vec3(), pt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
fn preview_line(a: Vec3, b: Vec3) -> WireModel {
|
||||
|
||||
@@ -27,22 +27,22 @@ pub fn tool() -> ToolDef {
|
||||
}
|
||||
|
||||
/// Fallback stacking increment (world units) when no DimStyle is available.
|
||||
const DEFAULT_DIMDLI: f32 = 1.5;
|
||||
const DEFAULT_DIMDLI: f64 = 1.5;
|
||||
|
||||
pub struct DimBaselineCommand {
|
||||
/// Fixed first-extension-line origin (never changes).
|
||||
base_p1: Vec3,
|
||||
base_p1: DVec3,
|
||||
/// Direction along the measurement direction (0.0 = horizontal, PI/2 = vertical).
|
||||
rotation: f64,
|
||||
/// Text reading rotation inherited from the base dim (keeps a UCS-aligned
|
||||
/// chain's text consistent with the originating DIMLINEAR). 0 = natural.
|
||||
text_rotation: f64,
|
||||
/// Unit vector perpendicular to the dimension axis, pointing toward the dim line side.
|
||||
perp: Vec3,
|
||||
perp: DVec3,
|
||||
/// Perpendicular distance of the NEXT dimension line from the extension-line axis.
|
||||
next_offset: f32,
|
||||
next_offset: f64,
|
||||
/// Stacking increment from the active DimStyle (DIMDLI).
|
||||
dimdli: f32,
|
||||
dimdli: f64,
|
||||
/// True once we have a base dimension loaded.
|
||||
ready: bool,
|
||||
}
|
||||
@@ -51,10 +51,10 @@ impl DimBaselineCommand {
|
||||
/// No base dim found — cancel immediately.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base_p1: Vec3::ZERO,
|
||||
base_p1: DVec3::ZERO,
|
||||
rotation: 0.0,
|
||||
text_rotation: 0.0,
|
||||
perp: Vec3::Y,
|
||||
perp: DVec3::Y,
|
||||
next_offset: DEFAULT_DIMDLI,
|
||||
dimdli: DEFAULT_DIMDLI,
|
||||
ready: false,
|
||||
@@ -76,11 +76,16 @@ impl DimBaselineCommand {
|
||||
text_rotation: f64,
|
||||
dimdli: f32,
|
||||
) -> Self {
|
||||
// The base dim's points enter as f32 from the caller; promote to f64 so
|
||||
// all committed-coordinate math downstream stays exact.
|
||||
let p1 = p1.as_dvec3();
|
||||
let definition_point = definition_point.as_dvec3();
|
||||
// Measurement axis = the base dim's rotation angle (any angle, incl. a
|
||||
// UCS-aligned one), not a world horizontal/vertical.
|
||||
let axis = Vec3::new(rotation.cos() as f32, rotation.sin() as f32, 0.0);
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let axis = DVec3::new(rotation.cos(), rotation.sin(), 0.0);
|
||||
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
||||
let base_offset = (definition_point - p1).dot(perp);
|
||||
let dimdli = dimdli as f64;
|
||||
let dimdli = if dimdli.abs() < 1e-6 {
|
||||
DEFAULT_DIMDLI
|
||||
} else {
|
||||
@@ -110,7 +115,7 @@ impl DimBaselineCommand {
|
||||
/// base origin and `p2` each projected INDEPENDENTLY onto the dim line (at
|
||||
/// the current stacking offset). Projecting both keeps the line straight
|
||||
/// even when the two origins aren't level — a shared offset tilts it. (#181)
|
||||
fn dim_line_pts(&self, p2: Vec3) -> (Vec3, Vec3) {
|
||||
fn dim_line_pts(&self, p2: DVec3) -> (DVec3, DVec3) {
|
||||
let target = self.base_p1.dot(self.perp) + self.next_offset;
|
||||
let d1 = self.base_p1 + self.perp * (target - self.base_p1.dot(self.perp));
|
||||
let d2 = p2 + self.perp * (target - p2.dot(self.perp));
|
||||
@@ -131,7 +136,7 @@ impl CadCommand for DimBaselineCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if !self.ready {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
@@ -162,12 +167,17 @@ impl CadCommand for DimBaselineCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
if !self.ready {
|
||||
return None;
|
||||
}
|
||||
let p1 = self.base_p1;
|
||||
// dim_line_pts stays in f64; downcast only here, into the preview's
|
||||
// [f32;3] GPU buffer — correct pixel-space, never touches committed geometry.
|
||||
let (dim_line_pt, dim_line_pt2) = self.dim_line_pts(pt);
|
||||
let p1 = self.base_p1.as_vec3();
|
||||
let dim_line_pt = dim_line_pt.as_vec3();
|
||||
let dim_line_pt2 = dim_line_pt2.as_vec3();
|
||||
let pt = pt.as_vec3();
|
||||
Some(WireModel {
|
||||
text_verts: Vec::new(),
|
||||
name: "dimbase_preview".into(),
|
||||
@@ -200,8 +210,8 @@ impl CadCommand for DimBaselineCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
pub struct DimContinueCommand {
|
||||
/// Fixed first-extension-line origin for the current step (moves each iteration).
|
||||
chain_p1: Vec3,
|
||||
chain_p1: DVec3,
|
||||
/// Direction along the dimension axis (0.0 = horizontal, PI/2 = vertical).
|
||||
rotation: f64,
|
||||
/// Text reading rotation inherited from the base dim so a UCS-aligned chain
|
||||
@@ -39,9 +39,9 @@ pub struct DimContinueCommand {
|
||||
/// coordinate so the whole chain stays collinear — even when the extension
|
||||
/// origins sit at different perpendicular positions (extension lines of
|
||||
/// different lengths). (#151)
|
||||
dim_line_perp: f32,
|
||||
dim_line_perp: f64,
|
||||
/// Direction of "up" perpendicular to the dim axis (points toward the dim line).
|
||||
perp: Vec3,
|
||||
perp: DVec3,
|
||||
/// True once we have a base dimension loaded.
|
||||
ready: bool,
|
||||
}
|
||||
@@ -50,11 +50,11 @@ impl DimContinueCommand {
|
||||
/// No base dim found — will show an error prompt and cancel immediately.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
chain_p1: Vec3::ZERO,
|
||||
chain_p1: DVec3::ZERO,
|
||||
rotation: 0.0,
|
||||
text_rotation: 0.0,
|
||||
dim_line_perp: 0.0,
|
||||
perp: Vec3::Y,
|
||||
perp: DVec3::Y,
|
||||
ready: false,
|
||||
}
|
||||
}
|
||||
@@ -75,11 +75,16 @@ impl DimContinueCommand {
|
||||
rotation: f64,
|
||||
text_rotation: f64,
|
||||
) -> Self {
|
||||
// Widen the base-dim points to f64 so the committed chain math runs in
|
||||
// full precision. (The base points arrive as f32 from the entity, but
|
||||
// every derived committed coordinate must stay f64 from here on.)
|
||||
let p2 = p2.as_dvec3();
|
||||
let definition_point = definition_point.as_dvec3();
|
||||
// Axis unit vector along the measurement direction — the base dim's
|
||||
// rotation angle (any angle, incl. a UCS-aligned one), not a world H/V.
|
||||
let axis = Vec3::new(rotation.cos() as f32, rotation.sin() as f32, 0.0);
|
||||
let axis = DVec3::new(rotation.cos(), rotation.sin(), 0.0);
|
||||
// Perpendicular unit vector toward the dim line.
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
||||
let dim_line_perp = definition_point.dot(perp);
|
||||
Self {
|
||||
chain_p1: p2,
|
||||
@@ -105,7 +110,7 @@ impl CadCommand for DimContinueCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if !self.ready {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
@@ -141,13 +146,18 @@ impl CadCommand for DimContinueCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
if !self.ready {
|
||||
return None;
|
||||
}
|
||||
let p1 = self.chain_p1;
|
||||
let dim_line_pt = p1 + self.perp * (self.dim_line_perp - p1.dot(self.perp));
|
||||
let dim_line_pt2 = pt + self.perp * (self.dim_line_perp - pt.dot(self.perp));
|
||||
// Preview / rubber-band geometry feeds an f32 GPU buffer, so drop to f32
|
||||
// at this screen-only boundary.
|
||||
let pt = pt.as_vec3();
|
||||
let p1 = self.chain_p1.as_vec3();
|
||||
let perp = self.perp.as_vec3();
|
||||
let dim_line_perp = self.dim_line_perp as f32;
|
||||
let dim_line_pt = p1 + perp * (dim_line_perp - p1.dot(perp));
|
||||
let dim_line_pt2 = pt + perp * (dim_line_perp - pt.dot(perp));
|
||||
Some(WireModel {
|
||||
text_verts: Vec::new(),
|
||||
name: "dimcont_preview".into(),
|
||||
@@ -180,8 +190,8 @@ impl CadCommand for DimContinueCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ impl CadCommand for DimJogLineCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let Step::PickJogPos { handle } = &self.step {
|
||||
let h = *handle;
|
||||
// Emit sentinel for commands.rs to store the jog position
|
||||
|
||||
@@ -69,13 +69,12 @@ impl CadCommand for DimTeditCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let Step::PickTextPos { handle, entity } = &mut self.step {
|
||||
let h = *handle;
|
||||
if let Some(mut ent) = entity.take() {
|
||||
if let EntityType::Dimension(ref mut d) = ent {
|
||||
let new_pt =
|
||||
acadrust::types::Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
let new_pt = acadrust::types::Vector3::new(pt.x, pt.y, pt.z);
|
||||
d.base_mut().text_middle_point = new_pt;
|
||||
d.base_mut().insertion_point = new_pt;
|
||||
// Pin the text to this location, else the renderer recomputes
|
||||
|
||||
@@ -31,7 +31,7 @@ pub fn tool() -> ToolDef {
|
||||
}
|
||||
|
||||
pub struct LeaderCommand {
|
||||
verts: Vec<Vec3>,
|
||||
verts: Vec<DVec3>,
|
||||
ucs: Mat4,
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ impl CadCommand for LeaderCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
self.verts.push(pt);
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -85,24 +85,24 @@ impl CadCommand for LeaderCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
if self.verts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut pts = self.verts.clone();
|
||||
pts.push(pt);
|
||||
let mut pts: Vec<Vec3> = self.verts.iter().map(|p| p.as_vec3()).collect();
|
||||
pts.push(pt.as_vec3());
|
||||
Some(preview_wire(&pts))
|
||||
}
|
||||
}
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn dv3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
fn build_leader(verts: &[Vec3], ucs: Mat4) -> Leader {
|
||||
let mut l = Leader::from_vertices(verts.iter().map(|p| v3(*p)).collect());
|
||||
fn build_leader(verts: &[DVec3], ucs: Mat4) -> Leader {
|
||||
let mut l = Leader::from_vertices(verts.iter().map(|p| dv3(*p)).collect());
|
||||
l.creation_type = LeaderCreationType::WithText;
|
||||
l.hookline_enabled = true;
|
||||
// The hookline / text read along the UCS X axis (DXF "horizontal direction
|
||||
@@ -116,17 +116,17 @@ fn build_leader(verts: &[Vec3], ucs: Mat4) -> Leader {
|
||||
/// keeps the text reading away from the leader (text to the right of a
|
||||
/// left-pointing landing, to the left of a right-pointing one).
|
||||
fn annotation_anchor(
|
||||
verts: &[Vec3],
|
||||
verts: &[DVec3],
|
||||
text_height: f64,
|
||||
ucs: Mat4,
|
||||
) -> (Vec3, AttachmentPoint) {
|
||||
) -> (DVec3, AttachmentPoint) {
|
||||
let last = *verts.last().unwrap();
|
||||
let prev = verts[verts.len() - 2];
|
||||
// Side + landing run along the UCS X axis (identity = world).
|
||||
let ux = ucs.transform_vector3(Vec3::X).normalize_or(Vec3::X);
|
||||
let ux = ucs.transform_vector3(Vec3::X).normalize_or(Vec3::X).as_dvec3();
|
||||
let to_right = (last - prev).dot(ux) >= 0.0;
|
||||
let sign = if to_right { 1.0_f32 } else { -1.0_f32 };
|
||||
let anchor = last + ux * (sign * text_height as f32 * 1.5);
|
||||
let sign = if to_right { 1.0_f64 } else { -1.0_f64 };
|
||||
let anchor = last + ux * (sign * text_height * 1.5);
|
||||
let attach = if to_right {
|
||||
AttachmentPoint::MiddleLeft
|
||||
} else {
|
||||
@@ -137,14 +137,14 @@ fn annotation_anchor(
|
||||
|
||||
fn build_mtext(
|
||||
text: &str,
|
||||
pos: Vec3,
|
||||
pos: DVec3,
|
||||
height: f64,
|
||||
attach: AttachmentPoint,
|
||||
ucs: Mat4,
|
||||
) -> MText {
|
||||
let mut m = MText::new();
|
||||
m.value = text.to_string();
|
||||
m.insertion_point = v3(pos);
|
||||
m.insertion_point = dv3(pos);
|
||||
m.height = height;
|
||||
m.attachment_point = attach;
|
||||
// Text reads along the UCS X axis.
|
||||
|
||||
@@ -10,10 +10,10 @@ use glam::{DVec3, Mat4, Vec3};
|
||||
/// World-space measurement axis for a linear dimension between `first` and
|
||||
/// `second`, chosen as the UCS X or Y axis (whichever the span is closer to).
|
||||
/// `ucs` is the UCS→wire affine; identity gives the world X/Y behaviour.
|
||||
fn measure_axis(first: Vec3, second: Vec3, ucs: Mat4) -> Vec3 {
|
||||
let ux = ucs.transform_vector3(Vec3::X).normalize_or(Vec3::X);
|
||||
let uy = ucs.transform_vector3(Vec3::Y).normalize_or(Vec3::Y);
|
||||
let du = ucs.inverse().transform_vector3(second - first);
|
||||
fn measure_axis(first: DVec3, second: DVec3, ucs: Mat4) -> DVec3 {
|
||||
let ux = ucs.transform_vector3(Vec3::X).normalize_or(Vec3::X).as_dvec3();
|
||||
let uy = ucs.transform_vector3(Vec3::Y).normalize_or(Vec3::Y).as_dvec3();
|
||||
let du = ucs.inverse().transform_vector3((second - first).as_vec3());
|
||||
if du.x.abs() >= du.y.abs() {
|
||||
ux
|
||||
} else {
|
||||
@@ -34,8 +34,8 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
FirstPoint,
|
||||
SecondPoint(Vec3),
|
||||
DimensionLine { first: Vec3, second: Vec3 },
|
||||
SecondPoint(DVec3),
|
||||
DimensionLine { first: DVec3, second: DVec3 },
|
||||
}
|
||||
|
||||
pub struct LinearDimensionCommand {
|
||||
@@ -91,7 +91,7 @@ impl CadCommand for LinearDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::FirstPoint => {
|
||||
self.step = Step::SecondPoint(pt);
|
||||
@@ -106,7 +106,7 @@ impl CadCommand for LinearDimensionCommand {
|
||||
// Measure along the UCS axis the span is closest to; the DXF
|
||||
// rotation is that axis's angle in world space.
|
||||
let axis = measure_axis(first, second, self.ucs);
|
||||
dim.rotation = (axis.y as f64).atan2(axis.x as f64);
|
||||
dim.rotation = axis.y.atan2(axis.x);
|
||||
// Bake the UCS X-axis angle as the text rotation so the
|
||||
// measurement text reads horizontally in the UCS (i.e. square on
|
||||
// screen) regardless of the style's force-horizontal flags,
|
||||
@@ -200,7 +200,7 @@ impl CadCommand for LinearDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
match self.step {
|
||||
Step::FirstPoint => None,
|
||||
Step::SecondPoint(first) => Some(preview_wire(vec![first, pt])),
|
||||
@@ -212,15 +212,18 @@ impl CadCommand for LinearDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(pt: Vec3) -> Vector3 {
|
||||
Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64)
|
||||
fn v3(pt: DVec3) -> Vector3 {
|
||||
Vector3::new(pt.x, pt.y, pt.z)
|
||||
}
|
||||
|
||||
fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
fn preview_wire(points: Vec<DVec3>) -> WireModel {
|
||||
WireModel {
|
||||
text_verts: Vec::new(),
|
||||
name: "dimlinear_preview".to_string(),
|
||||
points: points.into_iter().map(|p| [p.x, p.y, p.z]).collect(),
|
||||
points: points
|
||||
.into_iter()
|
||||
.map(|p| [p.x as f32, p.y as f32, p.z as f32])
|
||||
.collect(),
|
||||
points_low: Vec::new(),
|
||||
color: WireModel::CYAN,
|
||||
selected: false,
|
||||
@@ -244,23 +247,23 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
/// single shared offset only lands both on the line when they are level, and
|
||||
/// tilts the dimension line when they are not (e.g. measuring across sloped
|
||||
/// points). See #181.
|
||||
fn dim_line_endpoints(first: Vec3, second: Vec3, def: Vec3, axis: Vec3) -> (Vec3, Vec3) {
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
fn dim_line_endpoints(first: DVec3, second: DVec3, def: DVec3, axis: DVec3) -> (DVec3, DVec3) {
|
||||
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
||||
let dperp = def.dot(perp);
|
||||
let d1 = first + perp * (dperp - first.dot(perp));
|
||||
let d2 = second + perp * (dperp - second.dot(perp));
|
||||
(d1, d2)
|
||||
}
|
||||
|
||||
fn linear_dimension_preview(first: Vec3, second: Vec3, def: Vec3, axis: Vec3) -> Vec<Vec3> {
|
||||
fn linear_dimension_preview(first: DVec3, second: DVec3, def: DVec3, axis: DVec3) -> Vec<DVec3> {
|
||||
let (d1, d2) = dim_line_endpoints(first, second, def, axis);
|
||||
let nan = Vec3::new(f32::NAN, f32::NAN, f32::NAN);
|
||||
let nan = DVec3::new(f64::NAN, f64::NAN, f64::NAN);
|
||||
vec![first, d1, nan, second, d2, nan, d1, d2]
|
||||
}
|
||||
|
||||
fn linear_text_pos(first: Vec3, second: Vec3, def: Vec3, axis: Vec3) -> Vec3 {
|
||||
fn linear_text_pos(first: DVec3, second: DVec3, def: DVec3, axis: DVec3) -> DVec3 {
|
||||
let (d1, d2) = dim_line_endpoints(first, second, def, axis);
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
||||
(d1 + d2) * 0.5 + perp * 0.15
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn tool() -> ToolDef {
|
||||
}
|
||||
|
||||
pub struct MLeaderCommand {
|
||||
verts: Vec<Vec3>,
|
||||
verts: Vec<DVec3>,
|
||||
ucs: Mat4,
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ impl CadCommand for MLeaderCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
self.verts.push(pt);
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -75,23 +75,24 @@ impl CadCommand for MLeaderCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
if self.verts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut pts = self.verts.clone();
|
||||
pts.push(pt);
|
||||
// Preview / rubber-band is GPU screen-space: downcast to f32 here.
|
||||
let mut pts: Vec<Vec3> = self.verts.iter().map(|p| p.as_vec3()).collect();
|
||||
pts.push(pt.as_vec3());
|
||||
Some(preview_wire(&pts))
|
||||
}
|
||||
}
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
fn build_mleader(text: &str, verts: &[Vec3], ucs: Mat4) -> MultiLeader {
|
||||
fn build_mleader(text: &str, verts: &[DVec3], ucs: Mat4) -> MultiLeader {
|
||||
// Last vertex = content/text location; remaining = leader line points
|
||||
let (leader_pts, content_pt) = verts.split_at(verts.len() - 1);
|
||||
let content_pt = content_pt[0];
|
||||
@@ -113,7 +114,7 @@ fn build_mleader(text: &str, verts: &[Vec3], ucs: Mat4) -> MultiLeader {
|
||||
let ux = ucs.transform_vector3(Vec3::X).normalize_or(Vec3::X);
|
||||
// Which side of the leader the text sits on, measured along the UCS X axis.
|
||||
let last_leader = leader_pts.last().copied().unwrap_or(content_pt);
|
||||
let to_right = (content_pt - last_leader).dot(ux) >= 0.0;
|
||||
let to_right = (content_pt - last_leader).dot(ux.as_dvec3()) >= 0.0;
|
||||
let sign = if to_right { 1.0 } else { -1.0 };
|
||||
let landing = ux * (sign as f32);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ enum AddStep {
|
||||
CollectPoints {
|
||||
handle: Handle,
|
||||
entity: EntityType,
|
||||
pts: Vec<Vec3>,
|
||||
pts: Vec<DVec3>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ impl CadCommand for MLeaderAddCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match &mut self.step {
|
||||
AddStep::PickArrowhead { handle, entity } => {
|
||||
if let Some(ent) = entity.take() {
|
||||
@@ -121,7 +121,7 @@ impl CadCommand for MLeaderAddCommand {
|
||||
// Add a new leader root with the collected points
|
||||
let points: Vec<Vector3> = pts
|
||||
.iter()
|
||||
.map(|p| Vector3::new(p.x as f64, p.y as f64, p.z as f64))
|
||||
.map(|p| Vector3::new(p.x, p.y, p.z))
|
||||
.collect();
|
||||
let root = ml.context.add_leader_root();
|
||||
root.create_line(points);
|
||||
@@ -132,14 +132,16 @@ impl CadCommand for MLeaderAddCommand {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let existing_pts = match &self.step {
|
||||
AddStep::CollectPoints { pts, .. } => pts.clone(),
|
||||
_ => return None,
|
||||
};
|
||||
let mut all_pts = existing_pts;
|
||||
all_pts.push(pt);
|
||||
Some(preview_wire(&all_pts))
|
||||
Some(preview_wire(
|
||||
&all_pts.iter().map(|p| p.as_vec3()).collect::<Vec<_>>(),
|
||||
))
|
||||
}
|
||||
|
||||
fn inject_picked_entity(&mut self, entity: EntityType) {
|
||||
@@ -275,7 +277,7 @@ pub fn tool_align() -> ToolDef {
|
||||
enum AlignStep {
|
||||
Gathering,
|
||||
PickDirection { handles: Vec<Handle> },
|
||||
PickEndDir { handles: Vec<Handle>, from: Vec3 },
|
||||
PickEndDir { handles: Vec<Handle>, from: DVec3 },
|
||||
}
|
||||
|
||||
pub struct MLeaderAlignCommand {
|
||||
@@ -321,7 +323,7 @@ impl CadCommand for MLeaderAlignCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match &mut self.step {
|
||||
AlignStep::PickDirection { handles } => {
|
||||
let h = handles.clone();
|
||||
@@ -423,7 +425,7 @@ impl CadCommand for MLeaderCollectCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let CollectStep::PickLocation { handles } = &self.step {
|
||||
let h = handles.clone();
|
||||
// Build a new combined multileader at the collection point, delete originals.
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
FeaturePoint,
|
||||
LeaderEndpoint { feature: Vec3 },
|
||||
LeaderEndpoint { feature: DVec3 },
|
||||
}
|
||||
|
||||
pub struct OrdinateDimCommand {
|
||||
@@ -55,7 +55,7 @@ impl CadCommand for OrdinateDimCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::FeaturePoint => {
|
||||
self.step = Step::LeaderEndpoint { feature: pt };
|
||||
@@ -80,25 +80,30 @@ impl CadCommand for OrdinateDimCommand {
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let feature = match self.step {
|
||||
Step::LeaderEndpoint { feature } => feature,
|
||||
_ => return None,
|
||||
};
|
||||
let is_x = is_x_type(feature, pt);
|
||||
let elbow = ordinate_elbow(feature, pt, is_x);
|
||||
Some(preview_wire(vec![feature, elbow, pt]))
|
||||
// Screen-only rubber band: downcast to f32 at the preview boundary.
|
||||
Some(preview_wire(vec![
|
||||
feature.as_vec3(),
|
||||
elbow.as_vec3(),
|
||||
pt.as_vec3(),
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
fn v3(p: DVec3) -> Vector3 {
|
||||
Vector3::new(p.x, p.y, p.z)
|
||||
}
|
||||
|
||||
/// X-datum (labels the feature's X coordinate) when the leader runs more
|
||||
/// vertically than horizontally; Y-datum otherwise. Mirrors the placement
|
||||
/// decision so the preview and the committed entity agree.
|
||||
fn is_x_type(feature: Vec3, leader: Vec3) -> bool {
|
||||
fn is_x_type(feature: DVec3, leader: DVec3) -> bool {
|
||||
let dx = (leader.x - feature.x).abs();
|
||||
let dy = (leader.y - feature.y).abs();
|
||||
dy >= dx
|
||||
@@ -106,11 +111,11 @@ fn is_x_type(feature: Vec3, leader: Vec3) -> bool {
|
||||
|
||||
/// Orthogonal elbow of the ordinate leader: an X-datum runs along Y from the
|
||||
/// feature then jogs across in X; a Y-datum runs along X then jogs in Y.
|
||||
fn ordinate_elbow(feature: Vec3, leader: Vec3, is_x: bool) -> Vec3 {
|
||||
fn ordinate_elbow(feature: DVec3, leader: DVec3, is_x: bool) -> DVec3 {
|
||||
if is_x {
|
||||
Vec3::new(feature.x, leader.y, feature.z)
|
||||
DVec3::new(feature.x, leader.y, feature.z)
|
||||
} else {
|
||||
Vec3::new(leader.x, feature.y, feature.z)
|
||||
DVec3::new(leader.x, feature.y, feature.z)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use acadrust::entities::{Dimension, DimensionLinear};
|
||||
use acadrust::types::Vector3;
|
||||
use acadrust::{EntityType, Handle};
|
||||
use glam::{DVec3, Vec3};
|
||||
use glam::DVec3;
|
||||
|
||||
use crate::command::{CadCommand, CmdResult};
|
||||
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
||||
@@ -67,9 +67,11 @@ impl CadCommand for QdimCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let Step::PlaceLine { handles } = &self.step {
|
||||
CmdResult::Relaunch(
|
||||
// Keep the picked placement point in full f64 precision so the
|
||||
// committed dimension coordinates are not quantized to f32.
|
||||
format!("QDIM_PLACE {:.6} {:.6} {:.6}", pt.x, pt.y, pt.z),
|
||||
handles.clone(),
|
||||
)
|
||||
@@ -112,8 +114,8 @@ impl CadCommand for QdimCommand {
|
||||
|
||||
/// Build a linear dimension between two points at the given dimension-line position.
|
||||
#[allow(dead_code)]
|
||||
pub fn make_linear_dim(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> EntityType {
|
||||
let v = |p: Vec3| Vector3::new(p.x as f64, p.y as f64, p.z as f64);
|
||||
pub fn make_linear_dim(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> EntityType {
|
||||
let v = |p: DVec3| Vector3::new(p.x, p.y, p.z);
|
||||
let mut dim = DimensionLinear::new(v(p1), v(p2));
|
||||
// Determine axis: horizontal if Δx > Δz, else vertical
|
||||
let dx = (p2.x - p1.x).abs();
|
||||
|
||||
@@ -20,8 +20,8 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
CenterPoint,
|
||||
RadiusPoint(Vec3),
|
||||
TextPoint { center: Vec3, point: Vec3 },
|
||||
RadiusPoint(DVec3),
|
||||
TextPoint { center: DVec3, point: DVec3 },
|
||||
}
|
||||
|
||||
pub struct RadiusDimensionCommand {
|
||||
@@ -69,7 +69,7 @@ impl CadCommand for RadiusDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
match self.step {
|
||||
Step::CenterPoint => {
|
||||
self.step = Step::RadiusPoint(pt);
|
||||
@@ -84,7 +84,7 @@ impl CadCommand for RadiusDimensionCommand {
|
||||
dim.base.definition_point = v3(point);
|
||||
dim.base.text_middle_point = v3(pt);
|
||||
dim.base.insertion_point = v3(pt);
|
||||
dim.leader_length = point.distance(pt) as f64;
|
||||
dim.leader_length = point.distance(pt);
|
||||
dim.base.actual_measurement = dim.measurement();
|
||||
dim.base.user_text = self.text_override.clone();
|
||||
// An explicit text angle overrides the default rotation.
|
||||
@@ -163,23 +163,24 @@ impl CadCommand for RadiusDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
|
||||
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
||||
let pt = pt.as_vec3();
|
||||
match self.step {
|
||||
Step::CenterPoint => None,
|
||||
Step::RadiusPoint(center) => Some(preview_wire(vec![center, pt])),
|
||||
Step::RadiusPoint(center) => Some(preview_wire(vec![center.as_vec3(), pt])),
|
||||
Step::TextPoint { center, point } => Some(preview_wire(vec![
|
||||
center,
|
||||
point,
|
||||
center.as_vec3(),
|
||||
point.as_vec3(),
|
||||
Vec3::new(f32::NAN, f32::NAN, f32::NAN),
|
||||
point,
|
||||
point.as_vec3(),
|
||||
pt,
|
||||
])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(pt: Vec3) -> Vector3 {
|
||||
Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64)
|
||||
fn v3(pt: DVec3) -> Vector3 {
|
||||
Vector3::new(pt.x, pt.y, pt.z)
|
||||
}
|
||||
|
||||
fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
|
||||
@@ -116,9 +116,9 @@ impl CadCommand for TableCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let Step::Insertion { cols, rows } = self.step {
|
||||
let ins = Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
let ins = Vector3::new(pt.x, pt.y, pt.z);
|
||||
let table = TableBuilder::new(rows, cols)
|
||||
.at(ins)
|
||||
.row_height(ROW_HEIGHT)
|
||||
|
||||
@@ -64,9 +64,9 @@ impl CadCommand for ToleranceCommand {
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
|
||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||
if let Step::Insertion { text } = &self.step {
|
||||
let ins = Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
let ins = Vector3::new(pt.x, pt.y, pt.z);
|
||||
let tol = Tolerance::with_text(ins, text.clone());
|
||||
CmdResult::CommitAndExit(EntityType::Tolerance(tol))
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user