From fc0c0bf8176965add9c10144c9df942e5b7dc06b Mon Sep 17 00:00:00 2001 From: benjamaan476 Date: Thu, 5 Jun 2025 15:52:51 +0100 Subject: [PATCH] move conic std lib fns to sketch.kcl --- e2e/playwright/projects.spec.ts | 9 +- rust/Cargo.lock | 16 +- rust/kcl-lib/src/std/mod.rs | 30 ++- rust/kcl-lib/src/std/shapes.rs | 4 +- rust/kcl-lib/src/std/sketch.rs | 344 ++++++++++++++------------------ rust/kcl-lib/std/sketch.kcl | 192 +++++++++++++++++- 6 files changed, 386 insertions(+), 209 deletions(-) diff --git a/e2e/playwright/projects.spec.ts b/e2e/playwright/projects.spec.ts index 3974d4b1f..5974d9671 100644 --- a/e2e/playwright/projects.spec.ts +++ b/e2e/playwright/projects.spec.ts @@ -169,7 +169,8 @@ test( // error text on hover await page.hover('.cm-lint-marker-error') - const crypticErrorText = 'tag requires a value with type `tag`, but found string' + const crypticErrorText = + 'tag requires a value with type `tag`, but found string' await expect(page.getByText(crypticErrorText).first()).toBeVisible() // black pixel means the scene has been cleared. @@ -367,7 +368,8 @@ test( // error text on hover await page.hover('.cm-lint-marker-error') - const crypticErrorText = 'tag requires a value with type `tag`, but found string' + const crypticErrorText = + 'tag requires a value with type `tag`, but found string' await expect(page.getByText(crypticErrorText).first()).toBeVisible() // black pixel means the scene has been cleared. @@ -405,7 +407,8 @@ test( // error text on hover await page.hover('.cm-lint-marker-error') - const crypticErrorText = 'tag requires a value with type `tag`, but found string' + const crypticErrorText = + 'tag requires a value with type `tag`, but found string' await expect(page.getByText(crypticErrorText).first()).toBeVisible() } ) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 014c3d317..0e8e1ad66 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -525,7 +525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -949,7 +949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1723,7 +1723,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2049,7 +2049,7 @@ dependencies = [ [[package]] name = "kittycad-modeling-cmds" -version = "0.2.121" +version = "0.2.122" dependencies = [ "anyhow", "chrono", @@ -3013,7 +3013,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3325,7 +3325,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3929,7 +3929,7 @@ dependencies = [ "getrandom 0.3.1", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4778,7 +4778,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/rust/kcl-lib/src/std/mod.rs b/rust/kcl-lib/src/std/mod.rs index 939e2f1a4..752b3ddaf 100644 --- a/rust/kcl-lib/src/std/mod.rs +++ b/rust/kcl-lib/src/std/mod.rs @@ -260,9 +260,33 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp |e, a| Box::pin(crate::std::clone::clone(e, a)), StdFnProps::default("std::clone").include_in_feature_tree(), ), - ("sketch", "circle") => ( - |e, a| Box::pin(crate::std::shapes::circle(e, a)), - StdFnProps::default("std::sketch::circle"), + ("sketch", "conic") => ( + |e, a| Box::pin(crate::std::sketch::conic(e, a)), + StdFnProps::default("std::sketch::conic").include_in_feature_tree(), + ), + ("sketch", "parabolic") => ( + |e, a| Box::pin(crate::std::sketch::parabolic(e, a)), + StdFnProps::default("std::sketch::parabolic").include_in_feature_tree(), + ), + ("sketch", "parabolicPoint") => ( + |e, a| Box::pin(crate::std::sketch::parabolic_point(e, a)), + StdFnProps::default("std::sketch::parabolicPoint").include_in_feature_tree(), + ), + ("sketch", "hyperbolic") => ( + |e, a| Box::pin(crate::std::sketch::hyperbolic(e, a)), + StdFnProps::default("std::sketch::hyperbolic").include_in_feature_tree(), + ), + ("sketch", "hyperbolicPoint") => ( + |e, a| Box::pin(crate::std::sketch::hyperbolic_point(e, a)), + StdFnProps::default("std::sketch::hyperbolicPoint").include_in_feature_tree(), + ), + ("sketch", "elliptic") => ( + |e, a| Box::pin(crate::std::sketch::elliptic(e, a)), + StdFnProps::default("std::sketch::elliptic").include_in_feature_tree(), + ), + ("sketch", "ellipticPoint") => ( + |e, a| Box::pin(crate::std::sketch::elliptic_point(e, a)), + StdFnProps::default("std::sketch::ellipticPoint").include_in_feature_tree(), ), ("sketch", "extrude") => ( |e, a| Box::pin(crate::std::extrude::extrude(e, a)), diff --git a/rust/kcl-lib/src/std/shapes.rs b/rust/kcl-lib/src/std/shapes.rs index 2be1e4268..e9f260a7b 100644 --- a/rust/kcl-lib/src/std/shapes.rs +++ b/rust/kcl-lib/src/std/shapes.rs @@ -401,7 +401,8 @@ async fn inner_polygon( /// Sketch an ellipse. pub async fn ellipse(exec_state: &mut ExecState, args: Args) -> Result { - let sketch_or_surface = args.get_unlabeled_kw_arg("sketchOrSurface")?; + let sketch_or_surface = + args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?; let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?; let major_radius: TyF64 = args.get_kw_arg_typed("majorRadius", &RuntimeType::length(), exec_state)?; let minor_radius: TyF64 = args.get_kw_arg_typed("minorRadius", &RuntimeType::length(), exec_state)?; @@ -492,6 +493,7 @@ async fn inner_ellipse( .await?; Ok(new_sketch) +} pub(crate) fn get_radius( radius: Option, diff --git a/rust/kcl-lib/src/std/sketch.rs b/rust/kcl-lib/src/std/sketch.rs index d9af8b60b..c385ff2c4 100644 --- a/rust/kcl-lib/src/std/sketch.rs +++ b/rust/kcl-lib/src/std/sketch.rs @@ -1750,23 +1750,17 @@ pub async fn elliptic_point(exec_state: &mut ExecState, args: Args) -> Result, y: Option, @@ -1778,14 +1772,16 @@ async fn inner_elliptic_point( let minor_radius = minor_radius.n; if let Some(x) = x { if x.n > major_radius { - Err(KclError::Type(KclErrorDetails::new( - format!( - "Invalid input. The x value, {}, cannot be larger than the major radius {}.", - x.n, major_radius - ) - .to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + format!( + "Invalid input. The x value, {}, cannot be larger than the major radius {}.", + x.n, major_radius + ) + .to_owned(), + vec![args.source_range], + ), + }) } else { Ok(( x.n, @@ -1795,14 +1791,16 @@ async fn inner_elliptic_point( } } else if let Some(y) = y { if y.n > minor_radius { - Err(KclError::Type(KclErrorDetails::new( - format!( - "Invalid input. The y value, {}, cannot be larger than the major radius {}.", - y.n, major_radius - ) - .to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + format!( + "Invalid input. The y value, {}, cannot be larger than the major radius {}.", + y.n, major_radius + ) + .to_owned(), + vec![args.source_range], + ), + }) } else { Ok(( major_radius * (1.0 - y.n.powf(2.0) / minor_radius.powf(2.0)).sqrt(), @@ -1811,10 +1809,12 @@ async fn inner_elliptic_point( .into()) } } else { - Err(KclError::Type(KclErrorDetails::new( - "Invalid input. Must have either x or y, you cannot have both or neither.".to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + "Invalid input. Must have either x or y, you cannot have both or neither.".to_owned(), + vec![args.source_range], + ), + }) } } @@ -1852,32 +1852,22 @@ pub async fn elliptic(exec_state: &mut ExecState, args: Args) -> Result startProfile(at = [0, 0]) -/// |> elliptic( -/// endAbsolute = [10,0], -/// interiorAbsolute = [5,5] -/// ) -/// |> close() -/// example = extrude(exampleSketch, length = 10) -/// ``` -#[stdlib { - name = "elliptic", - unlabeled_first = true, - args = { - sketch = { docs = "Which sketch should this path be added to?" }, - center = { docs = "The center of the ellipse.", include_in_snippet = true }, - angle_start = { docs = "Where along the elliptic should this arc start?", include_in_snippet = true }, - angle_end = { docs = "Where along the elliptic should this arc end?", include_in_snippet = true }, - major_radius = { docs = "The major radius a of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.", include_in_snippet = true }, - minor_radius = { docs = "The minor radius b of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.", include_in_snippet = true }, - interior_absolute = { docs = "Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`" }, - end_absolute = { docs = "Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`" }, - tag = { docs = "Create a new tag which refers to this line"}, - }, - tags = ["sketch"] -}] +// #[stdlib { +// name = "elliptic", +// unlabeled_first = true, +// args = { +// sketch = { docs = "Which sketch should this path be added to?" }, +// center = { docs = "The center of the ellipse.", include_in_snippet = true }, +// angle_start = { docs = "Where along the elliptic should this arc start?", include_in_snippet = true }, +// angle_end = { docs = "Where along the elliptic should this arc end?", include_in_snippet = true }, +// major_radius = { docs = "The major radius a of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.", include_in_snippet = true }, +// minor_radius = { docs = "The minor radius b of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.", include_in_snippet = true }, +// interior_absolute = { docs = "Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`" }, +// end_absolute = { docs = "Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`" }, +// tag = { docs = "Create a new tag which refers to this line"}, +// }, +// tags = ["sketch"] +// }] #[allow(clippy::too_many_arguments)] pub(crate) async fn inner_elliptic( sketch: Sketch, @@ -1973,20 +1963,17 @@ pub async fn hyperbolic_point(exec_state: &mut ExecState, args: Args) -> Result< args.make_kcl_val_from_point(hyperbolic_point, exec_state.length_unit().into()) } -/// ```no_run -/// point = hyperbolicPoint(x = 5, semiMajor = 2, semiMinor = 1) -///``` -#[stdlib { - name = "hyperbolicPoint", - unlabeled_first = false, - args = { - semi_major = { docs = "The semi major value a of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, - semi_minor = { docs = "The semi minor value b of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, - x = { docs = "The x value of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1. Will calculate the point y that satisfies the equation and returns (x, y). Incompatible with `y`."}, - y = { docs = "The y value of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1. Will calculate the point x that satisfies the equation and returns (x, y). Incompatible with `x`."}, - }, - tags = ["sketch"] -}] +// #[stdlib { +// name = "hyperbolicPoint", +// unlabeled_first = false, +// args = { +// semi_major = { docs = "The semi major value a of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, +// semi_minor = { docs = "The semi minor value b of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, +// x = { docs = "The x value of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1. Will calculate the point y that satisfies the equation and returns (x, y). Incompatible with `y`."}, +// y = { docs = "The y value of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1. Will calculate the point x that satisfies the equation and returns (x, y). Incompatible with `x`."}, +// }, +// tags = ["sketch"] +// }] async fn inner_hyperbolic_point( x: Option, y: Option, @@ -1998,24 +1985,28 @@ async fn inner_hyperbolic_point( let semi_minor = semi_minor.n; if let Some(x) = x { if x.n < semi_major { - Err(KclError::Type(KclErrorDetails::new( - format!( - "Invalid input. The x value, {}, cannot be less than the semi major value, {}.", - x.n, semi_major - ) - .to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + format!( + "Invalid input. The x value, {}, cannot be less than the semi major value, {}.", + x.n, semi_major + ) + .to_owned(), + vec![args.source_range], + ), + }) } else { Ok((x.n, semi_minor * (x.n.powf(2.0) / semi_major.powf(2.0) - 1.0).sqrt()).into()) } } else if let Some(y) = y { Ok((semi_major * (y.n.powf(2.0) / semi_minor.powf(2.0) + 1.0).sqrt(), y.n).into()) } else { - Err(KclError::Type(KclErrorDetails::new( - "Invalid input. Must have either x or y, cannot have both or neither.".to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + "Invalid input. Must have either x or y, cannot have both or neither.".to_owned(), + vec![args.source_range], + ), + }) } } @@ -2057,32 +2048,21 @@ fn hyperbolic_tangent(point: Point2d, semi_major: f64, semi_minor: f64) -> [f64; (point.y * semi_major.powf(2.0), point.x * semi_minor.powf(2.0)).into() } -/// ```no_run -/// exampleSketch = startSketchOn(XY) -/// |> startProfile(at = [0,0]) -/// |> hyperbolic( -/// end = [10,0], -/// semiMajor = 2, -/// semiMinor = 1, -/// interior = [0,0] -/// ) -/// |>close() -///``` -#[stdlib { - name = "hyperbolic", - unlabeled_first = true, - args = { - sketch = { docs = "Which sketch should this path be added to?" }, - semi_major = { docs = "The semi major value a of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, - semi_minor = { docs = "The semi minor value b of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, - interior = { docs = "A point that lies on the conic segment. This point is relative to the start of the segment. Requires `end`. Incompatible with `interior_absolute` and `end_absolute`." }, - interior_absolute = { docs = "A point that lies on the conic. Requires `end_absolute`. Incompatible with `interior` and `end`." }, - end = { docs = "Where should this arc end? This point is relative to the start of the segment. Requires `interior`. Incompatible with `interior_absolute` and `end_absolute`." }, - end_absolute = { docs = "Where should this arc end? Requires `interior_absolute`. Incompatible with `interior` and `end`." }, - tag = { docs = "Create a new tag which refers to this line"}, - }, - tags = ["sketch"] -}] +// #[stdlib { +// name = "hyperbolic", +// unlabeled_first = true, +// args = { +// sketch = { docs = "Which sketch should this path be added to?" }, +// semi_major = { docs = "The semi major value a of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, +// semi_minor = { docs = "The semi minor value b of the hyperbolic equation x^2 / a^2 - y^2 / b^2 = 1." }, +// interior = { docs = "A point that lies on the conic segment. This point is relative to the start of the segment. Requires `end`. Incompatible with `interior_absolute` and `end_absolute`." }, +// interior_absolute = { docs = "A point that lies on the conic. Requires `end_absolute`. Incompatible with `interior` and `end`." }, +// end = { docs = "Where should this arc end? This point is relative to the start of the segment. Requires `interior`. Incompatible with `interior_absolute` and `end_absolute`." }, +// end_absolute = { docs = "Where should this arc end? Requires `interior_absolute`. Incompatible with `interior` and `end`." }, +// tag = { docs = "Create a new tag which refers to this line"}, +// }, +// tags = ["sketch"] +// }] #[allow(clippy::too_many_arguments)] pub(crate) async fn inner_hyperbolic( sketch: Sketch, @@ -2108,11 +2088,11 @@ pub(crate) async fn inner_hyperbolic( None, None, false, - Some(KclError::Type(KclErrorDetails::new( + Some(KclError::Type{details: KclErrorDetails::new( "Invalid combination of arguments. Either provide (end, interior) or (endAbsolute, interiorAbsolute)" .to_owned(), vec![args.source_range], - ))), + )}), ), }; @@ -2183,22 +2163,16 @@ pub async fn parabolic_point(exec_state: &mut ExecState, args: Args) -> Result, y: Option, @@ -2214,10 +2188,12 @@ async fn inner_parabolic_point( let det = (b.powf(2.0) - 4.0 * a * (c - y.n)).sqrt(); Ok(((-b + det) / (2.0 * a), y.n).into()) } else { - Err(KclError::Type(KclErrorDetails::new( - "Invalid input. Must have either x or y, cannot have both or neither.".to_owned(), - vec![args.source_range], - ))) + Err(KclError::Type { + details: KclErrorDetails::new( + "Invalid input. Must have either x or y, cannot have both or neither.".to_owned(), + vec![args.source_range], + ), + }) } } @@ -2244,28 +2220,18 @@ fn parabolic_tangent(point: Point2d, a: f64, b: f64) -> [f64; 2] { (1.0, 2.0 * a * point.x + b).into() } -/// ```no_run -/// exampleSketch = startSketchOn(XY) -/// |> startProfile(at = [0,0]) -/// |> parabolic( -/// end = [10,0], -/// coefficient = 2, -/// interior = [0,0] -/// ) -/// |>close() -///``` -#[stdlib { - name = "parabolic", - unlabeled_first = true, - args = { - sketch = { docs = "Which sketch should this path be added to?" }, - coefficients = { docs = "The coefficienta [a, b, c] of the parabolic equation y = ax^2 + bx + c. Incompatible with `interior`." }, - interior = { docs = "Any point between the arc's start and end?. Incompatible with `coefficients." }, - end = { docs = "Where should this arc end?" }, - tag = { docs = "Create a new tag which refers to this line"}, - }, - tags = ["sketch"] -}] +// #[stdlib { +// name = "parabolic", +// unlabeled_first = true, +// args = { +// sketch = { docs = "Which sketch should this path be added to?" }, +// coefficients = { docs = "The coefficienta [a, b, c] of the parabolic equation y = ax^2 + bx + c. Incompatible with `interior`." }, +// interior = { docs = "Any point between the arc's start and end?. Incompatible with `coefficients." }, +// end = { docs = "Where should this arc end?" }, +// tag = { docs = "Create a new tag which refers to this line"}, +// }, +// tags = ["sketch"] +// }] pub(crate) async fn inner_parabolic( sketch: Sketch, coefficients: Option<[TyF64; 3]>, @@ -2279,10 +2245,12 @@ pub(crate) async fn inner_parabolic( let id = exec_state.next_uuid(); if (coefficients.is_some() && interior.is_some()) || (coefficients.is_none() && interior.is_none()) { - return Err(KclError::Type(KclErrorDetails::new( - "Invalid combination of arguments. Either provide (a, b, c) or (interior)".to_owned(), - vec![args.source_range], - ))); + return Err(KclError::Type { + details: KclErrorDetails::new( + "Invalid combination of arguments. Either provide (a, b, c) or (interior)".to_owned(), + vec![args.source_range], + ), + }); } let (end, _) = untype_point(end); @@ -2412,32 +2380,20 @@ pub async fn conic(exec_state: &mut ExecState, args: Args) -> Result startProfile(at = [0, 0]) -/// |> conic( -/// end = [10,0], -/// endTangent = [0,1], -/// interior = [5,5], -/// startTangent = [0, -1], -/// ) -/// |> close() -/// example = extrude(exampleSketch, length = 10) -/// ``` -#[stdlib { - name = "conic", - unlabeled_first = true, - args = { - sketch = { docs = "Which sketch should this path be added to?" }, - start_tangent = { docs = "The tangent of the conic at the start point (the end of the previous path segement)" }, - end_tangent = { docs = "The tangent of the conic at the end point" }, - interior = { docs = "Any point between the arc's start and end? Incompatible with `coefficients`." }, - coefficients = { docs = "The coefficients [a, b, c, d, e, f] of the generic conic equation ax^2 + by^2 + cxy + dx + ey + f = 0. Incompatible with `endTangent`."}, - end = { docs = "Where should this arc end?" }, - tag = { docs = "Create a new tag which refers to this line"}, - }, - tags = ["sketch"] -}] +// #[stdlib { +// name = "conic", +// unlabeled_first = true, +// args = { +// sketch = { docs = "Which sketch should this path be added to?" }, +// start_tangent = { docs = "The tangent of the conic at the start point (the end of the previous path segement)" }, +// end_tangent = { docs = "The tangent of the conic at the end point" }, +// interior = { docs = "Any point between the arc's start and end? Incompatible with `coefficients`." }, +// coefficients = { docs = "The coefficients [a, b, c, d, e, f] of the generic conic equation ax^2 + by^2 + cxy + dx + ey + f = 0. Incompatible with `endTangent`."}, +// end = { docs = "Where should this arc end?" }, +// tag = { docs = "Create a new tag which refers to this line"}, +// }, +// tags = ["sketch"] +// }] #[allow(clippy::too_many_arguments)] pub(crate) async fn inner_conic( sketch: Sketch, @@ -2456,10 +2412,12 @@ pub(crate) async fn inner_conic( if (coefficients.is_some() && (start_tangent.is_some() || end_tangent.is_some())) || (coefficients.is_none() && (start_tangent.is_none() && end_tangent.is_none())) { - return Err(KclError::Type(KclErrorDetails::new( - "Invalid combination of arguments. Either provide coefficients or interior".to_owned(), - vec![args.source_range], - ))); + return Err(KclError::Type { + details: KclErrorDetails::new( + "Invalid combination of arguments. Either provide coefficients or interior".to_owned(), + vec![args.source_range], + ), + }); } let (end, _) = untype_array(end); diff --git a/rust/kcl-lib/std/sketch.kcl b/rust/kcl-lib/std/sketch.kcl index ce30aed4e..12d370c33 100644 --- a/rust/kcl-lib/std/sketch.kcl +++ b/rust/kcl-lib/std/sketch.kcl @@ -291,7 +291,7 @@ export fn ellipse( /// Create a new tag which refers to this ellipse. tag?: tag, ): Sketch {} -======= + /// Extend a 2-dimensional sketch through a third dimension in order to /// create new 3-dimensional volume, or if extruded into an existing volume, /// cut into an existing solid. @@ -1939,3 +1939,193 @@ export fn subtract2d( /// The shape(s) which should be cut out of the sketch. tool: [Sketch; 1+], ): Sketch {} + + +/// Add a conic section to an existing sketch. +/// +/// ```kcl +/// exampleSketch = startSketchOn(XZ) +/// |> startProfile(at = [0, 0]) +/// |> conic( +/// end = [10,0], +/// endTangent = [0,1], +/// interior = [5,5], +/// startTangent = [0, -1], +/// ) +/// |> close() +/// example = extrude(exampleSketch, length = 10) +/// ``` +@(impl = std_rust) +export fn conic( + /// Which sketch should this path be added to? + @sketch: Sketch, + /// Any point between the segment's start and end. Incompatible with `coefficients`. + interior: Point2d, + /// Where should the path end?. + end: Point2d, + /// The coefficients [a, b, c, d, e, f] of the generic conic equation ax^2 + by^2 + cxy + dx + ey + f = 0. If provided the start and end tangents will be calculated using this equation. Incompatible with `startTangent` and `endTangent`. + coefficients?: [number(Count); 6], + /// The tangent of the conic section at the start. If not provided the tangent of the previous path segment is used. + startTangent?: Point2d, + /// The tangnet of the conic section at the end. Incompatible with `coefficients`. + endTangent?: Point2d, + /// Create a new tag which refers to this segment. + tag?: tag, + ): Sketch {} + +/// Add a parabolic segment to an existing skwtch. +/// +/// ```kcl +/// exampleSketch = startSketchOn(XY) +/// |> startProfile(at = [0,0]) +/// |> parabolic( +/// end = [10,0], +/// coefficient = 2, +/// interior = [0,0] +/// ) +/// |>close() +///``` +@(impl = std_rust) +export fn parabolic( + /// Which sketch should this path be added to? + @sketch: Sketch, + /// Where should the path end? + end: Point2d, + /// The coefficients [a, b, c] of the parabolic equation y = ax^2 + bx + c. Incompatible with `interior`. + coefficients?: [number(Count); 3], + /// A point between the segment's start and end that lies on the parabola. Incompatible with `coefficients`. + interior?: Point2d, + /// Create a new tag which refers to this segment. + tag?: tag, +): Sketch {} + +/// Calculate the point (x, y) on a parabola given x or y and the coefficients [a, b, c] of the parabola. +/// +/// ```kcl +/// point001 = parabolicPoint(x = 5, a = 0.1, b = 0, c = 0) +/// point002 = parabolicPoint(y = 2.5, a = 0.1, b = 0, c = 0) +/// assert(point001[0], isEqualTo = point002[0]) +/// assert(point001[1], isEqualTo = point002[1]) +///``` +@(impl = std_rust) +export fn parabolicPoint( + /// The coefficients [a, b, c] of the parabolic equation y = ax^2 + bx + c. + coefficients: [number(Count); 3], + /// The x value. Calculates y and returns (x, y). Incompatible with `y`. + x?: number(Length), + /// The y value. Calculates x and returns (x, y). Incompatible with `x`. + y?: number(Length), +): Point2d {} + +/// Add a hyperbolic section to an existing sketch. +/// +/// ```kcl +/// exampleSketch = startSketchOn(XY) +/// |> startProfile(at = [0,0]) +/// |> hyperbolic( +/// end = [10,0], +/// semiMajor = 2, +/// semiMinor = 1, +/// interior = [0,0] +/// ) +/// |>close() +///``` +@(impl = std_rust) +export fn hyperbolic( + /// Which sketch should this path be added to? + @sketch: Sketch, + /// The semi major value, a, of the hyperbolic equation x^2 / a ^ 2 - y^2 / b^2 = 1. + semiMajor: number(Length), + /// The semi minor value, b, of the hyperbolic equation x^2 / a ^ 2 - y^2 / b^2 = 1. + semiMinor: number(Length), + /// Any point between the segments's start and end? Requires `end`. Incompatible with `endAbsolute` or `interiorAbsolute`. + interior?: Point2d, + /// Any point between the segments's start and end? This point is relative to the start point of the segment. Requires `endAbsolute`. Incompatible with `end` or `interior`. + interiorAbsolute?: Point2d, + /// Where should this segment endt? This point is relagive to the start point of the segment. Requires `interior`. Incompatible with `endAbsolute` or `interiorAbsolute`. + end?: Point2d, + /// Where should this segment end? Requires `interiorAbsolute`. Incompatible with `end` or `interior`. + endAbsolute?: Point2d, + /// Create a new tag which refers to this arc. + tag?: tag, +): Sketch {} + +/// Calculate the point (x, y) on a hyperbola given x or y and the semi major/minor values of the hyperbolic. +/// +/// ```kcl +/// point = hyperbolicPoint(x = 5, semiMajor = 2, semiMinor = 1) +///``` +@(impl = std_rust) +export fn hyperbolicPoint( + /// The semi major value, a, of the hyperbolic equation x^2 / a ^ 2 - y^2 / b^2 = 1. + semiMajor: number(Count), + /// The semi minor value, b, of the hyperbolic equation x^2 / a ^ 2 - y^2 / b^2 = 1. + semiMinor: number(Count), + /// The x value. Calculates y and returns (x, y). Incompatible with `y`. + x?: number(Length), + /// The y value. Calculates x and returns (x, y). Incompatible with `x`. + y?: number(Length), +): Point2d {} + +/// Add a parabolic section to an existing sketch. +/// +/// ```kcl +/// exampleSketch = startSketchOn(XZ) +/// |> startProfile(at = [0, 0]) +/// |> elliptic( +/// endAbsolute = [10,0], +/// interiorAbsolute = [5,5] +/// ) +/// |> close() +/// example = extrude(exampleSketch, length = 10) +/// ``` +@(impl = std_rust) +export fn elliptic( + /// Which sketch should this path be added to? + @sketch: Sketch, + /// The center of the ellipse. + @(snippetArray = ["0", "0"]) + center: Point2d, + /// Where along the ellptic should this segment start? + @(includeInSnippet = true) + angleStart: number(Angle), + /// Where along the ellptic should this segment end? + @(includeInSnippet = true) + angleEnd: number(Angle), + /// The major radius, a, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. + @(includeInSnippet = true) + majorRadius: number(Length), + /// The minor radius, b, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. + @(includeInSnippet = true) + minorRadius: number(Length), + /// Any point between the segment's start and end. Requies `endAbsolute`. Incompatible with `interior` or `end`. + interiorAbsolute?: Point2d, + /// Where should this segment end? Requires `interiorAbsolute`. Incompatible with `interior` or `end`. + endAbsolute?: Point2d, + /// Any point between the segment's start and end. This point is relative to the start point. Requires `end`. Incompatible with `interiorAbsolute` or `endAbsolute`. + interior?: Point2d, + /// Where should this segment end? This point is relative to the start point. Requires `interior`. Incompatible with `interiorAbsolute` or `endAbsolute`. + end?: Point2d, + /// Create a new tag which refers to this arc. + tag?: tag, +): Sketch {} + +/// Calculate the point (x, y) on an ellipse given x or y and the center and major/minor radii of the ellipse. +/// +/// ```kcl +/// point001 = ellipticPoint(x = 2, majorRadius = 2, minorRadius = 1) +/// point002 = ellipticPoint(y = 0, majorRadius = 2, minorRadius = 1) +/// assert(point001[0], isEqualTo = point002[0]) +/// assert(point001[1], isEqualTo = point002[1]) +///``` +@(impl = std_rust) +export fn ellipticPoint( + /// The major radius, a, of the elliptic equation x^2 / a ^ 2 + y^2 / b^2 = 1. + majorRadius: number(Count), + /// The minor radius, b, of the hyperbolic equation x^2 / a ^ 2 + y^2 / b^2 = 1. + minorRadius: number(Count), + /// The x value. Calculates y and returns (x, y). Incompatible with `y`. + x?: number(Length), + /// The y value. Calculates x and returns (x, y). Incompatible with `x`. + y?: number(Length), +): Point2d {}