100 lines
3.8 KiB
Rust
100 lines
3.8 KiB
Rust
//! OFFSET Erase/Layer/Multiple/Undo and the MOVE/COPY Displacement option at the command line.
|
|
|
|
use cadcraft_engine::Session;
|
|
use cadcraft_engine::doc::EntityKind;
|
|
use serde_json::json;
|
|
|
|
/// Every line as ((ax, ay), (bx, by), layer), sorted by the first y.
|
|
fn lines(s: &Session) -> Vec<((f64, f64), (f64, f64), String)> {
|
|
let mut v: Vec<_> = s
|
|
.doc()
|
|
.unwrap()
|
|
.model
|
|
.iter()
|
|
.filter_map(|e| if let EntityKind::Line(l) = &e.kind { Some(((l.a.x, l.a.y), (l.b.x, l.b.y), e.common.layer.clone())) } else { None })
|
|
.collect();
|
|
v.sort_by(|a, b| a.0.1.total_cmp(&b.0.1).then(a.0.0.total_cmp(&b.0.0)));
|
|
v
|
|
}
|
|
|
|
fn one_line() -> Session {
|
|
let mut s = Session::new();
|
|
s.cmdline("LINE 0,0 10,0").unwrap();
|
|
s.cmdline("").unwrap();
|
|
s
|
|
}
|
|
|
|
fn l(a: (f64, f64), b: (f64, f64), layer: &str) -> ((f64, f64), (f64, f64), String) {
|
|
(a, b, layer.to_string())
|
|
}
|
|
|
|
#[test]
|
|
fn offset_erase_source() {
|
|
let mut s = one_line();
|
|
s.script("OFFSET E Y 2 5,0 5,1\n\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((0.0, 2.0), (10.0, 2.0), "0")]);
|
|
// The choice is remembered: the next OFFSET erases the source too, until No.
|
|
s.script("OFFSET 2 5,2 5,3\n\n").unwrap();
|
|
assert_eq!(lines(&s), vec![l((0.0, 4.0), (10.0, 4.0), "0")]);
|
|
s.script("OFFSET E N 2 5,4 5,5\n\n").unwrap();
|
|
assert_eq!(lines(&s).len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
fn offset_layer_current() {
|
|
let mut s = one_line();
|
|
s.execute("layer.new", &json!({ "name": "Other", "current": true })).unwrap();
|
|
s.script("OFFSET L C 2 5,0 5,1\n\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((0.0, 0.0), (10.0, 0.0), "0"), l((0.0, 2.0), (10.0, 2.0), "Other")]);
|
|
// Source (the default) keeps the source object's layer.
|
|
s.script("OFFSET L S 2 5,0 5,-1\n\n").unwrap();
|
|
assert_eq!(lines(&s).first(), Some(&l((0.0, -2.0), (10.0, -2.0), "0")));
|
|
}
|
|
|
|
#[test]
|
|
fn offset_multiple_and_undo() {
|
|
let mut s = one_line();
|
|
// Multiple: each side point offsets the newest copy again; Undo takes the last one back.
|
|
s.script("OFFSET 2 5,0 M 5,1 5,3 5,5 U\n\n\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((0.0, 0.0), (10.0, 0.0), "0"), l((0.0, 2.0), (10.0, 2.0), "0"), l((0.0, 4.0), (10.0, 4.0), "0")]);
|
|
}
|
|
|
|
#[test]
|
|
fn offset_json_erase_and_layer() {
|
|
let mut s = one_line();
|
|
s.execute("layer.new", &json!({ "name": "Other", "current": true })).unwrap();
|
|
let h = s.doc().unwrap().model.iter().next().unwrap().handle.hex();
|
|
s.execute("offset", &json!({ "handle": h, "distance": 2, "side": [5, 1], "erase": true, "layer": "current" })).unwrap();
|
|
assert_eq!(lines(&s), vec![l((0.0, 2.0), (10.0, 2.0), "Other")]);
|
|
}
|
|
|
|
#[test]
|
|
fn move_displacement() {
|
|
// The Displacement keyword asks for the displacement directly.
|
|
let mut s = one_line();
|
|
s.script("MOVE 5,0 D 3,4\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((3.0, 4.0), (13.0, 4.0), "0")]);
|
|
// Enter at the base point prompt does the same.
|
|
let mut s = one_line();
|
|
s.script("MOVE 5,0\n\n\n3,4\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((3.0, 4.0), (13.0, 4.0), "0")]);
|
|
// Base and second point still work.
|
|
let mut s = one_line();
|
|
s.script("MOVE 5,0 1,1 2,3\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((1.0, 2.0), (11.0, 2.0), "0")]);
|
|
}
|
|
|
|
#[test]
|
|
fn copy_displacement() {
|
|
let mut s = one_line();
|
|
s.script("COPY 5,0 D 0,3\n").unwrap();
|
|
assert!(s.running.is_none(), "{}", s.prompt_text());
|
|
assert_eq!(lines(&s), vec![l((0.0, 0.0), (10.0, 0.0), "0"), l((0.0, 3.0), (10.0, 3.0), "0")]);
|
|
}
|