feat: DIMORDINATE + mark Named UCS saving and DIMORDINATE complete

- ordinate_dim.rs: OrdinateDimCommand picks feature point then leader
  endpoint; auto-detects X vs Y ordinate from movement direction
- Ordinate dim added to the Dimensions dropdown in the Annotate ribbon
- ROADMAP.md: DIMORDINATE , Named UCS (already implemented) 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-04-08 00:21:35 +03:00
commit d2a58bdd08
4 changed files with 90 additions and 1 deletions

View file

@ -194,7 +194,7 @@ Underlay (PDF/DWF/DGN)
| Plot Window önizleme | ✅ |
| UCS (WCS↔UCS dönüşüm pipeline) | ✅ |
| Named Views (VIEW komutu) | ✅ |
| Named UCS kaydetme | |
| Named UCS kaydetme | ✅ UCS SAVE/DELETE/LIST |
| VPORTS (viewport bölme) | ⬜ |
| Nesne snap izleme (Object Snap Tracking) | ⬜ |
| Dynamic Input overlay | ✅ F12 toggle, absolute XY + relative dist/angle |

View file

@ -1077,6 +1077,13 @@ impl H7CAD {
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
}
"DIMORDINATE"|"DOR" => {
use crate::modules::annotate::ordinate_dim::OrdinateDimCommand;
let new_cmd = OrdinateDimCommand::new();
self.command_line.push_info(&new_cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
}
"LEADER"|"LE" => {
use crate::modules::annotate::leader_cmd::LeaderCommand;
let new_cmd = LeaderCommand::new();

View file

@ -13,6 +13,7 @@ pub mod mtext;
pub mod radius_dim;
pub mod table_cmd;
pub mod text;
pub mod ordinate_dim;
pub mod tolerance_cmd;
use crate::modules::{CadModule, RibbonGroup, RibbonItem};
@ -55,6 +56,7 @@ impl CadModule for AnnotateModule {
(linear_dim::tool().id, linear_dim::tool().label, linear_dim::tool().icon),
(radius_dim::tool().id, radius_dim::tool().label, radius_dim::tool().icon),
(angular_dim::tool().id, angular_dim::tool().label, angular_dim::tool().icon),
(ordinate_dim::tool().id, ordinate_dim::tool().label, ordinate_dim::tool().icon),
],
default: "DIMLINEAR",
},

View file

@ -0,0 +1,80 @@
// DIMORDINATE command — ordinate (datum) dimension.
//
// Measures the X or Y distance from the UCS origin (datum) to a feature point.
// The user picks:
// 1. The feature location.
// 2. The leader endpoint (where the annotation line ends).
//
// If the leader moves mainly in Y → X-type ordinate (shows X coordinate).
// If the leader moves mainly in X → Y-type ordinate (shows Y coordinate).
use acadrust::entities::{Dimension, DimensionOrdinate};
use acadrust::types::Vector3;
use acadrust::EntityType;
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::wire_model::WireModel;
pub fn tool() -> ToolDef {
ToolDef {
id: "DIMORDINATE",
label: "Ordinate",
icon: IconKind::Glyph("Φ"),
event: ModuleEvent::Command("DIMORDINATE".to_string()),
}
}
enum Step {
FeaturePoint,
LeaderEndpoint { feature: Vec3 },
}
pub struct OrdinateDimCommand {
step: Step,
}
impl OrdinateDimCommand {
pub fn new() -> Self {
Self { step: Step::FeaturePoint }
}
}
impl CadCommand for OrdinateDimCommand {
fn name(&self) -> &'static str { "DIMORDINATE" }
fn prompt(&self) -> String {
match self.step {
Step::FeaturePoint => "DIMORDINATE Specify feature location:".into(),
Step::LeaderEndpoint { .. } => "DIMORDINATE Specify leader endpoint:".into(),
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
match self.step {
Step::FeaturePoint => {
self.step = Step::LeaderEndpoint { feature: pt };
CmdResult::NeedPoint
}
Step::LeaderEndpoint { feature } => {
let dx = (pt.x - feature.x).abs();
let dy = (pt.z - feature.z).abs();
// If leader is more vertical (Y-screen = Z-world moves more) → X ordinate.
// If leader is more horizontal → Y ordinate.
let is_x = dy >= dx;
let feat_v3 = v3(feature);
let lead_v3 = v3(pt);
let dim = DimensionOrdinate::new(feat_v3, lead_v3, is_x);
CmdResult::CommitAndExit(EntityType::Dimension(Dimension::Ordinate(dim)))
}
}
}
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
fn on_preview_wires(&mut self, _pt: Vec3) -> Vec<WireModel> { vec![] }
}
fn v3(p: Vec3) -> Vector3 {
Vector3::new(p.x as f64, 0.0, p.z as f64)
}