mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-29 13:26:49 -06:00
MEASUREGEOM Volume: the height can be given by two points, and Enter at the height prompt says a height is required
This commit is contained in:
@@ -933,6 +933,8 @@ pub(super) struct AreaM {
|
||||
volume: bool,
|
||||
/// Areas measured in volume mode that still wait for their height, oldest first.
|
||||
pending: Vec<f64>,
|
||||
/// The first point of a height given by two points.
|
||||
height_from: Option<Vec2>,
|
||||
}
|
||||
|
||||
impl AreaM {
|
||||
@@ -960,6 +962,19 @@ impl AreaM {
|
||||
AreaMode::Subtract => self.total - v,
|
||||
}
|
||||
}
|
||||
/// Measure the oldest pending area's volume with height `h`.
|
||||
fn height(&mut self, s: &mut Session, h: f64) -> Step {
|
||||
match self.pending.first().map(|a| a * h.abs()) {
|
||||
Some(v) if v.is_finite() && self.total_with(v).is_finite() => {
|
||||
self.pending.remove(0);
|
||||
self.volume_measured(s, v)
|
||||
}
|
||||
_ => {
|
||||
s.echo("The volume is too large.");
|
||||
Step::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Report a volume (and the running total in add/subtract mode); ends the command in single mode.
|
||||
fn volume_measured(&mut self, s: &mut Session, v: f64) -> Step {
|
||||
s.echo(volume_text(s, v));
|
||||
@@ -1003,7 +1018,10 @@ impl Interactive for AreaM {
|
||||
}
|
||||
fn prompt(&self, _s: &Session) -> Prompt {
|
||||
if !self.pending.is_empty() {
|
||||
return Prompt::new(format!("{}Specify height", self.mode_prefix()), Accept::NUMBER);
|
||||
return match self.height_from {
|
||||
Some(p) => Prompt::new("Specify second point", Accept::POINT).base(p),
|
||||
None => Prompt::new(format!("{}Specify height", self.mode_prefix()), Accept::POINT_OR_NUMBER),
|
||||
};
|
||||
}
|
||||
if self.object {
|
||||
return Prompt::new(format!("{}Select objects", self.mode_prefix()), Accept::SELECT);
|
||||
@@ -1023,17 +1041,20 @@ impl Interactive for AreaM {
|
||||
}
|
||||
fn input(&mut self, s: &mut Session, i: Input) -> Result<Step> {
|
||||
if !self.pending.is_empty() {
|
||||
if let Input::Text(t) = i {
|
||||
match crate::units::parse_distance(&t).filter(|v| v.is_finite()) {
|
||||
Some(h) => match self.pending.first().map(|a| a * h.abs()) {
|
||||
Some(v) if v.is_finite() && self.total_with(v).is_finite() => {
|
||||
self.pending.remove(0);
|
||||
return Ok(self.volume_measured(s, v));
|
||||
}
|
||||
_ => s.echo("The volume is too large."),
|
||||
},
|
||||
None => s.echo("Requires a distance."),
|
||||
// A height is typed, or given by two points (their distance).
|
||||
match (i, self.height_from) {
|
||||
(Input::Point(p), None) => self.height_from = Some(p),
|
||||
(Input::Point(p), Some(from)) => {
|
||||
self.height_from = None;
|
||||
return Ok(self.height(s, p.dist(from)));
|
||||
}
|
||||
(Input::Text(t), None) => match crate::units::parse_distance(&t).filter(|v| v.is_finite()) {
|
||||
Some(h) => return Ok(self.height(s, h)),
|
||||
None => s.echo("Requires a distance."),
|
||||
},
|
||||
(Input::Enter, None) => s.echo("Requires a height."),
|
||||
(Input::Enter, Some(_)) => s.echo("Requires a second point."),
|
||||
_ => {}
|
||||
}
|
||||
return Ok(Step::Continue);
|
||||
}
|
||||
|
||||
@@ -229,6 +229,14 @@ fn measuregeom_volume_multiplies_an_area_by_a_height() {
|
||||
assert!(has(&log, "Requires a distance."), "{log:?}");
|
||||
assert!(s.prompt_text().contains("Specify height"), "{}", s.prompt_text());
|
||||
|
||||
// Enter is not a height; two points give the height as their distance.
|
||||
let (mut s, log) = run(&["measuregeom", "v", "0,0", "4,0", "4,3", "", "", "1,1"]);
|
||||
assert!(has(&log, "Requires a height."), "{log:?}");
|
||||
assert!(s.prompt_text().contains("Specify second point"), "{}", s.prompt_text());
|
||||
s.cmdline("7,9").unwrap();
|
||||
assert!(has(&s.log, "Volume = 60.0000"), "{:?}", s.log);
|
||||
assert!(s.running.is_none(), "{}", s.prompt_text());
|
||||
|
||||
// The JSON forms, by points and by handle.
|
||||
let mut s = Session::new();
|
||||
let r = s.execute("measuregeom", &json!({"mode": "volume", "points": [[0, 0], [4, 0], [4, 3]], "height": 10})).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user