diff --git a/src/modules/draw/draw/arc.rs b/src/modules/draw/draw/arc.rs index 6eb231973..31edb4ccf 100644 --- a/src/modules/draw/draw/arc.rs +++ b/src/modules/draw/draw/arc.rs @@ -1698,6 +1698,9 @@ pub struct ArcCommand { step: ArcStep, cw: bool, plane: WorkingPlane, + /// Last pointer position at the end step: a typed arc length runs from + /// the start point towards it. + cursor: Option, } impl ArcCommand { @@ -1706,6 +1709,7 @@ impl ArcCommand { step: ArcStep::Start, cw: false, plane: WorkingPlane::default(), + cursor: None, } } @@ -1754,6 +1758,24 @@ impl ArcCommand { }) } + /// Arc about `c` from `s` whose length along the circle is `len`, running + /// towards the side of the start point the pointer is on. + fn sc_arc_length(&self, s: DVec3, c: DVec3, len: f64) -> Option<(DVec3, f64, f64, f64)> { + let r = c.distance(s); + if r < 1e-9 || len <= 0.0 || len >= TAU * r { + return None; + } + let toward = self + .cursor + .map(|cursor| (angle_xy(c, cursor, self.plane) - angle_xy(c, s, self.plane)).rem_euclid(TAU)); + let ccw = match toward { + Some(span) if span > 1e-9 => span <= std::f64::consts::PI, + _ => !self.cw, + }; + let span = len / r; + self.sc_angle(s, c, if ccw { span } else { -span }) + } + /// Sweep from `s` to the cursor about `c`, going the way Ctrl says. fn cursor_span(&self, s: DVec3, c: DVec3, cursor: DVec3) -> f64 { let span = (angle_xy(c, cursor, self.plane) - angle_xy(c, s, self.plane)).rem_euclid(TAU); @@ -1960,7 +1982,11 @@ impl CadCommand for ArcCommand { self.step = ArcStep::LengthSC { s, c }; Some(CmdResult::NeedPoint) } - _ => None, + // A bare number is the arc's length along the circle (#1408). + _ => { + let len = Self::typed_number(text)?; + Some(self.commit(self.sc_arc_length(s, c, len))) + } }, ArcStep::CenterSE { s, e } => match upper.as_str() { "A" | "ANGLE" => { @@ -2135,10 +2161,12 @@ impl CadCommand for ArcCommand { .into_iter() .collect() } - ArcStep::EndSC { s, c } => self - .preview(self.sc_end(s, c, pt), line_wire(c, pt)) - .into_iter() - .collect(), + ArcStep::EndSC { s, c } => { + self.cursor = Some(pt); + self.preview(self.sc_end(s, c, pt), line_wire(c, pt)) + .into_iter() + .collect() + } ArcStep::AngleSC { s, c } => { let span = self.cursor_span(s, c, pt); self.preview(self.sc_angle(s, c, span), line_wire(c, pt))