mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 20:36:02 +00:00
Merge pull request #7418 from dotCooCoo/fix/reflected-dimension-line
Dimension tool: a reflected aligned dimension has its line on the reflected side
This commit is contained in:
@@ -815,6 +815,10 @@ impl Dimension {
|
||||
if self.line_between_points() && !old.line_between_points() {
|
||||
self.keep_gap(&old);
|
||||
}
|
||||
} else if self.mode == DimensionMode::Linear && xf.determinant() < 0.0 && (self.b - self.a).hypot() > 1e-9 {
|
||||
// A reflection turns the left normal of a → b to the other side, so an aligned
|
||||
// dimension's line stays on the reflected side of its points.
|
||||
self.offset = -self.offset;
|
||||
}
|
||||
if self.mode == DimensionMode::Linear {
|
||||
self.length = self.measured();
|
||||
|
||||
@@ -419,6 +419,56 @@ fn a_reflected_horizontal_dimension_keeps_its_line_on_the_reflected_side() {
|
||||
assert_eq!(text(&s, id), "100.00 pt");
|
||||
}
|
||||
|
||||
/// An unlinked aligned dimension reflected on its own has its line on the reflected side of its
|
||||
/// points: a line 30 pt above a level pair is 30 pt below it after a flip top to bottom, and a
|
||||
/// half turn moves it below them as well, by turning it.
|
||||
#[test]
|
||||
fn a_reflected_aligned_dimension_keeps_its_line_on_the_reflected_side() {
|
||||
let mut s = session();
|
||||
let id = run(&mut s, "dimension.create", json!({"a":[100,200],"b":[200,200],"offset":-30}))["id"].as_u64().unwrap();
|
||||
assert_eq!(path_ends(&s, id)[2], vec![(100.0, 170.0), (200.0, 170.0)]);
|
||||
run(&mut s, "select.set", json!({"ids":[id]}));
|
||||
run(&mut s, "object.reflect", json!({"axis":"horizontal","origin":[0,200]}));
|
||||
assert_eq!(path_ends(&s, id)[2], vec![(100.0, 230.0), (200.0, 230.0)]);
|
||||
assert_eq!(text(&s, id), "100.00 pt");
|
||||
// Reflected left to right, the points swap ends and the line stays below them.
|
||||
run(&mut s, "object.reflect", json!({"axis":"vertical","origin":[150,0]}));
|
||||
assert_eq!(path_ends(&s, id)[2], vec![(200.0, 230.0), (100.0, 230.0)]);
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
assert_eq!(path_ends(&s, id)[2], vec![(100.0, 170.0), (200.0, 170.0)]);
|
||||
// A half turn about the points' midpoint puts the line below them by turning it.
|
||||
run(&mut s, "object.rotate", json!({"angle":180,"origin":[150,200]}));
|
||||
let ends = path_ends(&s, id)[2].iter().map(|(x, y)| (x.round(), y.round())).collect::<Vec<_>>();
|
||||
assert_eq!(ends, vec![(200.0, 230.0), (100.0, 230.0)]);
|
||||
}
|
||||
|
||||
/// An unlinked aligned dimension of a diagonal pair reflected about a mirror line through its
|
||||
/// points has its line on the other side of them, and a scale by a negative factor reverses the
|
||||
/// side as a reflection does, while a scale by positive factors keeps it.
|
||||
#[test]
|
||||
fn an_aligned_dimension_reflected_about_an_angle_or_scaled_by_a_negative_factor_changes_sides() {
|
||||
let mut s = session();
|
||||
let id = run(&mut s, "dimension.create", json!({"a":[100,200],"b":[200,100],"offset":-30}))["id"].as_u64().unwrap();
|
||||
let k = 30.0 / 2f64.sqrt();
|
||||
let near = |got: &[(f64, f64)], want: [(f64, f64); 2]| got.iter().zip(want).all(|(g, w)| (g.0 - w.0).abs() < 1e-6 && (g.1 - w.1).abs() < 1e-6);
|
||||
let ends = path_ends(&s, id)[2].clone();
|
||||
assert!(near(&ends, [(100.0 - k, 200.0 - k), (200.0 - k, 100.0 - k)]), "{ends:?}");
|
||||
run(&mut s, "select.set", json!({"ids":[id]}));
|
||||
// The mirror line at 45 degrees through (150, 150) holds both points.
|
||||
run(&mut s, "object.reflect", json!({"axis":45,"origin":[150,150]}));
|
||||
let ends = path_ends(&s, id)[2].clone();
|
||||
assert!(near(&ends, [(100.0 + k, 200.0 + k), (200.0 + k, 100.0 + k)]), "{ends:?}");
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
let level = run(&mut s, "dimension.create", json!({"a":[100,200],"b":[200,200],"offset":-30}))["id"].as_u64().unwrap();
|
||||
run(&mut s, "select.set", json!({"ids":[level]}));
|
||||
run(&mut s, "object.scale", json!({"sx":-200,"sy":100,"origin":[150,0]}));
|
||||
assert_eq!(path_ends(&s, level)[2], vec![(250.0, 170.0), (50.0, 170.0)]);
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
run(&mut s, "object.scale", json!({"sx":200,"sy":200,"origin":[150,200]}));
|
||||
assert_eq!(path_ends(&s, level)[2], vec![(50.0, 170.0), (250.0, 170.0)]);
|
||||
}
|
||||
|
||||
/// The line of a linked horizontal dimension below both points stays below them when the art
|
||||
/// turns a half turn; a line between the points keeps its distance from the first point.
|
||||
#[test]
|
||||
|
||||
+2
-1
@@ -66,7 +66,8 @@ Measurements follow the art they measure through moves, scaling and anchor and h
|
||||
undo and redo included. When the art is reflected, the line of a linked linear dimension goes to
|
||||
the reflected side, as far past the outermost point as before. This does not happen for art whose
|
||||
anchors and handles all lie on one line, such as a straight line, which a half turn puts in the
|
||||
same place as a reflection. Deleting the art, changing its number of anchors or whether it is
|
||||
same place as a reflection. An unlinked aligned dimension that is reflected, or scaled by a
|
||||
negative factor, has its line on the reflected side of its points. Deleting the art, changing its number of anchors or whether it is
|
||||
closed, turning an angle's arm into a curve, or making a measured circle or arc no longer circular
|
||||
leaves its dimensions where they were, no longer linked, in the same undo step, rather than
|
||||
attaching them to a different edge. Undo links them again. A linked dimension moved on its own
|
||||
|
||||
Reference in New Issue
Block a user