@no_std @settings(defaultLengthUnit = mm) // Note that everything in the prelude is treated as exported. export import * from "std::math" export import * from "std::sketch" export import "std::turns" /// A number /// /// May be signed or unsigned, an integer or decimal value. /// /// You may see a number type with units, e.g., `number(mm)`. These are currently experimental. @(impl = primitive) export type number(unit) /// A boolean value. /// /// `true` or `false` @(impl = primitive) export type bool /// A sequence of characters /// /// Strings may be delimited using either single or double quotes. /// /// ```kcl,norun /// "hello," /// 'world!' /// ``` @(impl = primitive) export type string /// Tags are used to give a name (tag) to a specific path. /// /// ### Tag Declaration /// /// The syntax for declaring a tag is `$myTag` you would use it in the following /// way: /// /// ```norun,inline /// startSketchOn('XZ') /// |> startProfileAt(origin, %) /// |> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001) - 90, /// length = 196.99, /// }, %, $rectangleSegmentB001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001), /// length = -segLen(rectangleSegmentA001), /// }, %, $rectangleSegmentC001) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// ``` /// /// ### Tag Identifier /// /// As per the example above you can use the tag identifier to get a reference to the /// tagged object. The syntax for this is `myTag`. /// /// In the example above we use the tag identifier to get the angle of the segment /// `segAng(rectangleSegmentA001, %)`. /// /// ### Tag Scope /// /// Tags are scoped globally if in the root context meaning in this example you can /// use the tag `rectangleSegmentA001` in any function or expression in the file. /// /// However if the code was written like this: /// /// ```norun,inline /// fn rect(origin) { /// return startSketchOn('XZ') /// |> startProfileAt(origin, %) /// |> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001) - 90, /// length = 196.99 /// }, %, $rectangleSegmentB001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001), /// length = -segLen(rectangleSegmentA001) /// }, %, $rectangleSegmentC001) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// } /// /// rect([0, 0]) /// rect([20, 0]) /// ``` /// /// Those tags would only be available in the `rect` function and not globally. /// /// However you likely want to use those tags somewhere outside the `rect` function. /// /// Tags are accessible through the sketch group they are declared in. /// For example the following code works. /// /// ```norun,inline /// fn rect(origin) { /// return startSketchOn('XZ') /// |> startProfileAt(origin, %) /// |> angledLine({angle = 0, length = 191.26}, %, $rectangleSegmentA001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001) - 90, /// length = 196.99 /// }, %, $rectangleSegmentB001) /// |> angledLine({ /// angle = segAng(rectangleSegmentA001), /// length = -segLen(rectangleSegmentA001) /// }, %, $rectangleSegmentC001) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// } /// /// rect([0, 0]) /// myRect = rect([20, 0]) /// /// myRect /// |> extrude(10, %) /// |> fillet( /// radius = 0.5, /// tags = [myRect.tags.rectangleSegmentA001] /// ) /// ``` /// /// See how we use the tag `rectangleSegmentA001` in the `fillet` function outside /// the `rect` function. This is because the `rect` function is returning the /// sketch group that contains the tags. @(impl = primitive) export type tag /// A plane. @(impl = std_rust) export type Plane /// A sketch is a collection of paths. /// /// When you define a sketch to a variable like: /// /// ```kcl,inline /// mySketch = startSketchOn('XY') /// |> startProfileAt([-12, 12], %) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// ``` /// /// The `mySketch` variable will be an executed `Sketch` object. Executed being past /// tense, because the engine has already executed the commands to create the sketch. /// /// The previous sketch commands will never be executed again, in this case. /// /// If you would like to encapsulate the commands to create the sketch any time you call it, /// you can use a function. /// /// ```kcl,inline /// fn createSketch() { /// return startSketchOn('XY') /// |> startProfileAt([-12, 12], %) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// } /// ``` /// /// Now, every time you call `createSketch()`, the commands will be /// executed and a new sketch will be created. /// /// When you assign the result of `createSketch()` to a variable (`mySketch = createSketch()`), you are assigning /// the executed sketch to that variable. Meaning that the sketch `mySketch` will not be executed /// again. /// /// You can still execute _new_ commands on the sketch like `extrude`, `revolve`, `loft`, etc. and /// the sketch will be updated. @(impl = std_rust) export type Sketch /// A solid is a collection of extrude surfaces. /// /// When you define a solid to a variable like: /// /// ```kcl,inline /// myPart = startSketchOn('XY') /// |> startProfileAt([-12, 12], %) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// |> extrude(length = 6) /// ``` /// /// The `myPart` variable will be an executed `Solid` object. Executed being past /// tense, because the engine has already executed the commands to create the solid. /// /// The previous solid commands will never be executed again, in this case. /// /// If you would like to encapsulate the commands to create the solid any time you call it, /// you can use a function. /// /// ```kcl,inline /// fn createPart() { /// return startSketchOn('XY') /// |> startProfileAt([-12, 12], %) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// |> extrude(length = 6) /// } /// ``` /// /// Now, every time you call `createPart()`, the commands will be /// executed and a new solid will be created. /// /// When you assign the result of `createPart()` to a variable (`myPart = createPart()`), you are assigning /// the executed solid to that variable. Meaning that the solid `myPart` will not be executed /// again. /// /// You can still execute _new_ commands on the solid like `shell`, `fillet`, `chamfer`, etc. /// and the solid will be updated. @(impl = std_rust) export type Solid /// A face. @(impl = std_rust) export type Face /// A helix. @(impl = std_rust) export type Helix /// The edge of a solid. @(impl = std_rust) export type Edge /// A point in two dimensional space. /// /// `Point2d` is an alias for a two-element array of [number](/docs/kcl/types/number)s. To write a value /// with type `Point2d`, use an array, e.g., `[0, 0]` or `[5.0, 3.14]`. export type Point2d = [number; 2] /// A point in three dimensional space. /// /// `Point3d` is an alias for a three-element array of [number](/docs/kcl/types/number)s. To write a value /// with type `Point3d`, use an array, e.g., `[0, 0, 0]` or `[5.0, 3.14, 6.8]`. export type Point3d = [number; 3] export XY = { origin = { x = 0, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 }, }: Plane export XZ = { origin = { x = 0, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 0, y = -1, z = 0 }, }: Plane export YZ = { origin = { x = 0, y = 0, z = 0 }, xAxis = { x = 0, y = 1, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 1, y = 0, z = 0 }, }: Plane /// An infinite line in 2d space. @(impl = std_rust) export type Axis2d /// An infinite line in 3d space. @(impl = std_rust) export type Axis3d export X = { origin = [0, 0, 0], direction = [1, 0, 0], }: Axis3d export Y = { origin = [0, 0, 0], direction = [0, 1, 0], }: Axis3d export Z = { origin = [0, 0, 0], direction = [0, 0, 1], }: Axis3d /// Create a helix. /// /// ``` /// // Create a helix around the Z axis. /// helixPath = helix( /// angleStart = 0, /// ccw = true, /// revolutions = 5, /// length = 10, /// radius = 5, /// axis = Z, /// ) /// /// // Create a spring by sweeping around the helix path. /// springSketch = startSketchOn(YZ) /// |> circle( center = [0, 0], radius = 0.5) /// |> sweep(path = helixPath) /// ``` /// /// ``` /// // Create a helix around an edge. /// helper001 = startSketchOn(XZ) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 10], tag = $edge001) /// /// helixPath = helix( /// angleStart = 0, /// ccw = true, /// revolutions = 5, /// length = 10, /// radius = 5, /// axis = edge001, /// ) /// /// // Create a spring by sweeping around the helix path. /// springSketch = startSketchOn(XY) /// |> circle( center = [0, 0], radius = 0.5 ) /// |> sweep(path = helixPath) /// ``` /// /// ``` /// // Create a helix around a custom axis. /// helixPath = helix( /// angleStart = 0, /// ccw = true, /// revolutions = 5, /// length = 10, /// radius = 5, /// axis = { /// direction = [0, 0, 1.0], /// origin = [0, 0.25, 0] /// } /// ) /// /// // Create a spring by sweeping around the helix path. /// springSketch = startSketchOn(XY) /// |> circle( center = [0, 0], radius = 1 ) /// |> sweep(path = helixPath) /// ``` /// /// ``` /// // Create a helix on a cylinder. /// /// part001 = startSketchOn(XY) /// |> circle( center= [5, 5], radius= 10 ) /// |> extrude(length = 10) /// /// helix( /// angleStart = 0, /// ccw = true, /// revolutions = 16, /// cylinder = part001, /// ) /// ``` @(impl = std_rust) export fn helix( /// Number of revolutions. revolutions: number(_), /// Start angle (in degrees). angleStart: number(deg), /// Is the helix rotation counter clockwise? The default is `false`. ccw?: bool, /// Radius of the helix. @(include_in_snippet = true) radius?: number(mm), /// Axis to use for the helix. @(include_in_snippet = true) axis?: Axis3d | Edge, /// Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used. @(include_in_snippet = true) length?: number(mm), /// Cylinder to create the helix on. cylinder?: Solid, ): Helix {} /// Rotate a sketch around some provided axis, creating a solid from its extent. /// /// 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 revolved around an axis rather /// than using the extent of the sketch linearly translated through a third /// dimension. /// /// Revolve occurs around a local sketch axis rather than a global axis. /// /// You can provide more than one sketch to revolve, and they will all be /// revolved around the same axis. /// /// ``` /// part001 = startSketchOn(XY) /// |> startProfileAt([4, 12], %) /// |> line(end = [2, 0]) /// |> line(end = [0, -6]) /// |> line(end = [4, -6]) /// |> line(end = [0, -6]) /// |> line(end = [-3.75, -4.5]) /// |> line(end = [0, -5.5]) /// |> line(end = [-2, 0]) /// |> close() /// |> revolve(axis = Y) // default angle is 360 /// ``` /// /// ``` /// // A donut shape. /// sketch001 = startSketchOn(XY) /// |> circle( center = [15, 0], radius = 5 ) /// |> revolve( /// angle = 360, /// axis = Y, /// ) /// ``` /// /// ``` /// part001 = startSketchOn(XY) /// |> startProfileAt([4, 12], %) /// |> line(end = [2, 0]) /// |> line(end = [0, -6]) /// |> line(end = [4, -6]) /// |> line(end = [0, -6]) /// |> line(end = [-3.75, -4.5]) /// |> line(end = [0, -5.5]) /// |> line(end = [-2, 0]) /// |> close() /// |> revolve(axis = Y, angle = 180) /// ``` /// /// ``` /// part001 = startSketchOn(XY) /// |> startProfileAt([4, 12], %) /// |> line(end = [2, 0]) /// |> line(end = [0, -6]) /// |> line(end = [4, -6]) /// |> line(end = [0, -6]) /// |> line(end = [-3.75, -4.5]) /// |> line(end = [0, -5.5]) /// |> line(end = [-2, 0]) /// |> close() /// |> revolve(axis = Y, angle = 180) /// /// part002 = startSketchOn(part001, 'end') /// |> startProfileAt([4.5, -5], %) /// |> line(end = [0, 5]) /// |> line(end = [5, 0]) /// |> line(end = [0, -5]) /// |> close() /// |> extrude(length = 5) /// ``` /// /// ``` /// box = startSketchOn(XY) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 20]) /// |> line(end = [20, 0]) /// |> line(end = [0, -20]) /// |> close() /// |> extrude(length = 20) /// /// sketch001 = startSketchOn(box, "END") /// |> circle( center = [10,10], radius = 4 ) /// |> revolve( /// angle = -90, /// axis = Y /// ) /// ``` /// /// ``` /// box = startSketchOn(XY) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 20]) /// |> line(end = [20, 0]) /// |> line(end = [0, -20], tag = $revolveAxis) /// |> close() /// |> extrude(length = 20) /// /// sketch001 = startSketchOn(box, "END") /// |> circle( center = [10,10], radius = 4 ) /// |> revolve( /// angle = 90, /// axis = getOppositeEdge(revolveAxis) /// ) /// ``` /// /// ``` /// box = startSketchOn(XY) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 20]) /// |> line(end = [20, 0]) /// |> line(end = [0, -20], tag = $revolveAxis) /// |> close() /// |> extrude(length = 20) /// /// sketch001 = startSketchOn(box, "END") /// |> circle( center = [10,10], radius = 4 ) /// |> revolve( /// angle = 90, /// axis = getOppositeEdge(revolveAxis), /// tolerance = 0.0001 /// ) /// ``` /// /// ``` /// sketch001 = startSketchOn(XY) /// |> startProfileAt([10, 0], %) /// |> line(end = [5, -5]) /// |> line(end = [5, 5]) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// /// part001 = revolve( /// sketch001, /// axis = { /// direction = [0.0, 1.0], /// origin: [0.0, 0.0] /// } /// ) /// ``` /// /// ``` /// // Revolve two sketches around the same axis. /// /// sketch001 = startSketchOn(XY) /// profile001 = startProfileAt([4, 8], sketch001) /// |> xLine(length = 3) /// |> yLine(length = -3) /// |> xLine(length = -3) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// /// profile002 = startProfileAt([-5, 8], sketch001) /// |> xLine(length = 3) /// |> yLine(length = -3) /// |> xLine(length = -3) /// |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) /// |> close() /// /// revolve( /// [profile001, profile002], /// axis = X, /// ) /// ``` /// /// ``` /// // Revolve around a path that has not been extruded. /// /// profile001 = startSketchOn(XY) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 20], tag = $revolveAxis) /// |> line(end = [20, 0]) /// |> line(end = [0, -20]) /// |> close(%) /// /// sketch001 = startSketchOn(XY) /// |> circle(center = [-10, 10], radius = 4) /// |> revolve(angle = 90, axis = revolveAxis) /// ``` /// /// ``` /// // Revolve around a path that has not been extruded or closed. /// /// profile001 = startSketchOn(XY) /// |> startProfileAt([0, 0], %) /// |> line(end = [0, 20], tag = $revolveAxis) /// |> line(end = [20, 0]) /// /// sketch001 = startSketchOn(XY) /// |> circle(center = [-10, 10], radius = 4) /// |> revolve(angle = 90, axis = revolveAxis) /// ``` @(impl = std_rust) export fn revolve( /// The sketch or set of sketches that should be revolved @sketches: [Sketch; 1+], /// Axis of revolution. axis: Axis2d | Edge, /// Angle to revolve (in degrees). Default is 360. angle?: number(deg), /// Tolerance for the revolve operation. tolerance?: number(mm), /// A named tag for the face at the start of the revolve, i.e. the original sketch. tagStart?: tag, /// A named tag for the face at the end of the revolve. tagEnd?: tag, ): Solid {}