Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs.
This commit is contained in:
parent
698f2c8c36
commit
093c87d08a
|
|
@ -760,6 +760,19 @@ fn pick_at(s: &Session, p: Vec2) -> Option<Handle> {
|
|||
crate::select::pick(s.doc().ok()?, &s.space(), p, ap)
|
||||
}
|
||||
|
||||
/// The straight or curved piece of `h` picked at `p`: a line, an arc, or the polyline segment nearest `p`.
|
||||
fn segment_at(s: &Session, h: Handle, p: Vec2) -> Option<Segment> {
|
||||
match &s.doc().ok()?.entity(h)?.kind {
|
||||
EntityKind::Line(l) => Some(Segment::Line(cadcraft_geom::Line::new(l.a.xy(), l.b.xy()))),
|
||||
EntityKind::Arc(a) => Some(Segment::Arc { arc: cadcraft_geom::Arc::new(a.center.xy(), a.radius, a.start, a.end), ccw: true }),
|
||||
EntityKind::LwPolyline(pl) => cadcraft_geom::Polyline { vertices: pl.vertices.clone(), closed: pl.closed }
|
||||
.segments()
|
||||
.into_iter()
|
||||
.min_by(|x, y| x.closest(p).dist(p).total_cmp(&y.closest(p).dist(p))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
struct LinearM {
|
||||
aligned: bool,
|
||||
pts: Vec<Vec2>,
|
||||
|
|
@ -1003,15 +1016,13 @@ impl Interactive for AngularM {
|
|||
s.echo("*Invalid selection*");
|
||||
return Ok(Step::Continue);
|
||||
};
|
||||
let kind = s.doc()?.entity(h).map(|e| e.kind.clone());
|
||||
match kind {
|
||||
Some(EntityKind::Arc(a)) if self.first.is_none() => {
|
||||
let g = cadcraft_geom::Arc::new(a.center.xy(), a.radius, a.start, a.end);
|
||||
match segment_at(s, h, p) {
|
||||
Some(Segment::Arc { arc: g, .. }) if self.first.is_none() => {
|
||||
self.arc = Some((g.center, g.start_point(), g.end_point()));
|
||||
}
|
||||
Some(EntityKind::Line(l)) => {
|
||||
Some(Segment::Line(l)) => {
|
||||
self.handles.push(h);
|
||||
let seg = (l.a.xy(), l.b.xy());
|
||||
let seg = (l.a, l.b);
|
||||
if self.first.is_none() {
|
||||
self.first = Some(seg);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -143,6 +143,31 @@ fn angular_between_lines_follows_rotation() {
|
|||
assert_eq!(cadcraft_render::dimension_in(s.doc().unwrap(), &dim(&s, d)).value, "45°");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interactive_angular_picks_polyline_segments() {
|
||||
// Rectangle sides are polyline segments, not lines (issue #10).
|
||||
let mut s = Session::new();
|
||||
s.cmdline("rectang 0,0 10,5").unwrap();
|
||||
s.cmdline("dimangular").unwrap();
|
||||
s.cmdline("5,0").unwrap();
|
||||
s.cmdline("0,2").unwrap();
|
||||
s.cmdline("2,2").unwrap();
|
||||
assert!(s.running.is_none());
|
||||
let d = s.last_dim.unwrap();
|
||||
assert_eq!(cadcraft_render::dimension_in(s.doc().unwrap(), &dim(&s, d)).value, "90°");
|
||||
// A polyline arc segment works like an arc.
|
||||
s.cmdline("pline 20,0 30,0 a 30,10").unwrap();
|
||||
s.cmdline("").unwrap();
|
||||
s.cmdline("dimangular").unwrap();
|
||||
let (cx, cy) = (30.0 + 5.0 * std::f64::consts::FRAC_1_SQRT_2, 5.0 - 5.0 * std::f64::consts::FRAC_1_SQRT_2);
|
||||
s.cmdline(&format!("{cx},{cy}")).unwrap();
|
||||
s.cmdline("40,5").unwrap();
|
||||
assert!(s.running.is_none());
|
||||
let d2 = s.last_dim.unwrap();
|
||||
assert_ne!(d, d2);
|
||||
assert_eq!(cadcraft_render::dimension_in(s.doc().unwrap(), &dim(&s, d2)).value, "180°");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn erase_disassociate_and_reassociate() {
|
||||
let mut s = Session::new();
|
||||
|
|
|
|||
Loading…
Reference in New Issue