mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-28 03:37:00 -06:00
Dimension tool: a click near a line snaps the measured point onto the line (#2432)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
6939a481a4
commit
848e7a296a
@@ -407,3 +407,17 @@ fn shift_shows_the_constrained_line_while_picking_the_second_point() {
|
||||
assert_eq!(end(&mut s, false).y, 310.0);
|
||||
assert!((end(&mut s, true).y - 300.0).abs() < 1e-9);
|
||||
}
|
||||
|
||||
/// A click near a line, away from its anchors, snaps to the closest point of the line (#2432).
|
||||
#[test]
|
||||
fn clicking_near_a_line_snaps_the_measured_point_onto_it() {
|
||||
let mut s = session();
|
||||
edge(&mut s);
|
||||
s.select_tool("dimension", ViewInfo::default()).unwrap();
|
||||
for (x, y) in [(130.0, 103.0), (150.0, 97.0), (140.0, 130.0)] {
|
||||
ev(&mut s, PointerKind::Down, x, y);
|
||||
ev(&mut s, PointerKind::Up, x, y);
|
||||
}
|
||||
let id = s.doc().unwrap().selection.objects[0].0;
|
||||
assert_eq!(text(&s, id), "20.00 pt");
|
||||
}
|
||||
|
||||
@@ -119,6 +119,20 @@ fn anchor_near(cx: &ToolContext, edge: &SegmentRef, p: Point) -> Option<(usize,
|
||||
.min_by(|(_, a), (_, b)| a.distance(p).total_cmp(&b.distance(p)))
|
||||
}
|
||||
|
||||
/// The point of `edge` closest to `p`.
|
||||
fn nearest_on(cx: &ToolContext, edge: &SegmentRef, p: Point) -> Option<Point> {
|
||||
use vectorcraft_geom::kurbo::ParamCurveNearest;
|
||||
let sp = cx.doc.node(edge.node)?.path_data()?.subpaths.get(edge.subpath)?;
|
||||
if edge.segment >= sp.segment_count() {
|
||||
return None;
|
||||
}
|
||||
let c = sp.segment(edge.segment);
|
||||
let t = c.nearest(p, 1e-4).t;
|
||||
use vectorcraft_geom::kurbo::ParamCurve;
|
||||
let q = c.eval(t);
|
||||
(q.x.is_finite() && q.y.is_finite()).then_some(q)
|
||||
}
|
||||
|
||||
impl DimensionTool {
|
||||
fn target(&self, cx: &ToolContext, p: Point) -> Option<Target> {
|
||||
let edge = pick(cx, p)?;
|
||||
@@ -216,11 +230,14 @@ impl DimensionTool {
|
||||
Kind::Linear => {
|
||||
let (mut at, _) = crate::guides::snap_pick(cx, p);
|
||||
let mut reference = None;
|
||||
if let Some(edge) = pick(cx, p)
|
||||
&& let Some((anchor, point)) = anchor_near(cx, &edge, p)
|
||||
{
|
||||
at = point;
|
||||
reference = Some(PointRef { node: edge.node, subpath: edge.subpath, anchor });
|
||||
if let Some(edge) = pick(cx, p) {
|
||||
if let Some((anchor, point)) = anchor_near(cx, &edge, p) {
|
||||
at = point;
|
||||
reference = Some(PointRef { node: edge.node, subpath: edge.subpath, anchor });
|
||||
} else if let Some(point) = nearest_on(cx, &edge, p) {
|
||||
// Not on an anchor: snap to the closest point of the line (#2432).
|
||||
at = point;
|
||||
}
|
||||
}
|
||||
if mods.shift
|
||||
&& let Some((last, _)) = self.points.last()
|
||||
|
||||
Reference in New Issue
Block a user