KCL: Sweep stdlib fn now uses keyword args (#5300)

Before:
```
|> sweep({ path = myPath }, %)
```

After:
```
|> sweep(path = myPath)
```
This commit is contained in:
Adam Chalmers
2025-02-07 12:35:04 -06:00
committed by GitHub
parent f20fc5b467
commit 30b1dae38a
13 changed files with 4730 additions and 1793 deletions

View File

@ -226,7 +226,7 @@ pipeHole = startSketchOn('XY')
sweepSketch = startSketchOn('XY') sweepSketch = startSketchOn('XY')
|> circle({ center = [0, 0], radius = 2 }, %) |> circle({ center = [0, 0], radius = 2 }, %)
|> hole(pipeHole, %) |> hole(pipeHole, %)
|> sweep({ path = sweepPath }, %) |> sweep(path = sweepPath)
|> appearance({ |> appearance({
color = "#ff0000", color = "#ff0000",
metalness = 50, metalness = 50,

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1029,7 +1029,7 @@ sketch002 = startSketchOn('XZ')
testPoint.x - 50, testPoint.x - 50,
testPoint.y testPoint.y
) )
const sweepDeclaration = 'sweep001 = sweep({ path = sketch002 }, sketch001)' const sweepDeclaration = 'sweep001 = sweep(sketch001, path = sketch002)'
await test.step(`Look for sketch001`, async () => { await test.step(`Look for sketch001`, async () => {
await toolbar.closePane('code') await toolbar.closePane('code')
@ -2221,7 +2221,7 @@ extrude002 = extrude(sketch002, length = 50)
sketch002 = startSketchOn('XZ') sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> xLine(-2000, %) |> xLine(-2000, %)
sweep001 = sweep({ path = sketch002 }, sketch001) sweep001 = sweep(sketch001, path = sketch002)
` `
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

@ -431,10 +431,11 @@ export function addSweep(
} { } {
const modifiedAst = structuredClone(node) const modifiedAst = structuredClone(node)
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SWEEP) const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SWEEP)
const sweep = createCallExpressionStdLib('sweep', [ const sweep = createCallExpressionStdLibKw(
createObjectExpression({ path: createIdentifier(pathDeclarator.id.name) }), 'sweep',
createIdentifier(profileDeclarator.id.name), createIdentifier(profileDeclarator.id.name),
]) [createLabeledArg('path', createIdentifier(pathDeclarator.id.name))]
)
const declaration = createVariableDeclaration(name, sweep) const declaration = createVariableDeclaration(name, sweep)
modifiedAst.body.push(declaration) modifiedAst.body.push(declaration)
const pathToNode: PathToNode = [ const pathToNode: PathToNode = [
@ -442,8 +443,9 @@ export function addSweep(
[modifiedAst.body.length - 1, 'index'], [modifiedAst.body.length - 1, 'index'],
['declaration', 'VariableDeclaration'], ['declaration', 'VariableDeclaration'],
['init', 'VariableDeclarator'], ['init', 'VariableDeclarator'],
['arguments', 'CallExpression'], ['arguments', 'CallExpressionKw'],
[0, 'index'], [0, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
] ]
return { return {

View File

@ -1038,12 +1038,7 @@ mod tests {
fn get_autocomplete_snippet_sweep() { fn get_autocomplete_snippet_sweep() {
let sweep_fn: Box<dyn StdLibFn> = Box::new(crate::std::sweep::Sweep); let sweep_fn: Box<dyn StdLibFn> = Box::new(crate::std::sweep::Sweep);
let snippet = sweep_fn.to_autocomplete_snippet().unwrap(); let snippet = sweep_fn.to_autocomplete_snippet().unwrap();
assert_eq!( assert_eq!(snippet, r#"sweep(${0:%}, path = ${1:sketch000})${}"#);
snippet,
r#"sweep({
path = ${0:sketch000},
}, ${1:%})${}"#
);
} }
#[test] #[test]

View File

@ -254,9 +254,7 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
/// radius = 2, /// radius = 2,
/// }, %) /// }, %)
/// |> hole(pipeHole, %) /// |> hole(pipeHole, %)
/// |> sweep({ /// |> sweep(path = sweepPath)
/// path: sweepPath,
/// }, %)
/// |> appearance({ /// |> appearance({
/// color: "#ff0000", /// color: "#ff0000",
/// metalness: 50, /// metalness: 50,

View File

@ -1042,20 +1042,6 @@ impl<'a> FromKclValue<'a> for super::fillet::FilletData {
} }
} }
impl<'a> FromKclValue<'a> for super::sweep::SweepData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let_field_of!(obj, path);
let_field_of!(obj, sectional?);
let_field_of!(obj, tolerance?);
Some(Self {
path,
sectional,
tolerance,
})
}
}
impl<'a> FromKclValue<'a> for super::appearance::AppearanceData { impl<'a> FromKclValue<'a> for super::appearance::AppearanceData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> { fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?; let obj = arg.as_object()?;

View File

@ -43,7 +43,7 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// // Create a spring by sweeping around the helix path. /// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn('YZ') /// springSketch = startSketchOn('YZ')
/// |> circle({ center = [0, 0], radius = 0.5 }, %) /// |> circle({ center = [0, 0], radius = 0.5 }, %)
/// |> sweep({ path = helixPath }, %) /// |> sweep(path = helixPath)
/// ``` /// ```
/// ///
/// ```no_run /// ```no_run
@ -64,7 +64,7 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// // Create a spring by sweeping around the helix path. /// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn('XY') /// springSketch = startSketchOn('XY')
/// |> circle({ center = [0, 0], radius = 0.5 }, %) /// |> circle({ center = [0, 0], radius = 0.5 }, %)
/// |> sweep({ path = helixPath }, %) /// |> sweep(path = helixPath)
/// ``` /// ```
/// ///
/// ```no_run /// ```no_run
@ -86,7 +86,7 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// // Create a spring by sweeping around the helix path. /// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn('XY') /// springSketch = startSketchOn('XY')
/// |> circle({ center = [0, 0], radius = 1 }, %) /// |> circle({ center = [0, 0], radius = 1 }, %)
/// |> sweep({ path = helixPath }, %) /// |> sweep(path = helixPath)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "helix", name = "helix",

View File

@ -22,24 +22,14 @@ pub enum SweepPath {
Helix(Box<Helix>), Helix(Box<Helix>),
} }
/// Data for a sweep.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
pub struct SweepData {
/// The path to sweep along.
pub path: SweepPath,
/// If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components.
pub sectional: Option<bool>,
/// Tolerance for the sweep operation.
#[serde(default)]
pub tolerance: Option<f64>,
}
/// Extrude a sketch along a path. /// Extrude a sketch along a path.
pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, sketch): (SweepData, Sketch) = args.get_data_and_sketch()?; let sketch = args.get_unlabeled_kw_arg("sketch")?;
let path: SweepPath = args.get_kw_arg("path")?;
let sectional = args.get_kw_arg_opt("sectional")?;
let tolerance = args.get_kw_arg_opt("tolerance")?;
let value = inner_sweep(data, sketch, exec_state, args).await?; let value = inner_sweep(sketch, path, sectional, tolerance, exec_state, args).await?;
Ok(KclValue::Solid { value }) Ok(KclValue::Solid { value })
} }
@ -82,9 +72,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// radius = 2, /// radius = 2,
/// }, %) /// }, %)
/// |> hole(pipeHole, %) /// |> hole(pipeHole, %)
/// |> sweep({ /// |> sweep(path = sweepPath)
/// path: sweepPath,
/// }, %)
/// ``` /// ```
/// ///
/// ```no_run /// ```no_run
@ -104,15 +92,25 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// // Create a spring by sweeping around the helix path. /// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn('YZ') /// springSketch = startSketchOn('YZ')
/// |> circle({ center = [0, 0], radius = 1 }, %) /// |> circle({ center = [0, 0], radius = 1 }, %)
/// |> sweep({ path = helixPath }, %) /// |> sweep(path = helixPath)
/// ``` /// ```
#[stdlib { #[stdlib {
name = "sweep", name = "sweep",
feature_tree_operation = true, feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
args = {
sketch = { docs = "The sketch that should be swept in space" },
path = { docs = "The path to sweep the sketch along" },
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components." },
tolerance = { docs = "Tolerance for this operation" },
}
}] }]
async fn inner_sweep( async fn inner_sweep(
data: SweepData,
sketch: Sketch, sketch: Sketch,
path: SweepPath,
sectional: Option<bool>,
tolerance: Option<f64>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Box<Solid>, KclError> { ) -> Result<Box<Solid>, KclError> {
@ -121,12 +119,12 @@ async fn inner_sweep(
id, id,
ModelingCmd::from(mcmd::Sweep { ModelingCmd::from(mcmd::Sweep {
target: sketch.id.into(), target: sketch.id.into(),
trajectory: match data.path { trajectory: match path {
SweepPath::Sketch(sketch) => sketch.id.into(), SweepPath::Sketch(sketch) => sketch.id.into(),
SweepPath::Helix(helix) => helix.value.into(), SweepPath::Helix(helix) => helix.value.into(),
}, },
sectional: data.sectional.unwrap_or(false), sectional: sectional.unwrap_or(false),
tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))), tolerance: LengthUnit(tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
}), }),
) )
.await?; .await?;