/// The KCL standard library
///
/// Contains frequently used constants, functions for interacting with the KittyCAD servers to
/// create sketches and geometry, and utility functions.
///
/// The standard library is organised into modules (listed below), but most things are always available
/// in KCL programs.
///
/// You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide](https://zoo.dev/docs/kcl-book/intro.html).
@no_std
@settings(defaultLengthUnit = mm, kclVersion = 1.0, experimentalFeatures = allow)
// Note that everything in the prelude is treated as exported.
export import * from "std::types"
export import "std::gdt"
export import "std::units"
export import * from "std::array"
export import * from "std::math"
export import * from "std::sketch"
export import * from "std::solid"
export import * from "std::transform"
export import "std::turns"
export import "std::sweep"
export import "std::appearance"
export import "std::vector"
export import "std::hole"
@(experimental = true)
export import "std::gear"
@(experimental = true)
export import * from "std::runtime"
/// An abstract 3d plane aligned with the X and Y axes. Its normal is the positive Z axis.
export XY = {
origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 1, z = 0 },
}: Plane
/// An abstract 3d plane aligned with the X and Z axes. Its normal is the negative Y axis.
export XZ = {
origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 0, z = 1 },
}: Plane
/// An abstract 3d plane aligned with the Y and Z axes. Its normal is the positive X axis.
export YZ = {
origin = { x = 0, y = 0, z = 0 },
xAxis = { x = 0, y = 1, z = 0 },
yAxis = { x = 0, y = 0, z = 1 },
}: Plane
/// The X-axis (can be used in both 2d and 3d contexts).
export X = {
origin = [0, 0, 0],
direction = [1, 0, 0],
}: Axis3d
/// The Y-axis (can be used in both 2d and 3d contexts).
export Y = {
origin = [0, 0, 0],
direction = [0, 1, 0],
}: Axis3d
/// The 3D Z-axis.
export Z = {
origin = [0, 0, 0],
direction = [0, 0, 1],
}: Axis3d
/// Identifies the starting face of an extrusion. I.e., the face which is extruded.
export START = 'start': TaggedFace
/// Identifies the ending face of an extrusion. I.e., the new face created by an extrusion.
export END = 'end': TaggedFace
/// Specifies that a new object is created during extrusion.
export NEW = "new": string
/// Specifies that the extrusion will be pulled into or pushed out of the existing object,
/// modifying it without creating a new object.
export MERGE = "merge": string
/// When bodies are solid, they have a top and bottom, and enclose all space between them.
export SOLID = "solid": string
/// When bodies are surfaces, they have zero thickness. They are perfectly flat and do not
/// enclose any space.
export SURFACE = "surface": string
/// Counterclockwise circular direction, currently used by `region()`.
export CCW = "ccw": string
/// Clockwise circular direction, currently used by `region()`.
export CW = "cw": string
/// Create a helix.
///
/// ```kcl,no3d,legacySketch
/// // 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(XZ)
/// |> circle( center = [5, 0], radius = 0.5)
/// |> sweep(path = helixPath)
/// ```
///
/// ```kcl,no3d,legacySketch
/// // Create a helix around an edge.
/// helper001 = startSketchOn(XZ)
/// |> startProfile(at = [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(XZ)
/// |> circle( center = [5, 0], radius = 0.5 )
/// |> sweep(path = helixPath)
/// ```
///
/// ```kcl,no3d,legacySketch
/// // 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(XZ)
/// |> circle( center = [5, 0], radius = 1 )
/// |> sweep(path = helixPath)
/// ```
///
/// ```kcl,no3d,legacySketch
/// // 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,
/// )
/// ```
/// ```kcl,sketchSolve
/// // Demonstrate building a helix where the central axis is a line defined in a sketch block.
/// // First, here's the sketch block with a line:
/// sketch002 = sketch(on = XZ) {
/// line1 = line(start = [var -0.82mm, var 3.4mm], end = [var -1.58mm, var -5.24mm])
/// }
///
/// // Create a helix around the line in the sketch above.
/// helixPath = helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 5,
/// length = 10,
/// radius = 5,
/// axis = sketch002.line1,
/// )
///
/// // Create a spring by sweeping around the helix path.
/// springSketch = startSketchOn(XZ)
/// |> circle(center = [5, 0], radius = 0.5)
/// |> sweep(path = helixPath)
/// ```
@(impl = std_rust, feature_tree = true)
export fn helix(
/// Number of revolutions.
revolutions: number(_),
/// Start angle.
angleStart: number(Angle),
/// Is the helix rotation counter clockwise? The default is `false`.
ccw?: bool,
/// Radius of the helix.
@(includeInSnippet = true)
radius?: number(Length),
/// Axis to use for the helix.
/// The center of the helix's base will be at this axis's origin point.
@(includeInSnippet = true)
axis?: Axis3d | Edge | Segment,
/// 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.
@(includeInSnippet = true)
length?: number(Length),
/// Cylinder to create the helix on.
cylinder?: Solid,
): Helix {}
/// Offset a plane by a distance along its normal.
///
/// For example, if you offset the `XZ` plane by 10, the new plane will be parallel to the `XZ`
/// plane and 10 units away from it.
///
/// ```kcl,legacySketch
/// // Loft a square and a circle on the `XY` plane using offset.
/// squareSketch = startSketchOn(XY)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(XY, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```kcl,legacySketch
/// // Loft a square and a circle on the `XZ` plane using offset.
/// squareSketch = startSketchOn(XZ)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(XZ, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```kcl,legacySketch
/// // Loft a square and a circle on the `YZ` plane using offset.
/// squareSketch = startSketchOn(YZ)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(YZ, offset = 150))
/// |> circle( center = [0, 100], radius = 50 )
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```kcl,legacySketch
/// // Loft a square and a circle on the `-XZ` plane using offset.
/// squareSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-100, 200])
/// |> line(end = [200, 0])
/// |> line(end = [0, -200])
/// |> line(end = [-200, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
///
/// circleSketch = startSketchOn(offsetPlane(-XZ, offset = 150))
/// |> circle(center = [0, 100], radius = 50)
///
/// loft([squareSketch, circleSketch])
/// ```
///
/// ```kcl,legacySketch
/// // A circle on the XY plane
/// startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> circle( radius = 10, center = [0, 0] )
///
/// // Triangle on the plane 4 units above
/// startSketchOn(offsetPlane(XY, offset = 4))
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> close()
/// ```
@(impl = std_rust, feature_tree = true)
export fn offsetPlane(
/// The plane (e.g. `XY`) which this new plane is created from.
@plane: Plane,
/// Distance from the standard plane this new plane will be created at.
offset: number(Length),
): Plane {}
/// Clone a sketch or solid.
///
/// This works essentially like a copy-paste operation. It creates a perfect replica
/// at that point in time that you can manipulate individually afterwards.
///
/// This doesn't really have much utility unless you need the equivalent of a double
/// instance pattern with zero transformations.
///
/// Really only use this function if YOU ARE SURE you need it. In most cases you
/// do not need clone and using a pattern with `instance = 2` is more appropriate.
///
/// ```kcl,legacySketch
/// // Clone a basic sketch and move it and extrude it.
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// clonedSketch = clone(exampleSketch)
/// |> scale(
/// x = 1.0,
/// y = 1.0,
/// z = 2.5,
/// )
/// |> translate(
/// x = 15.0,
/// y = 0,
/// z = 0,
/// )
///
/// extrude(clonedSketch, length = 5)
/// ```
///
/// ```kcl,legacySketch
/// // Clone a basic solid and move it.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// myPart = extrude(exampleSketch, length = 5)
/// clonedPart = clone(myPart)
/// |> translate(
/// x = 25.0,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Translate and rotate a cloned sketch to create a loft.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [-10, 10])
/// |> xLine(length = 20)
/// |> yLine(length = -20)
/// |> xLine(length = -20)
/// |> close()
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 0, y = 0, z = 20)
/// |> rotate(axis = [0, 0, 1.0], angle = 45)
///
/// loft([sketch001, sketch002])
/// ```
///
/// ```kcl,legacySketch
/// // Translate a cloned solid. Fillet only the clone.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [-10, 10])
/// |> xLine(length = 20)
/// |> yLine(length = -20)
/// |> xLine(length = -20, tag = $face0)
/// |> line(endAbsolute = [profileStart()], tag=$face1)
/// |> extrude(length = 5, tagEnd=$end1)
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 0, y = 0, z = 20)
///
/// fillet(
/// sketch002,
/// radius = 2,
/// tags = [getCommonEdge(faces = [sketch002.sketch.tags.face0, sketch002.sketch.tags.face1])],
/// )
/// ```
///
/// ```kcl,legacySketch
/// // You can reuse the tags from the original geometry with the cloned geometry.
///
/// sketch001 = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10], tag = $sketchingFace)
/// |> line(end = [-10, 0])
/// |> close()
///
/// sketch002 = clone(sketch001)
/// |> translate(x = 15, y = 0, z = 5)
/// |> extrude(length = 5)
///
/// startSketchOn(sketch002, face = sketch002.sketch.tags.sketchingFace)
/// |> startProfile(at = [4, 6])
/// |> line(end = [3, 0])
/// |> line(end = [0, 3])
/// |> line(end = [-3, 0])
/// |> close()
/// |> extrude(length = 5)
/// ```
///
/// ```kcl,legacySketch
/// // You can also use the tags from the original geometry to fillet the cloned geometry.
///
/// width = 20
/// length = 10
/// thickness = 1
/// filletRadius = 2
///
/// mountingPlateSketch = startSketchOn(XY)
/// |> startProfile(at = [-width/2, -length/2])
/// |> line(endAbsolute = [width/2, -length/2], tag = $edge1)
/// |> line(endAbsolute = [width/2, length/2], tag = $edge2)
/// |> line(endAbsolute = [-width/2, length/2], tag = $edge3)
/// |> close(tag = $edge4)
///
/// mountingPlate = extrude(mountingPlateSketch, length = thickness)
///
/// clonedMountingPlate = clone(mountingPlate)
///
/// fillet(
/// clonedMountingPlate,
/// radius = filletRadius,
/// tags = [
/// getNextAdjacentEdge(clonedMountingPlate.sketch.tags.edge1),
/// getNextAdjacentEdge(clonedMountingPlate.sketch.tags.edge2),
/// getNextAdjacentEdge(clonedMountingPlate.sketch.tags.edge3),
/// getNextAdjacentEdge(clonedMountingPlate.sketch.tags.edge4)
/// ],
/// )
/// |> translate(x = 0, y = 50, z = 0)
/// ```
///
/// ```kcl,legacySketch
/// // Create a spring by sweeping around a helix path from a cloned sketch.
///
/// // Create a helix around the Z axis.
/// helixPath = helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 4,
/// length = 10,
/// radius = 5,
/// axis = Z,
/// )
///
///
/// springSketch = startSketchOn(XZ)
/// |> circle( center = [0, 0], radius = 1)
///
/// // Create a spring by sweeping around the helix path.
/// sweepedSpring = clone(springSketch)
/// |> translate(x=5)
/// |> sweep(path = helixPath)
/// ```
///
/// ```kcl,legacySketch
/// // A donut shape from a cloned sketch.
/// sketch001 = startSketchOn(XY)
/// |> circle( center = [15, 0], radius = 5 )
///
/// sketch002 = clone(sketch001)
/// |> translate( z = 30)
/// |> revolve(
/// angle = 360,
/// axis = Y,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Sketch on the end of a revolved face by tagging the end face.
/// // This shows the cloned geometry will have the same tags as the original geometry.
///
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [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()
///
/// example001 = revolve(exampleSketch, axis = Y, angle = 180, tagEnd = $end01)
///
/// // example002 = clone(example001)
/// // |> translate(x = 0, y = 20, z = 0)
///
/// // Sketch on the cloned face.
/// // exampleSketch002 = startSketchOn(example002, face = example002.sketch.tags.end01)
/// // |> startProfile(at = [4.5, -5])
/// // |> line(end = [0, 5])
/// // |> line(end = [5, 0])
/// // |> line(end = [0, -5])
/// // |> close()
///
/// // example003 = extrude(exampleSketch002, length = 5)
/// ```
///
/// ```kcl,sketchSyntaxAgnostic
/// // Clone an imported model.
///
/// import "tests/inputs/cube.sldprt" as cube
///
/// myCube = cube
///
/// clonedCube = clone(myCube)
/// |> translate(
/// x = 1020,
/// )
/// |> appearance(
/// color = "#ff0000",
/// metalness = 50,
/// roughness = 50
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Clone an array of sketches and solids
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// exampleSolid = startSketchOn(XY)
/// |> startProfile(at = [-15, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
/// |> extrude(length = 5)
///
///
/// inputArray = [ exampleSketch, exampleSolid]
/// outputArray = clone(inputArray)
///
/// outputArray[0]
/// |> translate(xyz = [10, 10, 10])
/// |> extrude(length = 5)
///
/// clonedSolid = outputArray[1]
/// |> translate(xyz = [-10, -10, -10])
///
/// ```
///
/// // Clone an array that includes an imported geometry, solid and sketch.
/// ```kcl,legacySketch
/// import "tests/inputs/cube.sldprt" as cube
///
/// geom = cube
/// |> translate(xyz = [1000, 50 , 50])
///
/// // Clone a basic sketch and move it and extrude it.
/// exampleSketch = startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
///
/// exampleSolid = startSketchOn(XY)
/// |> startProfile(at = [-15, 0])
/// |> line(end = [10, 0])
/// |> line(end = [0, 10])
/// |> line(end = [-10, 0])
/// |> close()
/// |> extrude(length = 5)
///
///
/// inputArray = [ exampleSketch, exampleSolid, geom ]
/// outputArray = clone(inputArray)
///
/// outputArray[0]
/// |> translate(xyz = [10, 10, 10])
/// |> extrude(length = 5)
/// ```
@(impl = std_rust, feature_tree = true)
export fn clone(
/// The sketch, solid, or imported geometry to be cloned.
@geometries: [Sketch | Solid | ImportedGeometry; 1+],
): [Sketch | Solid | ImportedGeometry; 1+] {}
/// Asserts that a value is the boolean value true.
///
/// ```kcl,norun,sketchSyntaxAgnostic
/// kclIsFun = true
/// assertIs(kclIsFun)
/// ```
@(impl = std_rust, feature_tree = false)
export fn assertIs(
/// Value to check. If this is the boolean value true, assert passes. Otherwise it fails..
@actual: bool,
/// If the value was false, the program will terminate with this error message
error?: string,
) {}
/// Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met.
/// If you provide multiple conditions, they will all be checked and all must be met.
///
/// ```kcl,norun,sketchSyntaxAgnostic
/// n = 10
/// assert(n, isEqualTo = 10)
/// assert(n, isGreaterThanOrEqual = 0, isLessThan = 100, error = "number should be between 0 and 100")
/// assert(1.0000000000012, isEqualTo = 1, tolerance = 0.0001, error = "number should be almost exactly 1")
/// assert(PI, isNotEqualTo = 3, tolerance = 0.0001, error = "PI should not be exactly 3")
/// ```
@(impl = std_rust, feature_tree = false)
export fn assert(
/// Value to check. If this is the boolean value true, assert passes. Otherwise it fails..
@actual: number,
/// Comparison argument. If given, checks the `actual` value is greater than this.
isGreaterThan?: number,
/// Comparison argument. If given, checks the `actual` value is less than this.
isLessThan?: number,
/// Comparison argument. If given, checks the `actual` value is greater than or equal to this.
isGreaterThanOrEqual?: number,
/// Comparison argument. If given, checks the `actual` value is less than or equal to this.
isLessThanOrEqual?: number,
/// Comparison argument. If given, checks the `actual` value is equal to this.
@(includeInSnippet = true)
isEqualTo?: number,
/// Comparison argument. If given, checks the `actual` value is not equal to this.
isNotEqualTo?: number,
/// If `isEqualTo` or `isNotEqualTo` is used, this is the tolerance to allow for the comparison. This tolerance is used because KCL's number system has some floating-point imprecision when used with very large decimal places.
tolerance?: number,
/// If the value was false, the program will terminate with this error message
error?: string,
) {}
/// Given a face index, find its ID.
/// In general, you should prefer tagging faces to using this function. Use this function if
/// you can't tag a face. For example, if the face comes from imported geometry in a .STEP file,
/// or if it's from an operation that doesn't yet support tagging the faces it creates, like `subtract`.
/// ```kcl,legacySketch
/// // Cylinder
/// cylinder = startSketchOn(XY)
/// |> circle(center = [0, 0], radius = 4.09, tag = $seg01)
/// |> extrude(length = 5)
///
/// // Delete the face at index 2
/// // (the top face)
/// deleteFace(cylinder, faces = [faceId(cylinder, index = 2)])
/// ```
@(impl = std_rust, feature_tree = false)
export fn faceId(
/// The solid whose faces we're trying to find
@body: Solid,
/// Face to identify.
/// The index is a stable ordering of faces, used when you can't get the
/// usual ID of a face.
index: number(Count),
): TaggedFace {}
/// Given an edge index, find its ID.
/// In general, you should prefer tagging edges to using this function. Use this function if
/// you can't tag an edge. For example, if the edge comes from imported geometry in a .STEP file,
/// or if it's from an operation that doesn't yet support tagging the edges it creates, like `subtract`.
/// ```kcl,legacySketch
/// // Cylinder
/// cylinder = startSketchOn(XY)
/// |> circle(center = [0, 0], radius = 4.09, tag = $seg01)
/// |> extrude(length = 5)
/// // Fillet the edge at index 2, i.e. the top edge.
/// |> fillet(radius = 1, tags = [edgeId(index = 2)])
/// ```
/// ```kcl,legacySketch
/// startSketchOn(XY)
/// |> rectangle(width = 10, height = 10, center = [0, 0])
/// |> extrude(length = 2)
/// |> fillet(radius = 0.5, tags = [edgeId(closestTo = [5, 0, 2])])
/// ```
@(impl = std_rust, feature_tree = false)
export fn edgeId(
/// The solid whose edges we're trying to find
@body: Solid,
/// Edge to identify.
/// The index is a stable ordering of edges, used when you can't get the
/// usual ID of an edge.
index?: number(Count),
/// Query the edge closest to this point. Uses absolute global coordinates.
closestTo?: Point3d,
): Edge {}