forked from 1b-agent/opencadstudio-upstream
ARC: a number typed at the end point is the arc length
After Center and Start, typing a length now draws the arc that long along the circle, running towards the side of the start point the pointer is on. A length of a full circle or more keeps the prompt. Closes #1408 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3a3d2e4a84
commit
6ef399d83b
1 file changed
+33
-5
@@ -1698,6 +1698,9 @@ pub struct ArcCommand {
|
|||||||
step: ArcStep,
|
step: ArcStep,
|
||||||
cw: bool,
|
cw: bool,
|
||||||
plane: WorkingPlane,
|
plane: WorkingPlane,
|
||||||
|
/// Last pointer position at the end step: a typed arc length runs from
|
||||||
|
/// the start point towards it.
|
||||||
|
cursor: Option<DVec3>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArcCommand {
|
impl ArcCommand {
|
||||||
@@ -1706,6 +1709,7 @@ impl ArcCommand {
|
|||||||
step: ArcStep::Start,
|
step: ArcStep::Start,
|
||||||
cw: false,
|
cw: false,
|
||||||
plane: WorkingPlane::default(),
|
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.
|
/// Sweep from `s` to the cursor about `c`, going the way Ctrl says.
|
||||||
fn cursor_span(&self, s: DVec3, c: DVec3, cursor: DVec3) -> f64 {
|
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);
|
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 };
|
self.step = ArcStep::LengthSC { s, c };
|
||||||
Some(CmdResult::NeedPoint)
|
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() {
|
ArcStep::CenterSE { s, e } => match upper.as_str() {
|
||||||
"A" | "ANGLE" => {
|
"A" | "ANGLE" => {
|
||||||
@@ -2135,10 +2161,12 @@ impl CadCommand for ArcCommand {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
ArcStep::EndSC { s, c } => self
|
ArcStep::EndSC { s, c } => {
|
||||||
.preview(self.sc_end(s, c, pt), line_wire(c, pt))
|
self.cursor = Some(pt);
|
||||||
.into_iter()
|
self.preview(self.sc_end(s, c, pt), line_wire(c, pt))
|
||||||
.collect(),
|
.into_iter()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
ArcStep::AngleSC { s, c } => {
|
ArcStep::AngleSC { s, c } => {
|
||||||
let span = self.cursor_span(s, c, pt);
|
let span = self.cursor_span(s, c, pt);
|
||||||
self.preview(self.sc_angle(s, c, span), line_wire(c, pt))
|
self.preview(self.sc_angle(s, c, span), line_wire(c, pt))
|
||||||
|
|||||||
Reference in new issue
Block a user