Sweep in kcl (#4754)
* updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores) * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores) * empty * Update src/wasm-lib/kcl/src/docs/mod.rs Co-authored-by: Jonathan Tran <jonnytran@gmail.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -102,6 +102,7 @@ layout: manual
|
|||||||
* [`startProfileAt`](kcl/startProfileAt)
|
* [`startProfileAt`](kcl/startProfileAt)
|
||||||
* [`startSketchAt`](kcl/startSketchAt)
|
* [`startSketchAt`](kcl/startSketchAt)
|
||||||
* [`startSketchOn`](kcl/startSketchOn)
|
* [`startSketchOn`](kcl/startSketchOn)
|
||||||
|
* [`sweep`](kcl/sweep)
|
||||||
* [`tan`](kcl/tan)
|
* [`tan`](kcl/tan)
|
||||||
* [`tangentToEnd`](kcl/tangentToEnd)
|
* [`tangentToEnd`](kcl/tangentToEnd)
|
||||||
* [`tangentialArc`](kcl/tangentialArc)
|
* [`tangentialArc`](kcl/tangentialArc)
|
||||||
|
4127
docs/kcl/std.json
4127
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
55
docs/kcl/sweep.md
Normal file
55
docs/kcl/sweep.md
Normal file
File diff suppressed because one or more lines are too long
23
docs/kcl/types/SweepData.md
Normal file
23
docs/kcl/types/SweepData.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
title: "SweepData"
|
||||||
|
excerpt: "Data for a sweep."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Data for a sweep.
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `path` |[`Sketch`](/docs/kcl/types/Sketch)| The path to sweep along. | No |
|
||||||
|
| `sectional` |`boolean`| If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. | No |
|
||||||
|
| `tolerance` |`number`| Tolerance for the sweep operation. | No |
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
@ -13,6 +13,8 @@ use tower_lsp::lsp_types::{
|
|||||||
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
|
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::execution::Sketch;
|
||||||
|
|
||||||
use crate::std::Primitive;
|
use crate::std::Primitive;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
||||||
@ -232,6 +234,9 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_autocomplete_snippet(&self) -> Result<String> {
|
fn to_autocomplete_snippet(&self) -> Result<String> {
|
||||||
|
if self.name() == "loft" {
|
||||||
|
return Ok("loft([${0:sketch000}, ${1:sketch001}])${}".to_string());
|
||||||
|
}
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
for arg in self.args(true).iter() {
|
for arg in self.args(true).iter() {
|
||||||
@ -451,6 +456,16 @@ fn get_autocomplete_snippet_from_schema(
|
|||||||
) -> Result<Option<(usize, String)>> {
|
) -> Result<Option<(usize, String)>> {
|
||||||
match schema {
|
match schema {
|
||||||
schemars::schema::Schema::Object(o) => {
|
schemars::schema::Schema::Object(o) => {
|
||||||
|
// Check if the schema is the same as a Sketch.
|
||||||
|
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||||
|
// We set this so we can recurse them later.
|
||||||
|
settings.inline_subschemas = true;
|
||||||
|
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||||
|
let sketch_schema = generator.root_schema_for::<Sketch>().schema;
|
||||||
|
if sketch_schema.object == o.object {
|
||||||
|
return Ok(Some((index, format!("${{{}:sketch{}}}", index, "000"))));
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(serde_json::Value::Bool(nullable)) = o.extensions.get("nullable") {
|
if let Some(serde_json::Value::Bool(nullable)) = o.extensions.get("nullable") {
|
||||||
if *nullable {
|
if *nullable {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -967,6 +982,25 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_autocomplete_snippet_loft() {
|
||||||
|
let loft_fn: Box<dyn StdLibFn> = Box::new(crate::std::loft::Loft);
|
||||||
|
let snippet = loft_fn.to_autocomplete_snippet().unwrap();
|
||||||
|
assert_eq!(snippet, r#"loft([${0:sketch000}, ${1:sketch001}])${}"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_autocomplete_snippet_sweep() {
|
||||||
|
let sweep_fn: Box<dyn StdLibFn> = Box::new(crate::std::sweep::Sweep);
|
||||||
|
let snippet = sweep_fn.to_autocomplete_snippet().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
snippet,
|
||||||
|
r#"sweep({
|
||||||
|
path: ${0:sketch000},
|
||||||
|
}, ${1:%})${}"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// We want to test the snippets we compile at lsp start.
|
// We want to test the snippets we compile at lsp start.
|
||||||
#[test]
|
#[test]
|
||||||
fn get_all_stdlib_autocomplete_snippets() {
|
fn get_all_stdlib_autocomplete_snippets() {
|
||||||
|
@ -65,7 +65,7 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
///
|
///
|
||||||
/// This will work on any solid, including extruded solids, revolved solids, and shelled solids.
|
/// This will work on any solid, including extruded solids, revolved solids, and shelled solids.
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Add color to an extruded solid.
|
/// // Add color to an extruded solid.
|
||||||
/// exampleSketch = startSketchOn("XZ")
|
/// exampleSketch = startSketchOn("XZ")
|
||||||
/// |> startProfileAt([0, 0], %)
|
/// |> startProfileAt([0, 0], %)
|
||||||
/// |> lineTo([10, 0], %)
|
/// |> lineTo([10, 0], %)
|
||||||
@ -78,7 +78,7 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Add color to a revolved solid.
|
/// // Add color to a revolved solid.
|
||||||
/// sketch001 = startSketchOn('XY')
|
/// sketch001 = startSketchOn('XY')
|
||||||
/// |> circle({ center = [15, 0], radius = 5 }, %)
|
/// |> circle({ center = [15, 0], radius = 5 }, %)
|
||||||
/// |> revolve({ angle = 360, axis = 'y' }, %)
|
/// |> revolve({ angle = 360, axis = 'y' }, %)
|
||||||
@ -90,7 +90,7 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Add color to different solids.
|
/// // Add color to different solids.
|
||||||
/// fn cube(center) {
|
/// fn cube(center) {
|
||||||
/// return startSketchOn('XY')
|
/// return startSketchOn('XY')
|
||||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||||
@ -110,8 +110,8 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// You can set the appearance before or after you shell it will yield the same result.
|
/// // You can set the appearance before or after you shell it will yield the same result.
|
||||||
/// /// This example shows setting the appearance _after_ the shell.
|
/// // This example shows setting the appearance _after_ the shell.
|
||||||
/// firstSketch = startSketchOn('XY')
|
/// firstSketch = startSketchOn('XY')
|
||||||
/// |> startProfileAt([-12, 12], %)
|
/// |> startProfileAt([-12, 12], %)
|
||||||
/// |> line([24, 0], %)
|
/// |> line([24, 0], %)
|
||||||
@ -132,8 +132,8 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// You can set the appearance before or after you shell it will yield the same result.
|
/// // You can set the appearance before or after you shell it will yield the same result.
|
||||||
/// /// This example shows setting the appearance _before_ the shell.
|
/// // This example shows setting the appearance _before_ the shell.
|
||||||
/// firstSketch = startSketchOn('XY')
|
/// firstSketch = startSketchOn('XY')
|
||||||
/// |> startProfileAt([-12, 12], %)
|
/// |> startProfileAt([-12, 12], %)
|
||||||
/// |> line([24, 0], %)
|
/// |> line([24, 0], %)
|
||||||
@ -154,8 +154,8 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
||||||
/// /// This example shows _before_ the pattern.
|
/// // This example shows _before_ the pattern.
|
||||||
/// exampleSketch = startSketchOn('XZ')
|
/// exampleSketch = startSketchOn('XZ')
|
||||||
/// |> startProfileAt([0, 0], %)
|
/// |> startProfileAt([0, 0], %)
|
||||||
/// |> line([0, 2], %)
|
/// |> line([0, 2], %)
|
||||||
@ -177,8 +177,8 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
||||||
/// /// This example shows _after_ the pattern.
|
/// // This example shows _after_ the pattern.
|
||||||
/// exampleSketch = startSketchOn('XZ')
|
/// exampleSketch = startSketchOn('XZ')
|
||||||
/// |> startProfileAt([0, 0], %)
|
/// |> startProfileAt([0, 0], %)
|
||||||
/// |> line([0, 2], %)
|
/// |> line([0, 2], %)
|
||||||
@ -200,7 +200,7 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// /// Color the result of a 2D pattern that was extruded.
|
/// // Color the result of a 2D pattern that was extruded.
|
||||||
/// exampleSketch = startSketchOn('XZ')
|
/// exampleSketch = startSketchOn('XZ')
|
||||||
/// |> startProfileAt([.5, 25], %)
|
/// |> startProfileAt([.5, 25], %)
|
||||||
/// |> line([0, 5], %)
|
/// |> line([0, 5], %)
|
||||||
@ -221,6 +221,41 @@ pub async fn appearance(_exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
|||||||
/// roughness = 90
|
/// roughness = 90
|
||||||
/// }, %)
|
/// }, %)
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Color the result of a sweep.
|
||||||
|
///
|
||||||
|
/// // Create a path for the sweep.
|
||||||
|
/// sweepPath = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0.05, 0.05], %)
|
||||||
|
/// |> line([0, 7], %)
|
||||||
|
/// |> tangentialArc({
|
||||||
|
/// offset: 90,
|
||||||
|
/// radius: 5
|
||||||
|
/// }, %)
|
||||||
|
/// |> line([-3, 0], %)
|
||||||
|
/// |> tangentialArc({
|
||||||
|
/// offset: -90,
|
||||||
|
/// radius: 5
|
||||||
|
/// }, %)
|
||||||
|
/// |> line([0, 7], %)
|
||||||
|
///
|
||||||
|
/// sweepSketch = startSketchOn('XY')
|
||||||
|
/// |> startProfileAt([2, 0], %)
|
||||||
|
/// |> arc({
|
||||||
|
/// angleEnd: 360,
|
||||||
|
/// angleStart: 0,
|
||||||
|
/// radius: 2
|
||||||
|
/// }, %)
|
||||||
|
/// |> sweep({
|
||||||
|
/// path: sweepPath,
|
||||||
|
/// }, %)
|
||||||
|
/// |> appearance({
|
||||||
|
/// color: "#ff0000",
|
||||||
|
/// metalness: 50,
|
||||||
|
/// roughness: 50
|
||||||
|
/// }, %)
|
||||||
|
/// ```
|
||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "appearance",
|
name = "appearance",
|
||||||
}]
|
}]
|
||||||
|
@ -1096,6 +1096,20 @@ 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()?;
|
||||||
|
@ -21,6 +21,7 @@ pub mod segment;
|
|||||||
pub mod shapes;
|
pub mod shapes;
|
||||||
pub mod shell;
|
pub mod shell;
|
||||||
pub mod sketch;
|
pub mod sketch;
|
||||||
|
pub mod sweep;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod units;
|
pub mod units;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
@ -114,6 +115,7 @@ lazy_static! {
|
|||||||
Box::new(crate::std::shell::Shell),
|
Box::new(crate::std::shell::Shell),
|
||||||
Box::new(crate::std::shell::Hollow),
|
Box::new(crate::std::shell::Hollow),
|
||||||
Box::new(crate::std::revolve::Revolve),
|
Box::new(crate::std::revolve::Revolve),
|
||||||
|
Box::new(crate::std::sweep::Sweep),
|
||||||
Box::new(crate::std::loft::Loft),
|
Box::new(crate::std::loft::Loft),
|
||||||
Box::new(crate::std::planes::OffsetPlane),
|
Box::new(crate::std::planes::OffsetPlane),
|
||||||
Box::new(crate::std::import::Import),
|
Box::new(crate::std::import::Import),
|
||||||
|
96
src/wasm-lib/kcl/src/std/sweep.rs
Normal file
96
src/wasm-lib/kcl/src/std/sweep.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//! Standard library sweep.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use derive_docs::stdlib;
|
||||||
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||||
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
errors::KclError,
|
||||||
|
execution::{ExecState, KclValue, Sketch, Solid},
|
||||||
|
std::{extrude::do_post_extrude, fillet::default_tolerance, Args},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 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: Sketch,
|
||||||
|
/// 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.
|
||||||
|
pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
|
let (data, sketch): (SweepData, Sketch) = args.get_data_and_sketch()?;
|
||||||
|
|
||||||
|
let solid = inner_sweep(data, sketch, exec_state, args).await?;
|
||||||
|
Ok(KclValue::Solid(solid))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extrude a sketch along a path.
|
||||||
|
///
|
||||||
|
/// This, like extrude, is able to create a 3-dimensional solid from a
|
||||||
|
/// 2-dimensional sketch. However, unlike extrude, this creates a solid
|
||||||
|
/// by using the extent of the sketch as its path. This is useful for
|
||||||
|
/// creating more complex shapes that can't be created with a simple
|
||||||
|
/// extrusion.
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Create a pipe using a sweep.
|
||||||
|
///
|
||||||
|
/// // Create a path for the sweep.
|
||||||
|
/// sweepPath = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0.05, 0.05], %)
|
||||||
|
/// |> line([0, 7], %)
|
||||||
|
/// |> tangentialArc({
|
||||||
|
/// offset: 90,
|
||||||
|
/// radius: 5
|
||||||
|
/// }, %)
|
||||||
|
/// |> line([-3, 0], %)
|
||||||
|
/// |> tangentialArc({
|
||||||
|
/// offset: -90,
|
||||||
|
/// radius: 5
|
||||||
|
/// }, %)
|
||||||
|
/// |> line([0, 7], %)
|
||||||
|
///
|
||||||
|
/// sweepSketch = startSketchOn('XY')
|
||||||
|
/// |> startProfileAt([2, 0], %)
|
||||||
|
/// |> arc({
|
||||||
|
/// angleEnd: 360,
|
||||||
|
/// angleStart: 0,
|
||||||
|
/// radius: 2
|
||||||
|
/// }, %)
|
||||||
|
/// |> sweep({
|
||||||
|
/// path: sweepPath,
|
||||||
|
/// }, %)
|
||||||
|
/// ```
|
||||||
|
#[stdlib {
|
||||||
|
name = "sweep",
|
||||||
|
}]
|
||||||
|
async fn inner_sweep(
|
||||||
|
data: SweepData,
|
||||||
|
sketch: Sketch,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<Box<Solid>, KclError> {
|
||||||
|
let id = exec_state.id_generator.next_uuid();
|
||||||
|
args.batch_modeling_cmd(
|
||||||
|
id,
|
||||||
|
ModelingCmd::from(mcmd::Sweep {
|
||||||
|
target: sketch.id.into(),
|
||||||
|
trajectory: data.path.id.into(),
|
||||||
|
sectional: data.sectional.unwrap_or(false),
|
||||||
|
tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
do_post_extrude(sketch, 0.0, exec_state, args).await
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
BIN
src/wasm-lib/kcl/tests/outputs/serial_test_example_sweep0.png
Normal file
BIN
src/wasm-lib/kcl/tests/outputs/serial_test_example_sweep0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Reference in New Issue
Block a user