Bidirectional extrude/revolve (#6154)

* extend extrude endpoint

* revolve and mocks

* add bounds check to revolve

* kcl examples of new args

* update to 110

* fix mock

* move example to prelude

* change to camelCase

* new prelude tests

* extend just file

* missed change

* change to XY

* redo sim tests

* review changes

* redo markdown
This commit is contained in:
Ben Crabbe
2025-04-10 15:46:10 +01:00
committed by GitHub
parent 4664427832
commit d125efcd60
109 changed files with 4595 additions and 571 deletions

View File

@ -1,7 +1,7 @@
//! Standard library revolution surfaces.
use anyhow::Result;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, shared::Opposite, ModelingCmd};
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
use super::DEFAULT_TOLERANCE;
@ -30,8 +30,22 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
let tolerance = args.get_kw_arg_opt("tolerance")?;
let tag_start = args.get_kw_arg_opt("tagStart")?;
let tag_end = args.get_kw_arg_opt("tagEnd")?;
let symmetric = args.get_kw_arg_opt("symmetric")?;
let bidirectional_angle = args.get_kw_arg_opt("bidirectionalAngle")?;
let value = inner_revolve(sketches, axis, angle, tolerance, tag_start, tag_end, exec_state, args).await?;
let value = inner_revolve(
sketches,
axis,
angle,
tolerance,
tag_start,
tag_end,
symmetric,
bidirectional_angle,
exec_state,
args,
)
.await?;
Ok(value.into())
}
@ -43,6 +57,8 @@ async fn inner_revolve(
tolerance: Option<f64>,
tag_start: Option<TagNode>,
tag_end: Option<TagNode>,
symmetric: Option<bool>,
bidirectional_angle: Option<f64>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Vec<Solid>, KclError> {
@ -58,8 +74,54 @@ async fn inner_revolve(
}
}
if let Some(bidirectional_angle) = bidirectional_angle {
// Return an error if the angle is zero.
// We don't use validate() here because we want to return a specific error message that is
// nice and we use the other data in the docs, so we still need use the derive above for the json schema.
if !(-360.0..=360.0).contains(&bidirectional_angle) || bidirectional_angle == 0.0 {
return Err(KclError::Semantic(KclErrorDetails {
message: format!(
"Expected bidirectional angle to be between -360 and 360 and not 0, found `{}`",
bidirectional_angle
),
source_ranges: vec![args.source_range],
}));
}
if let Some(angle) = angle {
let ang = angle.signum() * bidirectional_angle + angle;
if !(-360.0..=360.0).contains(&ang) {
return Err(KclError::Semantic(KclErrorDetails {
message: format!(
"Combined angle and bidirectional must be between -360 and 360, found '{}'",
ang
),
source_ranges: vec![args.source_range],
}));
}
}
}
if symmetric.unwrap_or(false) && bidirectional_angle.is_some() {
return Err(KclError::Semantic(KclErrorDetails {
source_ranges: vec![args.source_range],
message: "You cannot give both `symmetric` and `bidirectional` params, you have to choose one or the other"
.to_owned(),
}));
}
let angle = Angle::from_degrees(angle.unwrap_or(360.0));
let bidirectional_angle = bidirectional_angle.map(Angle::from_degrees);
let opposite = match (symmetric, bidirectional_angle) {
(Some(true), _) => Opposite::Symmetric,
(None, None) => Opposite::None,
(Some(false), None) => Opposite::None,
(None, Some(angle)) => Opposite::Other(angle),
(Some(false), Some(angle)) => Opposite::Other(angle),
};
let mut solids = Vec::new();
for sketch in &sketches {
let id = exec_state.next_uuid();
@ -83,6 +145,7 @@ async fn inner_revolve(
},
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
axis_is_2d: true,
opposite: opposite.clone(),
}),
)
.await?;
@ -96,6 +159,7 @@ async fn inner_revolve(
target: sketch.id.into(),
edge_id,
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
opposite: opposite.clone(),
}),
)
.await?;