cadcraft/crates/engine/tests/annotate_options.rs

141 lines
5.0 KiB
Rust

//! Options listed at the dimension and multileader prompts take effect (#243).
use cadcraft_engine::Session;
use cadcraft_engine::doc::{DimKind, Dimension, EntityKind, MLeader};
use cadcraft_engine::geom::Vec2;
fn last(s: &Session) -> EntityKind {
s.doc().unwrap().model.last().unwrap().kind.clone()
}
fn last_dim(s: &Session) -> Dimension {
match last(s) {
EntityKind::Dimension(d) => d,
other => panic!("not a dimension: {other:?}"),
}
}
fn last_mleader(s: &Session) -> MLeader {
match last(s) {
EntityKind::MLeader(m) => m,
other => panic!("not a multileader: {other:?}"),
}
}
fn value(s: &Session, d: &Dimension) -> String {
cadcraft_engine::render::dimension_in(s.doc().unwrap(), d).value
}
fn near(a: Vec2, b: Vec2) -> bool {
a.dist(b) < 1e-6
}
#[test]
fn dimlinear_angle_rotates_the_text_and_text_replaces_it() {
let mut s = Session::new();
s.script("dimlinear 0,0 10,0 a 30 t\nX=<>\n5,-3\n").unwrap();
let d = last_dim(&s);
assert_eq!(d.kind, DimKind::Linear { rotation: 0.0 }, "Angle must not rotate the dimension line");
assert!((d.text_rotation - 30f64.to_radians()).abs() < 1e-9, "{}", d.text_rotation);
assert_eq!(d.text, "X=<>");
assert!(s.running.is_none());
}
#[test]
fn dimlinear_vertical_forces_the_orientation() {
let mut s = Session::new();
s.script("dimlinear 0,0 10,5 v").unwrap();
let p = s.prompt_text();
assert!(p.contains("[Mtext/Text/Angle]"), "{p}");
s.script("5,-3\n").unwrap();
assert_eq!(last_dim(&s).kind, DimKind::Linear { rotation: std::f64::consts::FRAC_PI_2 });
}
#[test]
fn dimordinate_datum_and_text_options() {
let mut s = Session::new();
// The leader endpoint alone would make a Y datum; Xdatum forces X, and Text is a text option.
s.script("dimordinate 0,0 x t\nA <>\n10,2\n").unwrap();
let d = last_dim(&s);
assert_eq!(d.kind, DimKind::Ordinate { x_type: true });
assert_eq!(d.text, "A <>");
s.script("dimordinate 0,0 y a 90 2,10\n").unwrap();
let d = last_dim(&s);
assert_eq!(d.kind, DimKind::Ordinate { x_type: false });
assert!((d.text_rotation - std::f64::consts::FRAC_PI_2).abs() < 1e-9);
}
#[test]
fn dimradius_text_options() {
let mut s = Session::new();
s.script("circle 0,0 5\ndimradius 5,0 t\nR=<>\na 45 8,8\n").unwrap();
let d = last_dim(&s);
assert_eq!(d.kind, DimKind::Radius);
assert_eq!(d.text, "R=<>");
assert!((d.text_rotation - 45f64.to_radians()).abs() < 1e-9);
}
#[test]
fn dimangular_quadrant_locks_the_measured_angle() {
let mut s = Session::new();
// Placed at (-3,-4) the arc would measure the 270° side; the quadrant keeps the 90° one.
s.script("dimangular\n\n0,0 10,0 0,10 q 5,5 -3,-4\n").unwrap();
let d = last_dim(&s);
assert_eq!(value(&s, &d), "90°");
assert!(near(d.defpt.xy(), Vec2::new(5.0, 5.0).normalized() * 5.0), "{:?}", d.defpt);
}
#[test]
fn dimarc_partial_measures_part_of_the_arc() {
let mut s = Session::new();
s.script("arc c 0,0 -10,0 10,0\n").unwrap();
assert!(matches!(last(&s), EntityKind::Arc(_)), "{:?}", last(&s));
s.script("dimarc 0,-10 p 10,0 0,-10 5,-12\n").unwrap();
let d = last_dim(&s);
assert_eq!(d.kind, DimKind::ArcLength);
assert!(near(d.p13.xy(), Vec2::new(0.0, -10.0)) && near(d.p14.xy(), Vec2::new(10.0, 0.0)), "{d:?}");
assert_eq!(value(&s, &d), "⌒15.7080");
}
#[test]
fn mleader_landing_first_and_content_first() {
let mut s = Session::new();
s.script("mleader l 10,5 0,0 note\n").unwrap();
let m = last_mleader(&s);
assert_eq!(m.leaders.len(), 1);
assert!(near(m.leaders[0][0].xy(), Vec2::ZERO) && near(m.landing.xy(), Vec2::new(10.0, 5.0)), "{m:?}");
assert_eq!(m.text.unwrap().contents, "note");
s.script("mleader c 10,5 hello\n0,0\n").unwrap();
let m = last_mleader(&s);
assert!(near(m.leaders[0][0].xy(), Vec2::ZERO) && near(m.landing.xy(), Vec2::new(10.0, 5.0)), "{m:?}");
assert_eq!(m.text.unwrap().contents, "hello");
}
#[test]
fn mleader_options_take_effect() {
let mut s = Session::new();
// Enter opens Options; Maxpoints 3 and no landing line.
s.script("mleader\n\nm 3 a n x 0,0 5,5 10,5 txt\n").unwrap();
let m = last_mleader(&s);
assert_eq!(m.leaders[0].len(), 2, "{m:?}");
assert!(near(m.leaders[0][1].xy(), Vec2::new(5.0, 5.0)) && near(m.landing.xy(), Vec2::new(10.0, 5.0)));
assert_eq!(m.dogleg, 0.0);
assert_eq!(m.text.unwrap().contents, "txt");
// First angle constraint snaps the leader to 45° steps (a new session: MLEADER would keep the
// Maxpoints and landing chosen above).
let mut s = Session::new();
s.script("mleader o f 45 x 0,0 10,8 note\n").unwrap();
let m = last_mleader(&s);
let r = Vec2::new(10.0, 8.0).len();
assert!(near(m.landing.xy(), Vec2::new(r, r) / 2f64.sqrt()), "{:?}", m.landing);
// Leader type sPline keeps the following input and draws a spline leader.
s.script("mleader o l p x 0,0 4,4 hi\n").unwrap();
let m = last_mleader(&s);
assert!(m.spline);
assert_eq!(m.text.unwrap().contents, "hi");
assert!(s.running.is_none());
}