/// This module contains functions for modifying solids, e.g., by adding a fillet or chamfer, or
/// removing part of a solid.
@no_std
@settings(defaultLengthUnit = mm, kclVersion = 1.0, experimentalFeatures = allow)
import Axis3d, BoundedEdge, Edge, Face, Plane, Point3d, Solid, TaggedEdge, TaggedFace from "std::types"
/// Blend a transitional edge along a tagged path, smoothing the sharp edge.
///
/// Fillet is similar in function and use to a chamfer, except
/// a chamfer will cut a sharp transition along an edge while fillet
/// will smoothly blend the transition.
///
/// ```kcl,legacySketch
/// 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)
/// |> fillet(
/// radius = filletRadius,
/// tags = [
/// getNextAdjacentEdge(edge1),
/// getNextAdjacentEdge(edge2),
/// getNextAdjacentEdge(edge3),
/// getNextAdjacentEdge(edge4)
/// ],
/// )
/// ```
///
/// ```kcl,legacySketch
/// width = 20
/// length = 10
/// thickness = 1
/// filletRadius = 1
///
/// 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)
/// |> fillet(
/// radius = filletRadius,
/// tolerance = 0.000001,
/// tags = [
/// getNextAdjacentEdge(edge1),
/// getNextAdjacentEdge(edge2),
/// getNextAdjacentEdge(edge3),
/// getNextAdjacentEdge(edge4)
/// ],
/// )
/// ```
///
/// ```kcl,sketchSolve
/// blockProfile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 6mm, var 0mm])
/// edge2 = line(start = [var 6mm, var 0mm], end = [var 6mm, var 4mm])
/// edge3 = line(start = [var 6mm, var 4mm], end = [var 0mm, var 4mm])
/// edge4 = line(start = [var 0mm, var 4mm], end = [var 0mm, var 0mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// horizontal(edge1)
/// vertical(edge2)
/// horizontal(edge3)
/// vertical(edge4)
/// }
///
/// block = extrude(region(segments = [blockProfile.edge1, blockProfile.edge2]), length = 3, tagEnd = $top)
///
/// tabProfile = startSketchOn(block, face = top)
/// |> startProfile(at = [1mm, 1mm])
/// |> line(end = [4mm, 0mm], tag = $tabEdge)
/// |> line(end = [0mm, 1mm])
/// |> line(end = [-4mm, 0mm])
/// |> close()
///
/// blockWithTab = extrude(tabProfile, length = 1mm)
/// filletedBlock = fillet(blockWithTab, radius = 0.5mm, tags = [getNextAdjacentEdge(tabEdge)])
/// ```
/// ```kcl,sketchSolve
/// // This example shows rolling ball fillets, a new type of fillet
/// // available with KCL 3.
/// @settings(kclVersion = "3.0-preview", experimentalFeatures = allow)
///
/// sketch001 = sketch(on = XY) {
/// seg02 = line(start = [var -131.92mm, var 32.75mm], end = [var 195.16mm, var 32.75mm])
/// seg01 = line(start = [var 195.16mm, var 32.75mm], end = [var 195.16mm, var 112.75mm])
/// topRightInset = line(start = [var 195.16mm, var 112.75mm], end = [var 168.73mm, var 112.75mm])
/// innerRightDrop = line(start = [var 168.73mm, var 112.75mm], end = [var 168.73mm, var 62.75mm])
/// lowerSpan = line(start = [var 168.73mm, var 62.75mm], end = [var -104.94mm, var 62.75mm])
/// innerLeftRise = line(start = [var -104.94mm, var 62.75mm], end = [var -104.94mm, var 112.75mm])
/// topLeftInset = line(start = [var -104.94mm, var 112.75mm], end = [var -131.92mm, var 112.75mm])
/// seg03 = line(start = [var -131.92mm, var 112.75mm], end = [var -131.92mm, var 32.75mm])
///
/// coincident([seg02.end, seg01.start])
/// coincident([seg01.end, topRightInset.start])
/// coincident([
/// topRightInset.end,
/// innerRightDrop.start
/// ])
/// coincident([innerRightDrop.end, lowerSpan.start])
/// coincident([lowerSpan.end, innerLeftRise.start])
/// coincident([innerLeftRise.end, topLeftInset.start])
/// coincident([topLeftInset.end, seg03.start])
/// coincident([seg03.end, seg02.start])
///
/// horizontal(seg02)
/// vertical(seg01)
/// horizontal(topRightInset)
/// vertical(innerRightDrop)
/// horizontal(lowerSpan)
/// vertical(innerLeftRise)
/// horizontal(topLeftInset)
///
/// horizontalDistance([seg02.start, ORIGIN]) == 131.92mm
/// verticalDistance([ORIGIN, seg02.start]) == 32.75mm
/// distance([seg01.start, seg01.end]) == 80
/// distance([topRightInset.start, topRightInset.end]) == 26.43mm
/// distance([
/// innerRightDrop.start,
/// innerRightDrop.end
/// ]) == 50
/// distance([lowerSpan.start, lowerSpan.end]) == 273.67mm
/// distance([innerLeftRise.start, innerLeftRise.end]) == 50
/// distance([topLeftInset.start, topLeftInset.end]) == 26.98mm
/// vertical(seg03)
/// }
///
/// hidden001 = hide(sketch001)
/// profile001 = region(segments = [sketch001.seg02, sketch001.seg01], intersectionIndex = -1, direction = CCW)
/// revolve001 = revolve(profile001, angle = 360deg, axis = X)
/// |> fillet(
/// radius = 10mm,
/// tags = [
/// getCommonEdge(faces = [seg02, seg01]),
/// getCommonEdge(faces = [seg02, seg03])
/// ],
/// )
/// |> rotate(yaw = 70deg, pitch = 10deg)
/// ```
/// ```kcl,sketchSolve
/// // Same as previous example, but with the fillet and revolve call
/// // in separate commands, with an intermediate variable.
/// @settings(kclVersion = "3.0-preview", experimentalFeatures = allow)
///
/// sketch001 = sketch(on = XY) {
/// seg02 = line(start = [var -131.92mm, var 32.75mm], end = [var 195.16mm, var 32.75mm])
/// seg01 = line(start = [var 195.16mm, var 32.75mm], end = [var 195.16mm, var 112.75mm])
/// topRightInset = line(start = [var 195.16mm, var 112.75mm], end = [var 168.73mm, var 112.75mm])
/// innerRightDrop = line(start = [var 168.73mm, var 112.75mm], end = [var 168.73mm, var 62.75mm])
/// lowerSpan = line(start = [var 168.73mm, var 62.75mm], end = [var -104.94mm, var 62.75mm])
/// innerLeftRise = line(start = [var -104.94mm, var 62.75mm], end = [var -104.94mm, var 112.75mm])
/// topLeftInset = line(start = [var -104.94mm, var 112.75mm], end = [var -131.92mm, var 112.75mm])
/// seg03 = line(start = [var -131.92mm, var 112.75mm], end = [var -131.92mm, var 32.75mm])
///
/// coincident([seg02.end, seg01.start])
/// coincident([seg01.end, topRightInset.start])
/// coincident([
/// topRightInset.end,
/// innerRightDrop.start
/// ])
/// coincident([innerRightDrop.end, lowerSpan.start])
/// coincident([lowerSpan.end, innerLeftRise.start])
/// coincident([innerLeftRise.end, topLeftInset.start])
/// coincident([topLeftInset.end, seg03.start])
/// coincident([seg03.end, seg02.start])
///
/// horizontal(seg02)
/// vertical(seg01)
/// horizontal(topRightInset)
/// vertical(innerRightDrop)
/// horizontal(lowerSpan)
/// vertical(innerLeftRise)
/// horizontal(topLeftInset)
///
/// horizontalDistance([seg02.start, ORIGIN]) == 131.92mm
/// verticalDistance([ORIGIN, seg02.start]) == 32.75mm
/// distance([seg01.start, seg01.end]) == 80
/// distance([topRightInset.start, topRightInset.end]) == 26.43mm
/// distance([
/// innerRightDrop.start,
/// innerRightDrop.end
/// ]) == 50
/// distance([lowerSpan.start, lowerSpan.end]) == 273.67mm
/// distance([innerLeftRise.start, innerLeftRise.end]) == 50
/// distance([topLeftInset.start, topLeftInset.end]) == 26.98mm
/// vertical(seg03)
/// }
///
/// hidden001 = hide(sketch001)
/// profile001 = region(segments = [sketch001.seg02, sketch001.seg01], intersectionIndex = -1, direction = CCW)
///
/// revolve001 = revolve(profile001, angle = 360deg, axis = X)
///
/// fillet001 = fillet(
/// revolve001,
/// tags = getCommonEdge(faces = [
/// profile001.tags.seg02,
/// profile001.tags.seg01
/// ]),
/// radius = 10,
/// version=2
/// )
/// |> rotate(yaw = 70deg, pitch = 10deg)
/// ```
@(impl = std_rust, feature_tree = true)
export fn fillet(
/// The solid whose edges should be filletted
@solid: Solid,
/// The radius of the fillet
radius: number(Length),
/// The paths you want to fillet (legacy API)
@(includeInSnippet = true)
tags?: [Edge; 1+],
/// Experimental face API. Do not use in generated or user-facing KCL yet; prefer `tags` until point-and-click and migration support ships. Array of edge references; each element is an object with:
/// - `sideFaces`: [Face | Tag; 1+] - Adjacent faces that share the edge(s) to fillet
/// - `endFaces?`: [Face | Tag] - Optional faces to disambiguate when multiple edges share the same two faces
/// - `index?`: number(Count) - Optional index when multiple edges share the same faces (0-based)
@(experimental = true)
edges?: [any],
/// Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters.
tolerance?: number(Length),
/// Create a new tag which refers to this fillet
tag?: TagDecl,
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
/// What version of the fillet algorithm to use.
/// 0 means "let the Zoo engine choose whichever version is best",
/// 1 is the original Zoo fillet algorithm,
/// 2 is the newer algorithm (supports rolling ball fillets).
/// On KCL 2.0 and before, the default is 1.
/// On KCL 3.0 and later, the default is 2.
@(experimental = true) version?: number(Count),
): Solid {}
/// Cut a straight transitional edge along a tagged path.
///
/// Chamfer is similar in function and use to a fillet, except
/// a fillet will blend the transition along an edge, rather than cut
/// a sharp, straight transitional edge.
///
/// ```kcl,legacySketch
/// // Chamfer a mounting plate.
/// width = 20
/// length = 10
/// thickness = 1
/// chamferLength = 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)
/// |> chamfer(
/// length = chamferLength,
/// tags = [
/// getNextAdjacentEdge(edge1),
/// getNextAdjacentEdge(edge2),
/// getNextAdjacentEdge(edge3),
/// getNextAdjacentEdge(edge4)
/// ],
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Sketch on the face of a chamfer.
/// fn cube(pos, scale) {
/// sg = startSketchOn(XY)
/// |> startProfile(at = pos)
/// |> line(end = [0, scale])
/// |> line(end = [scale, 0])
/// |> line(end = [0, -scale])
///
/// return sg
/// }
///
/// part001 = cube(pos = [0,0], scale = 20)
/// |> close(tag = $line1)
/// |> extrude(length = 20)
/// // We tag the chamfer to reference it later.
/// |> chamfer(
/// length = 10,
/// tags = [getOppositeEdge(line1)],
/// tag = $chamfer1,
/// )
///
/// sketch001 = startSketchOn(part001, face = chamfer1)
/// |> startProfile(at = [10, 10])
/// |> line(end = [2, 0])
/// |> line(end = [0, 2])
/// |> line(end = [-2, 0])
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
/// |> extrude(length = 10)
/// ```
///
/// ```kcl,legacySketch
/// // Specify a custom chamfer angle.
/// fn cube(pos, scale) {
/// sg = startSketchOn(XY)
/// |> startProfile(at = pos)
/// |> line(end = [0, scale])
/// |> line(end = [scale, 0])
/// |> line(end = [0, -scale])
///
/// return sg
/// }
///
/// part001 = cube(pos = [0,0], scale = 20)
/// |> close(tag = $line1)
/// |> extrude(length = 20)
/// |> chamfer(
/// length = 10,
/// angle = 30deg,
/// tags = [getOppositeEdge(line1)],
/// )
/// ```
///
/// ```kcl,sketchSolve
/// baseProfile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 6mm, var 0mm])
/// edge2 = line(start = [var 6mm, var 0mm], end = [var 6mm, var 4mm])
/// edge3 = line(start = [var 6mm, var 4mm], end = [var 0mm, var 4mm])
/// edge4 = line(start = [var 0mm, var 4mm], end = [var 0mm, var 0mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// horizontal(edge1)
/// vertical(edge2)
/// horizontal(edge3)
/// vertical(edge4)
/// }
///
/// block = extrude(region(segments = [baseProfile.edge1, baseProfile.edge2]), length = 3mm, tagEnd = $top)
///
/// tabProfile = startSketchOn(block, face = top)
/// |> startProfile(at = [1mm, 1mm])
/// |> line(end = [4mm, 0mm], tag = $tabEdge)
/// |> line(end = [0mm, 1mm])
/// |> line(end = [-4mm, 0mm])
/// |> close()
///
/// blockWithTab = extrude(tabProfile, length = 1mm)
/// chamfered = chamfer(blockWithTab, length = 0.5mm, tags = [getNextAdjacentEdge(tabEdge)])
/// ```
///
/// ```kcl,sketchSolve
/// @settings(defaultLengthUnit = mm, kclVersion = 2.0)
///
/// // Chamfer the top circular edge of an extruded 8 mm shaft.
/// // These two shafts show two equivalent edge-selection approaches:
/// // `getOppositeEdge` and a tagged end face with `getCommonEdge`.
///
/// // Sketch two circles, one on the left, one on the right.
/// // We'll use them for shafts below.
/// leftShaftSketch = sketch(on = XY) {
/// leftCircle = circle(start = [var -8mm, var 0mm], center = [var -12mm, var 0mm])
/// radius(leftCircle) == 4mm
/// }
/// rightShaftSketch = sketch(on = XY) {
/// rightCircle = circle(start = [var 16mm, var 0mm], center = [var 12mm, var 0mm])
/// radius(rightCircle) == 4mm
/// }
///
/// // For each sketch, get the region inside its circle.
/// leftRegion = region(segments = [leftShaftSketch.leftCircle])
/// rightRegion = region(segments = [rightShaftSketch.rightCircle])
///
/// // Extrude one circle into a shaft,
/// // then use `leftRegion.tags.leftCircle` to reference the original circle
/// // at the base of the shaft,
/// // then use `getOppositeEdge` to get the opposite circular edge at the *top* of the shaft.
/// leftShaft = extrude(leftRegion, length = 20mm)
/// |> chamfer(
/// length = 1mm,
/// tags = [
/// getOppositeEdge(leftRegion.tags.leftCircle)
/// ],
/// )
///
/// // Extrude the other circle into a shaft and tag its top end face.
/// rightShaftBase = extrude(rightRegion, length = 20mm, tagEnd = $rightShaftTop)
///
/// // After extrusion, the circle identifies the cylindrical side face.
/// // `getCommonEdge` selects the top rim shared by that face and the top end face.
/// rightTopEdge = getCommonEdge(faces = [
/// rightShaftBase.sketch.tags.rightCircle,
/// rightShaftBase.faces.rightShaftTop
/// ])
///
/// rightShaft = chamfer(rightShaftBase, length = 1mm, tags = [rightTopEdge])
/// ```
@(impl = std_rust, feature_tree = true)
export fn chamfer(
/// The solid whose edges should be chamfered
@solid: Solid,
/// Chamfering cuts away two faces to create a third face.
/// This is the length to chamfer away from each face.
/// The larger this length to chamfer away, the larger the
/// new face will be.
length: number(Length),
/// The paths you want to chamfer (legacy API)
tags?: [Edge; 1+],
/// Experimental face API. Do not use in generated or user-facing KCL yet; prefer `tags` until point-and-click and migration support ships. Array of edge references; each element is an object with:
/// - `sideFaces`: [Face | Tag; 1+] - Adjacent faces that share the edge(s) to chamfer
/// - `endFaces?`: [Face | Tag] - Optional faces to disambiguate when multiple edges share the same two faces
/// - `index?`: number(Count) - Optional index when multiple edges share the same faces (0-based)
@(experimental = true)
edges?: [any],
/// Chamfering cuts away two faces to create a third face.
/// If this argument isn't given, the lengths chamfered away from both
/// the first and second face are both given by `length`.
/// If this argument _is_ given, it determines how much is cut away
/// from the second face. Incompatible with `angle`.
secondLength?: number(Length),
/// Chamfering cuts away two faces to create a third face.
/// This argument determines the angle between the two cut edges.
/// Requires `length`, incompatible with `secondLength`.
/// The valid range is 0deg < angle < 90deg.
angle?: number(Angle),
/// Create a new tag which refers to this chamfer
tag?: TagDecl,
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
/// What version of the fillet algorithm to use. Defaults to 1.
/// 0 means "let the Zoo engine choose whichever version is best",
/// 1 is the original Zoo fillet algorithm,
/// 2 is the newer algorithm (supports rolling ball fillets).
@(experimental = true) version?: number(Count) = 1,
): Solid {}
/// Remove volume from a 3-dimensional shape such that a wall of the
/// provided thickness remains, taking volume starting at the provided
/// face, leaving it open in that direction.
///
/// ```kcl,legacySketch
/// // Remove the end face for the extrusion.
/// firstSketch = startSketchOn(XY)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0])
/// |> close()
/// |> extrude(length = 6)
///
/// // Remove the end face for the extrusion.
/// shell(
/// firstSketch,
/// faces = [END],
/// thickness = 0.25,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Remove the start face for the extrusion.
/// firstSketch = startSketchOn(-XZ)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0])
/// |> close()
/// |> extrude(length = 6)
///
/// // Remove the start face for the extrusion.
/// shell(
/// firstSketch,
/// faces = [START],
/// thickness = 0.25,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Remove a tagged face and the end face for the extrusion.
/// firstSketch = startSketchOn(XY)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0], tag = $myTag)
/// |> close()
/// |> extrude(length = 6)
///
/// // Remove a tagged face for the extrusion.
/// shell(
/// firstSketch,
/// faces = [myTag],
/// thickness = 0.25,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Remove multiple faces at once.
/// firstSketch = startSketchOn(XY)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0], tag = $myTag)
/// |> close()
/// |> extrude(length = 6)
///
/// // Remove a tagged face and the end face for the extrusion.
/// shell(
/// firstSketch,
/// faces = [myTag, END],
/// thickness = 0.25,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Shell a sketch on face.
/// size = 100
/// case = startSketchOn(-XZ)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close()
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle( center = [-size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// thing2 = startSketchOn(case, face = END)
/// |> circle( center = [size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// // We put "case" in the shell function to shell the entire object.
/// shell(case, faces = [START], thickness = 5)
/// ```
///
/// ```kcl,legacySketch
/// // Shell a sketch on face object on the end face.
/// size = 100
/// case = startSketchOn(XY)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close()
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle( center = [-size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// thing2 = startSketchOn(case, face = END)
/// |> circle( center = [size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// // We put "thing1" in the shell function to shell the end face of the object.
/// shell(thing1, faces = [END], thickness = 5)
/// ```
///
/// ```kcl,legacySketch
/// // Shell sketched on face objects on the end face, include all sketches to shell
/// // the entire object.
///
/// size = 100
/// case = startSketchOn(XY)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close()
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle( center = [-size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// thing2 = startSketchOn(case, face = END)
/// |> circle( center = [size / 2, -size / 2], radius = 25)
/// |> extrude(length = 50)
///
/// // We put "thing1" and "thing2" in the shell function to shell the end face of the object.
/// shell([thing1, thing2], faces = [END], thickness = 5)
/// ```
///
/// ```kcl,sketchSolve
/// boxProfile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 6mm, var 0mm])
/// edge2 = line(start = [var 6mm, var 0mm], end = [var 6mm, var 4mm])
/// edge3 = line(start = [var 6mm, var 4mm], end = [var 0mm, var 4mm])
/// edge4 = line(start = [var 0mm, var 4mm], end = [var 0mm, var 0mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// horizontal(edge1)
/// vertical(edge2)
/// horizontal(edge3)
/// vertical(edge4)
/// }
///
/// box = extrude(region(segments = [boxProfile.edge1, boxProfile.edge2]), length = 4mm)
/// openBox = shell(box, faces = [END], thickness = 0.5mm)
/// ```
@(impl = std_rust, feature_tree = true)
export fn shell(
/// Which solid (or solids) to shell out
@solids: [Solid; 1+],
/// The thickness of the shell
thickness: number(Length),
/// The faces you want removed
faces: [TaggedFace; 1+],
): [Solid] {}
/// Make the inside of a 3D object hollow.
///
/// Remove volume from a 3-dimensional shape such that a wall of the
/// provided thickness remains around the exterior of the shape.
/// By default, it'll look visually the same, but you can see the difference
/// if you use `appearance` to make it transparent, or cut it open with
/// a `subtract`.
///
/// ```kcl,legacySketch
/// // Make two cubes, utterly identical,
/// // except that one (left) is hollowed out,
/// // and the other one (right) isn't.
/// width = 2
/// solidCube = startSketchOn(-XZ)
/// |> startProfile(at = [-width, width])
/// |> line(end = [width, 0])
/// |> line(end = [0, -width])
/// |> line(end = [-width, 0])
/// |> close()
/// |> extrude(length = width, symmetric = true)
///
/// hollowCube = clone(solidCube)
/// |> hollow(thickness = 0.25)
/// |> translate(x = width * 1.1)
///
/// // Make a tool that spans the top half of both cubes,
/// // so we can cut open the cubes and look at their insides.
/// tool = startSketchOn(offsetPlane(XY, offset = width))
/// |> startProfile(at = [0, width])
/// |> line(end = [width * 3, 0])
/// |> line(end = [0, -width * 2])
/// |> line(end = [-width * 3, 0])
/// |> close()
/// |> extrude(length = width, symmetric = true)
/// subtract([solidCube, hollowCube], tools = tool)
/// ```
/// ```kcl,legacySketch
/// // Hollow a sketch on face object.
/// size = 100
/// case = startSketchOn(-XZ)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close()
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle( center = [-size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// thing2 = startSketchOn(case, face = END)
/// |> circle( center = [size / 2, -size / 2], radius = 25 )
/// |> extrude(length = 50)
///
/// hollow(case, thickness = 0.5)
/// ```
@(impl = std_rust, feature_tree = true)
export fn hollow(
/// Which solid to hollow out
@solid: Solid,
/// The thickness of the remaining shell
thickness: number(Length),
): Solid {}
/// Repeat a 3-dimensional body or imported geometry, changing it each time.
///
/// Replicates the 3D solid or imported geometry, applying a transformation function to each replica.
/// Transformation function could alter rotation, scale, visibility, position, etc.
///
/// The `patternTransform` call itself takes a number for how many total instances of
/// the shape should be. For example, if you use a circle with `patternTransform(instances = 4, transform = f)`
/// then there will be 4 circles: the original, and 3 created by replicating the original and
/// calling the transform function on each.
///
/// The transform function takes a single parameter: an integer representing which
/// number replication the transform is for. E.g. the first replica to be transformed
/// will be passed the argument `1`. This simplifies your math: the transform function can
/// rely on id `0` being the original instance passed into the `patternTransform`. See the examples.
///
/// The transform function returns a transform object. All properties of the object are optional,
/// they each default to "no change". So the overall transform object defaults to "no change" too.
/// Its properties are:
///
/// - `translate` (3D point)
///
/// Translates the replica, moving its position in space.
///
/// - `replicate` (bool)
///
/// If false, this ID will not actually copy the object. It'll be skipped.
///
/// - `scale` (3D point)
///
/// Stretches the object, multiplying its width in the given dimension by the point's component in
/// that direction.
///
/// - `rotation` (object, with the following properties)
///
/// - `rotation.axis` (a 3D point, defaults to the Z axis)
///
/// - `rotation.angle`
///
/// - `rotation.origin` (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local")
///
/// **NOTE:** Currently,, revolved bodies don't support being scaled in a non-uniform
/// way (i.e. scaled differently along each axis).
///
/// ```kcl,legacySketch
/// // Each instance will be shifted along the X axis.
/// fn transform(@id) {
/// return { translate = [4 * id, 0, 0] }
/// }
///
/// // Sketch 4 cylinders.
/// sketch001 = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 2)
/// |> extrude(length = 5)
/// |> patternTransform(instances = 4, transform = transform)
/// ```
///
/// ```kcl,legacySketch
/// // Each instance will be shifted along the X axis,
/// // with a gap between the original (at x = 0) and the first replica
/// // (at x = 8). This is because `id` starts at 1.
/// fn transform(@id) {
/// return { translate = [4 * (1+id), 0, 0] }
/// }
///
/// sketch001 = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 2)
/// |> extrude(length = 5)
/// |> patternTransform(instances = 4, transform = transform)
/// ```
///
/// ```kcl,legacySketch
/// fn cube(length, center) {
/// l = length/2
/// x = center[0]
/// y = center[1]
/// p0 = [-l + x, -l + y]
/// p1 = [-l + x, l + y]
/// p2 = [ l + x, l + y]
/// p3 = [ l + x, -l + y]
///
/// return startSketchOn(XY)
/// |> startProfile(at = p0)
/// |> line(endAbsolute = p1)
/// |> line(endAbsolute = p2)
/// |> line(endAbsolute = p3)
/// |> line(endAbsolute = p0)
/// |> close()
/// |> extrude(length = length)
/// }
///
/// width = 20
/// fn transform(@i) {
/// return {
/// // Move down each time.
/// translate = [0, 0, -i * width],
/// // Make the cube longer, wider and flatter each time.
/// scale = [pow(1.1, exp = i), pow(1.1, exp = i), pow(0.9, exp = i)],
/// // Turn by 15 degrees each time.
/// rotation = {
/// angle = 15deg * i,
/// origin = "local",
/// }
/// }
/// }
///
/// myCubes =
/// cube(length = width, center = [100,0])
/// |> patternTransform(instances = 25, transform = transform)
/// ```
///
/// ```kcl,legacySketch
/// fn cube(length, center) {
/// l = length/2
/// x = center[0]
/// y = center[1]
/// p0 = [-l + x, -l + y]
/// p1 = [-l + x, l + y]
/// p2 = [ l + x, l + y]
/// p3 = [ l + x, -l + y]
///
/// return startSketchOn(XY)
/// |> startProfile(at = p0)
/// |> line(endAbsolute = p1)
/// |> line(endAbsolute = p2)
/// |> line(endAbsolute = p3)
/// |> line(endAbsolute = p0)
/// |> close()
/// |> extrude(length = length)
/// }
///
/// width = 20
/// fn transform(@i) {
/// return {
/// translate = [0, 0, -i * width],
/// rotation = {
/// angle = 90deg * i,
/// // Rotate around the overall scene's origin.
/// origin = "global",
/// }
/// }
/// }
/// myCubes =
/// cube(length = width, center = [100,100])
/// |> patternTransform(instances = 4, transform = transform)
/// ```
///
/// ```kcl,legacySketch
/// // Parameters
/// r = 50 // base radius
/// h = 10 // layer height
/// t = 0.005 // taper factor [0-1)
/// // Defines how to modify each layer of the vase.
/// // Each replica is shifted up the Z axis, and has a smoothly-varying radius
/// fn transform(@replicaId) {
/// scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
/// return {
/// translate = [0, 0, replicaId * 10],
/// scale = [scale, scale, 1],
/// }
/// }
/// // Each layer is just a pretty thin cylinder.
/// fn layer() {
/// return startSketchOn(XY) // or some other plane idk
/// |> circle(center = [0, 0], radius = 1, tag = $tag1)
/// |> extrude(length = h)
/// }
/// // The vase is 100 layers tall.
/// // The 100 layers are replica of each other, with a slight transformation applied to each.
/// vase = layer() |> patternTransform(instances = 100, transform = transform)
/// ```
///
/// ```kcl,legacySketch
/// fn transform(@i) {
/// // Transform functions can return multiple transforms. They'll be applied in order.
/// return [
/// { translate = [30 * i, 0, 0] },
/// { rotation = { angle = 45deg * i } },
/// ]
/// }
/// startSketchOn(XY)
/// |> startProfile(at = [0, 0])
/// |> polygon(
/// radius = 10,
/// numSides = 4,
/// center = [0, 0],
/// inscribed = false,
/// )
/// |> extrude(length = 4)
/// |> patternTransform(instances = 3, transform = transform)
/// ```
/// ```kcl,legacySketch
/// n = 5
/// width = 10
/// gap = 1.5 * width
///
/// // Transform function
/// fn chessboard(@i) {
/// row = rem(i, divisor = n)
/// column = floor(i / n)
/// isEven = rem(i, divisor = 2) == 0
/// return [{ translate = [row * gap, column * gap, 0], replicate = isEven }]
/// }
///
/// startSketchOn(XY)
/// |> polygon(numSides = 4, radius = width, center = [0, 0])
/// |> extrude(length = 2)
/// |> rotate(yaw = 45)
/// |> patternTransform(instances = n * n, transform = chessboard)
/// ```
@(impl = std_rust, feature_tree = true)
export fn patternTransform(
/// The solid(s) or imported geometry to duplicate.
@solids: [Solid; 1+] | ImportedGeometry,
/// The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect.
instances: number(Count),
/// How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples.
transform: fn(number(Count)): {},
/// If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid.
useOriginal?: bool = false,
): [Solid | ImportedGeometry; 1+] {}
/// Repeat a 3-dimensional body or imported geometry along a linear path, with a dynamic amount
/// of distance between each repetition, some specified number of times.
///
/// ```kcl,legacySketch
/// /// Pattern using a named axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 2])
/// |> line(end = [3, 1])
/// |> line(end = [0, -4])
/// |> close()
///
/// example = extrude(exampleSketch, length = 1)
/// |> patternLinear3d(
/// axis = X,
/// instances = 7,
/// distance = 6
/// )
/// ```
///
/// ```kcl,legacySketch
/// /// Pattern using a raw axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 2])
/// |> line(end = [3, 1])
/// |> line(end = [0, -4])
/// |> close()
///
/// example = extrude(exampleSketch, length = 1)
/// |> patternLinear3d(
/// axis = [1, 0, 1],
/// instances = 7,
/// distance = 6
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Pattern a whole sketch on face.
/// size = 100
/// case = startSketchOn(XY)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close(%)
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle(center = [-size / 2, -size / 2], radius = 25)
/// |> extrude(length = 50)
///
/// thing2 = startSketchOn(case, face = END)
/// |> circle(center = [size / 2, -size / 2], radius = 25)
/// |> extrude(length = 50)
///
/// // We pass in the "case" here since we want to pattern the whole sketch.
/// // And the case was the base of the sketch.
/// patternLinear3d(case,
/// axis= [1, 0, 0],
/// distance= 250,
/// instances=2,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Pattern an object on a face.
/// size = 100
/// case = startSketchOn(XY)
/// |> startProfile(at = [-size, -size])
/// |> line(end = [2 * size, 0])
/// |> line(end = [0, 2 * size])
/// |> tangentialArc(endAbsolute = [-size, size])
/// |> close(%)
/// |> extrude(length = 65)
///
/// thing1 = startSketchOn(case, face = END)
/// |> circle(center =[-size / 2, -size / 2], radius = 25)
/// |> extrude(length = 50)
///
/// // We pass in `thing1` here with `useOriginal` since we want to pattern just this object on the face.
/// patternLinear3d(thing1,
/// axis = [1, 0, 0],
/// distance = size,
/// instances =2,
/// useOriginal = true
/// )
/// ```
@(impl = std_rust, feature_tree = true)
export fn patternLinear3d(
/// The solid(s) or imported geometry to duplicate.
@solids: [Solid; 1+] | ImportedGeometry,
/// The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect.
instances: number(Count),
/// Distance between each repetition. Also known as 'spacing'.
distance: number(Length),
/// The axis of the pattern. A 3D vector.
@(snippetArray = ["1", "0", "0"])
axis: Axis3d | Point3d,
/// If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid.
useOriginal?: bool = false,
): [Solid | ImportedGeometry; 1+] {}
/// Repeat a 3-dimensional body or imported geometry some number of times along a partial or
/// complete circle some specified number of times. Each object may
/// additionally be rotated along the circle, ensuring orientation of the
/// solid with respect to the center of the circle is maintained.
///
/// ```kcl,legacySketch
/// /// Pattern using a named axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
///
/// example = extrude(exampleSketch, length = -5)
/// |> patternCircular3d(
/// axis = X,
/// center = [10, -20, 0],
/// instances = 11,
/// arcDegrees = 360,
/// rotateDuplicates = true
/// )
/// ```
///
/// ```kcl,legacySketch
/// /// Pattern using a raw axis.
///
/// exampleSketch = startSketchOn(XZ)
/// |> circle(center = [0, 0], radius = 1)
///
/// example = extrude(exampleSketch, length = -5)
/// |> patternCircular3d(
/// axis = [1, -1, 0],
/// center = [10, -20, 0],
/// instances = 11,
/// arcDegrees = 360,
/// rotateDuplicates = true
/// )
/// ```
@(impl = std_rust, feature_tree = true)
export fn patternCircular3d(
/// The solid(s) or imported geometry to pattern.
@solids: [Solid; 1+] | ImportedGeometry,
/// The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect.
instances: number(Count),
/// The axis of the pattern. A 3D vector.
@(snippetArray = ["1", "0", "0"])
axis: Axis3d | Point3d,
/// The center about which to make the pattern. This is a 3D vector.
/// If not given, defaults to `[0, 0, 0]`.
@(includeInSnippet = true, snippetArray = ["0", "0", "0"])
center?: Point3d,
/// "The arc angle to place the repetitions. Must be greater than 0.
arcDegrees?: number(deg) = 360deg,
/// Whether or not to rotate the duplicates as they are copied.
rotateDuplicates?: bool = true,
/// If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid.
useOriginal?: bool = false,
): [Solid | ImportedGeometry; 1+] {}
/// Union two or more solids into a single solid.
///
/// This operation consumes every input solid. After it succeeds, the original
/// solid variables cannot be used in another modeling operation. Assign the
/// returned solid or solids to a new variable and use that result for any
/// subsequent operations.
///
/// ```kcl,legacySketch
/// // Union two cubes using the stdlib functions.
///
/// fn cube(center, size) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// unionedPart = union([part001, part002])
/// ```
///
/// ```kcl,legacySketch
/// // Union two cubes using operators.
/// // NOTE: This will not work when using codemods through the UI.
/// // Codemods will generate the stdlib function call instead.
///
/// fn cube(center, size) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
/// unionedPart = part001 + part002
/// ```
///
/// ```kcl,legacySketch
/// // Union two cubes using the more programmer-friendly operator.
/// // NOTE: This will not work when using codemods through the UI.
/// // Codemods will generate the stdlib function call instead.
///
/// fn cube(center, size) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
/// // Programmers will understand `|` as a union operation, but mechanical engineers
/// // will understand `+`, we made both work.
/// unionedPart = part001 | part002
/// ```
@(impl = std_rust, feature_tree = true)
export fn union(
/// The solids to union. Every input solid is consumed by this operation.
@solids: [Solid; 2+],
/// Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters.
tolerance?: number(Length),
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
): [Solid; 1+] {}
/// Intersect returns the shared volume between multiple solids, preserving only
/// overlapping regions.
///
/// Intersect computes the geometric intersection of multiple solid bodies,
/// returning a new solid representing the volume that is common to all input
/// solids. This operation is useful for determining shared material regions,
/// verifying fit, and analyzing overlapping geometries in assemblies.
///
/// This operation consumes every input solid. After it succeeds, the original
/// solid variables cannot be used in another modeling operation. Assign the
/// returned solid or solids to a new variable and use that result for any
/// subsequent operations.
///
/// ```kcl,legacySketch
/// // Intersect two cubes using the stdlib functions.
///
/// fn cube(center, size) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// intersectedPart = intersect([part001, part002])
/// ```
///
/// ```kcl,legacySketch
/// // Intersect two cubes using operators.
/// // NOTE: This will not work when using codemods through the UI.
/// // Codemods will generate the stdlib function call instead.
///
/// fn cube(center, size) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: intersect([part001, part002])
/// intersectedPart = part001 & part002
/// ```
@(impl = std_rust, feature_tree = true)
export fn intersect(
/// The solids to intersect. Every input solid is consumed by this operation.
@solids: [Solid; 2+],
/// Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters.
tolerance?: number(Length),
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
): [Solid; 1+] {}
/// Subtract removes tool solids from base solids, leaving the remaining material.
///
/// Performs a bool subtraction operation, removing the volume of one or more
/// tool solids from one or more base solids. The result is a new solid
/// representing the material that remains after all tool solids have been cut
/// away. This function is essential for machining simulations, cavity creation,
/// and complex multi-body part modeling.
///
/// This operation consumes both the base solids and the tool solids. After it
/// succeeds, neither set of original variables can be used in another modeling
/// operation. Assign the returned solid or solids to a new variable and use that
/// result for subsequent operations. For multiple cuts, pass each `subtract`
/// result into the next call instead of reusing the original base solid.
///
/// ```kcl,sketchSolve
/// @settings(defaultLengthUnit = mm, kclVersion = 2.0)
///
/// baseSketch = sketch(on = XY) {
/// bottom = line(start = [var -10mm, var -10mm], end = [var 10mm, var -10mm])
/// right = line(start = [var 10mm, var -10mm], end = [var 10mm, var 10mm])
/// top = line(start = [var 10mm, var 10mm], end = [var -10mm, var 10mm])
/// left = line(start = [var -10mm, var 10mm], end = [var -10mm, var -10mm])
/// coincident([bottom.end, right.start])
/// coincident([right.end, top.start])
/// coincident([top.end, left.start])
/// coincident([left.end, bottom.start])
/// }
/// baseRegion = region(segments = [baseSketch.bottom, baseSketch.right])
/// base = extrude(baseRegion, length = 10mm)
///
/// toolSketch = sketch(on = XY) {
/// bottom = line(start = [var 2mm, var -2mm], end = [var 12mm, var -2mm])
/// right = line(start = [var 12mm, var -2mm], end = [var 12mm, var 8mm])
/// top = line(start = [var 12mm, var 8mm], end = [var 2mm, var 8mm])
/// left = line(start = [var 2mm, var 8mm], end = [var 2mm, var -2mm])
/// coincident([bottom.end, right.start])
/// coincident([right.end, top.start])
/// coincident([top.end, left.start])
/// coincident([left.end, bottom.start])
/// }
/// toolRegion = region(segments = [toolSketch.bottom, toolSketch.right])
/// tool = extrude(toolRegion, length = 10mm)
/// |> translate(z = 1mm)
///
/// subtractedPart = subtract([base], tools = [tool])
/// ```
///
/// ```kcl,sketchSolve
/// @settings(defaultLengthUnit = mm, kclVersion = 2.0)
///
/// baseSketch = sketch(on = XY) {
/// bottom = line(start = [var -10mm, var -10mm], end = [var 10mm, var -10mm])
/// right = line(start = [var 10mm, var -10mm], end = [var 10mm, var 10mm])
/// top = line(start = [var 10mm, var 10mm], end = [var -10mm, var 10mm])
/// left = line(start = [var -10mm, var 10mm], end = [var -10mm, var -10mm])
/// coincident([bottom.end, right.start])
/// coincident([right.end, top.start])
/// coincident([top.end, left.start])
/// coincident([left.end, bottom.start])
/// }
/// baseRegion = region(segments = [baseSketch.bottom, baseSketch.right])
/// base = extrude(baseRegion, length = 10mm)
///
/// toolSketch = sketch(on = XY) {
/// bottom = line(start = [var 2mm, var -2mm], end = [var 12mm, var -2mm])
/// right = line(start = [var 12mm, var -2mm], end = [var 12mm, var 8mm])
/// top = line(start = [var 12mm, var 8mm], end = [var 2mm, var 8mm])
/// left = line(start = [var 2mm, var 8mm], end = [var 2mm, var -2mm])
/// coincident([bottom.end, right.start])
/// coincident([right.end, top.start])
/// coincident([top.end, left.start])
/// coincident([left.end, bottom.start])
/// }
/// toolRegion = region(segments = [toolSketch.bottom, toolSketch.right])
/// tool = extrude(toolRegion, length = 10mm)
/// |> translate(z = 1mm)
///
/// // This is equivalent to: subtract([base], tools = [tool])
/// subtractedPart = base - tool
/// ```
@(impl = std_rust, feature_tree = true)
export fn subtract(
/// The solids to use as the base to subtract from. These solids are consumed by this operation.
@solids: [Solid; 1+],
/// The solids to subtract. These tool solids are also consumed by this operation.
tools: [Solid],
/// Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters.
tolerance?: number(Length),
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
): [Solid] {}
/// Set the appearance of a solid, imported geometry, or plane. This does not work on sketches or individual paths.
///
/// This will work on any solid, including extruded solids, revolved solids, and shelled solids.
/// For planes, only `color` is used.
///
/// ```kcl,legacySketch
/// // Add color to an extruded solid.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(endAbsolute = [10, 0])
/// |> line(endAbsolute = [0, 10])
/// |> line(endAbsolute = [-10, 0])
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// // There are other options besides 'color', but they're optional.
/// |> appearance(color='#ff0000')
/// ```
///
/// ```kcl,legacySketch
/// // Add color to a revolved solid.
/// sketch001 = startSketchOn(XY)
/// |> circle( center = [15, 0], radius = 5 )
/// |> revolve( angle = 360deg, axis = Y)
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Add color to different solids.
/// fn cube(center) {
/// return startSketchOn(XY)
/// |> startProfile(at = [center[0] - 10, center[1] - 10])
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// example0 = cube(center = [0, 0])
/// example1 = cube(center = [20, 0])
/// example2 = cube(center = [40, 0])
///
/// appearance([example0, example1], color='#ff0000', metalness=50, roughness=50)
/// appearance(example2, color='#00ff00', metalness=50, roughness=50)
/// ```
///
/// ```kcl,legacySketch
/// // 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.
/// firstSketch = startSketchOn(XY)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0])
/// |> close()
/// |> extrude(length = 6)
///
/// shell(
/// firstSketch,
/// faces = [END],
/// thickness = 0.25,
/// )
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
/// ```
///
/// ```kcl,legacySketch
/// // 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.
/// firstSketch = startSketchOn(XY)
/// |> startProfile(at = [-12, 12])
/// |> line(end = [24, 0])
/// |> line(end = [0, -24])
/// |> line(end = [-24, 0])
/// |> close()
/// |> extrude(length = 6)
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
///
/// shell(
/// firstSketch,
/// faces = [END],
/// thickness = 0.25,
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
/// // This example shows _before_ the pattern.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 2])
/// |> line(end = [3, 1])
/// |> line(end = [0, -4])
/// |> close()
///
/// example = extrude(exampleSketch, length = 1)
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
/// |> patternLinear3d(
/// axis = [1, 0, 1],
/// instances = 7,
/// distance = 6
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
/// // This example shows _after_ the pattern.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [0, 0])
/// |> line(end = [0, 2])
/// |> line(end = [3, 1])
/// |> line(end = [0, -4])
/// |> close()
///
/// example = extrude(exampleSketch, length = 1)
/// |> patternLinear3d(
/// axis = [1, 0, 1],
/// instances = 7,
/// distance = 6
/// )
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
/// ```
///
/// ```kcl,legacySketch
/// // Color the result of a 2D pattern that was extruded.
/// exampleSketch = startSketchOn(XZ)
/// |> startProfile(at = [.5, 25])
/// |> line(end = [0, 5])
/// |> line(end = [-1, 0])
/// |> line(end = [0, -5])
/// |> close()
/// |> patternCircular2d(
/// center = [0, 0],
/// instances = 13,
/// arcDegrees = 360,
/// rotateDuplicates = true
/// )
///
/// example = extrude(exampleSketch, length = 1)
/// |> appearance(
/// color = '#ff0000',
/// metalness = 90,
/// roughness = 90
/// )
/// ```
///
/// ```kcl,sketchSolve
/// @settings(defaultLengthUnit = mm, kclVersion = 2.0)
///
/// sweepPath = sketch(on = XZ) {
/// line1 = line(start = [var 0.05mm, var 0.05mm], end = [var 0.05mm, var 7.05mm])
/// arc2 = arc(start = [var 0.05mm, var 7.05mm], end = [var -4.95mm, var 12.05mm], center = [var -4.95mm, var 7.05mm])
/// coincident([line1.end, arc2.start])
/// line3 = line(start = [var -4.95mm, var 12.05mm], end = [var -7.95mm, var 12.05mm])
/// coincident([arc2.end, line3.start])
/// arc4 = arc(start = [var -12.95mm, var 17.05mm], end = [var -7.95mm, var 12.05mm], center = [var -7.95mm, var 17.05mm])
/// coincident([line3.end, arc4.end])
/// line5 = line(start = [var -12.95mm, var 17.05mm], end = [var -12.95mm, var 24.05mm])
/// coincident([arc4.start, line5.start])
/// }
/// pipeProfile = sketch(on = XY) {
/// outerCircle = circle(start = [var 2mm, var 0mm], center = [var 0mm, var 0mm])
/// innerCircle = circle(start = [var 1.5mm, var 0mm], center = [var 0mm, var 0mm])
/// }
/// pipeRegion = region(segments = [pipeProfile.outerCircle])
/// sweep(pipeRegion, path = sweepPath)
/// |> appearance(color = "#ff0000", metalness = 50, roughness = 50)
/// ```
///
/// ```kcl,sketchSyntaxAgnostic
/// // Change the appearance of an imported model.
///
/// import "tests/inputs/cube.sldprt" as cube
///
/// cube
/// |> appearance(
/// color = "#ff0000",
/// metalness = 50,
/// roughness = 50
/// )
/// ```
/// ```kcl
/// offsetPlane(XZ, offset = 4mm)
/// |> appearance(color = "#ff0000", opacity = 50)
/// ```
@(impl = std_rust, feature_tree = true)
export fn appearance(
/// The solid(s), imported geometry, or plane whose appearance is being set.
@solids: [Solid; 1+] | ImportedGeometry | Plane,
/// Color of the new material, a hex string like '#ff0000'.
color: string,
/// Metalness of the new material, a percentage like 95.7.
@(includeInSnippet = true)
metalness?: number(Count),
/// Roughness of the new material, a percentage like 95.7.
@(includeInSnippet = true)
roughness?: number(Count),
/// Opacity. Defaults to 100 (totally opaque). 0 would be totally transparent.
opacity?: number(Count),
): [Solid; 1+] | ImportedGeometry | Plane {}
/// Flips the orientation of a surface, swapping which side is the front and which is the reverse.
///
/// ```kcl,legacySketch
/// sideLen = 4
///
/// fn square(@plane, offset, y) {
/// at = if y {
/// [-offset, 0]
/// } else {
/// [0, offset]
/// }
/// return startSketchOn(plane)
/// |> startProfile(at)
/// |> if y { yLine(length = sideLen)} else {xLine(length = sideLen)}
/// |> extrude(length = if y {-sideLen} else {sideLen}, bodyType = SURFACE)
/// }
///
/// // Make a cube polysurface from 6 squares
/// cube = [
/// square(XY, offset = 0, y = false),
/// square(XZ, offset = 0, y = true) |> flipSurface(),
/// square(YZ, offset = 0, y = false),
/// square(XY, offset = sideLen, y = false),
/// square(XZ, offset = -sideLen, y = true),
/// square(YZ, offset = sideLen, y = false)
/// ]
/// ```
/// ```kcl,legacySketch
/// sideLen = 4
///
/// fn square(@plane, offset, y) {
/// at = if y {
/// [-offset, 0]
/// } else {
/// [0, offset]
/// }
/// return startSketchOn(plane)
/// |> startProfile(at)
/// |> if y { yLine(length = sideLen)} else {xLine(length = sideLen)}
/// |> extrude(length = if y {-sideLen} else {sideLen}, bodyType = SURFACE)
/// }
///
/// // Make a cube polysurface from 6 squares
/// cube = [
/// square(XY, offset = 0, y = false),
/// square(XZ, offset = 0, y = true) |> flipSurface(),
/// square(YZ, offset = 0, y = false),
/// square(XY, offset = sideLen, y = false),
/// square(XZ, offset = -sideLen, y = true),
/// square(YZ, offset = sideLen, y = false)
/// ]
/// // Flip the cube inside out
/// flipSurface(cube)
/// ```
@(impl = std_rust, feature_tree = true)
export fn flipSurface(
/// The surfaces to flip (swap the surface's back and front sides)
@surface: [Solid; 1+],
): [Solid; 1+] {}
/// Split all faces of the target body along all faces of the tool bodies.
///
/// ```kcl,legacySketch
/// sideLen = 4
///
/// // Helper function to make a square surface body.
/// fn square(@plane, offset, y) {
/// at = if y {
/// [-offset, 0]
/// } else {
/// [0, offset]
/// }
/// return startSketchOn(plane)
/// |> startProfile(at)
/// |> if y { yLine(length = sideLen)} else {xLine(length = sideLen)}
/// |> extrude(length = if y {-sideLen} else {sideLen}, bodyType = SURFACE)
/// }
///
/// // Make a cube polysurface from 6 squares.
/// cube = [
/// square(XY, offset = 0, y = false),
/// square(XZ, offset = 0, y = true) |> flipSurface(),
/// square(YZ, offset = 0, y = false),
/// square(XY, offset = sideLen, y = false),
/// square(XZ, offset = -sideLen, y = true),
/// square(YZ, offset = sideLen, y = false)
/// ]
///
/// // Via split + merge, create a solid cube from the 6 square surfaces (faces of the cube).
/// cubeSolid = split(cube, merge = true)
///
/// // To prove it's solid, we can set the whole cube's appearance.
/// appearance(cubeSolid, color = "#da4333", roughness = 50, metalness = 90)
/// ```
/// ```kcl,legacySketch
/// cube1 = startSketchOn(XY)
/// |> rectangle(width = 3, height = 3, center = [0, 0])
/// |> extrude(length = 2)
///
/// cube2 = startSketchOn(offsetPlane(XY, offset = 0.4))
/// |> rectangle(width = 3, height = 3, center = [2, 2])
/// |> extrude(length = 2)
///
/// cubes = split([cube1], tools = [cube2], merge = true)
/// |> appearance(color = "#da4333", roughness = 50, metalness = 90, opacity = 80)
/// ```
/// ```kcl,legacySketch
/// goldCube = startSketchOn(XY)
/// |> rectangle(width = 10, height = 10, center = [0, 0])
/// |> extrude(length = 10)
/// |> appearance(color = "#da7333", roughness = 50, metalness = 90)
///
/// roseCube = startSketchOn(offsetPlane(XY, offset = 2))
/// |> rectangle(width = 10, height = 10, center = [4, 2])
/// |> extrude(length = 10)
/// |> appearance(color = "#da4333", roughness = 50, metalness = 90)
///
/// // Split the gold cube along the edges of rose cube. Keep rose cube in place after.
/// final = split([goldCube], tools = [roseCube], merge = true, keepTools = true)
/// // You can't see it, because the rose cube is covering it, but the gold cube now has
/// // had its faces split along the edges of the rose cube.
/// ```
/// ```kcl,legacySketch
/// goldCube = startSketchOn(XY)
/// |> rectangle(width = 10, height = 10, center = [0, 0])
/// |> extrude(length = 10)
/// |> appearance(color = "#da7333", roughness = 50, metalness = 90)
///
/// roseCube = startSketchOn(offsetPlane(XY, offset = 2))
/// |> rectangle(width = 10, height = 10, center = [4, 2])
/// |> extrude(length = 10)
/// |> appearance(color = "#da4333", roughness = 50, metalness = 90)
///
/// // Split the gold cube along the edges of rose cube.
/// // Then delete some of the new faces that were created on gold cube.
/// final = split([goldCube], tools = [roseCube], merge = true)
/// |> deleteFace(faceIndices = [6, 8])
/// ```
/// ```kcl,legacySketch
/// // Make a cylinder.
/// sketch001 = startSketchOn(XY)
/// profile001 = circle(
/// sketch001,
/// center = [0, 0],
/// radius = 4.09,
/// tag = $seg01,
/// )
/// cylinder = extrude(profile001, length = 5)
///
/// // Make a wedge that splits the cylinder down the middle.
/// sketch002 = startSketchOn(XY)
/// profile002 = startProfile(sketch002, at = [0, -4.75])
/// |> angledLine(angle = 0deg, length = 2, tag = $a)
/// |> angledLine(angle = segAng(a) + 90deg, length = 9.5)
/// |> angledLine(angle = segAng(a), length = -segLen(a))
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
/// |> close()
/// wedge = extrude(profile002, length = 15, symmetric = true)
///
/// // Split the cylinder down the wedge.
/// result = split([cylinder], tools = [wedge])
///
/// // Color each part of the split cylinder differently,
/// // and move the parts a bit away from each other,
/// // so you can see their interiors.
/// right = appearance(result[2], color = "#B2FFD6")
/// |> translate(x = 4)
///
/// middle = appearance(result[1], color = "#F6AE2D")
///
/// left = appearance(result[0], color = "#AA78A6")
/// |> translate(x = -4)
///
/// ```
@(impl = std_rust, feature_tree = true)
export fn split(
/// The bodies to split
@targets: [Solid; 1+],
/// Whether to merge the bodies into one after.
/// Defaults to false.
merge?: bool,
/// If false, the tool bodies will be removed from the scene.
/// If true, they'll be kept.
/// Defaults to false.
keepTools?: bool,
/// The tools to split the target bodies along.
tools?: [Solid],
/// You probably shouldn't set this or care about this, it's for opting back into an older version of an engine algorithm.
/// If true, revert to older engine SSI algorithm.
/// Defaults to false.
@(deprecated_since = "2.0")
legacyMethod?: bool,
): [Solid; 1+] {}
/// Given a KCL value that is a "body" (currently typed as `Solid`), returns `true` if the value is a solid and `false` otherwise.
///
/// ```kcl,legacySketch
/// fn square(@plane, origin, side, body_type) {
/// return startSketchOn(plane)
/// |> startProfile(at = origin)
/// |> yLine(length = side)
/// |> xLine(length = side)
/// |> yLine(length = -side)
/// |> xLine(length = -side)
/// |> extrude(length = side, bodyType = body_type)
/// }
///
/// originX0Y0 = [0, 0]
/// originX10Y0 = [10, 0]
///
/// cube = square(
/// XY,
/// origin = originX0Y0,
/// side = 5,
/// body_type = "solid",
/// )
/// openBoxSurface = square(
/// XY,
/// origin = originX10Y0,
/// side = 6,
/// body_type = "surface",
/// )
///
/// assertIs(isSolid(cube))
/// assertIs(isSurface(openBoxSurface))
///
/// // surface is not a solid
/// assertIs(!isSolid(openBoxSurface))
///
/// // solid is not a surface
/// assertIs(!isSurface(cube))
/// ```
@(impl = std_rust, feature_tree = true)
export fn isSolid(
/// Value to check if it is a solid or not
@val: Solid,
): bool {}
/// Given a KCL value that is a 'body' (currently typed as `Solid`), returns `true` if the value is a surface and `false` otherwise.
///
/// ```kcl,legacySketch
/// fn square(@plane, origin, side, body_type) {
/// return startSketchOn(plane)
/// |> startProfile(at = origin)
/// |> yLine(length = side)
/// |> xLine(length = side)
/// |> yLine(length = -side)
/// |> xLine(length = -side)
/// |> extrude(length = side, bodyType = body_type)
/// }
///
/// originX0Y0 = [0, 0]
/// originX10Y0 = [10, 0]
///
/// cube = square(
/// XY,
/// origin = originX0Y0,
/// side = 5,
/// body_type = "solid",
/// )
/// openBoxSurface = square(
/// XY,
/// origin = originX10Y0,
/// side = 6,
/// body_type = "surface",
/// )
///
/// assertIs(isSolid(cube))
/// assertIs(isSurface(openBoxSurface))
///
/// // surface is not a solid
/// assertIs(!isSolid(openBoxSurface))
///
/// // solid is not a surface
/// assertIs(!isSurface(cube))
/// ```
@(impl = std_rust, feature_tree = true)
export fn isSurface(
/// Value to check if it is a surface or not
@val: Solid,
): bool {}
/// Delete a face from a body (a solid, or a polysurface).
/// ```kcl,legacySketch
/// // Make an extruded triangle.
/// startSketchOn(XY)
/// |> startProfile(at = [0, 15])
/// |> xLine(length = 10, tag = $a)
/// |> yLine(length = 8)
/// |> close()
/// |> extrude(length = 2)
/// // Delete some faces.
/// |> deleteFace(faces = [a, END])
/// ```
/// ```kcl,legacySketch
/// // Make an extruded square.
/// startSketchOn(XY)
/// |> polygon(radius = 10, numSides = 4, center = [0, 0])
/// |> extrude(length = 2)
/// // Delete some faces. Because there's no tags, we can delete by face _index_.
/// |> deleteFace(faceIndices = [0, 5])
/// ```
/// ```kcl,legacySketch
/// sideLen = 4
///
/// // Helper function to make a square surface body.
/// fn square(@plane, offset, y) {
/// at = if y {
/// [-offset, 0]
/// } else {
/// [0, offset]
/// }
/// return startSketchOn(plane)
/// |> startProfile(at)
/// |> if y { yLine(length = sideLen)} else {xLine(length = sideLen)}
/// |> extrude(length = if y {-sideLen} else {sideLen}, bodyType = SURFACE)
/// }
///
/// // Make a cube polysurface from 6 squares.
/// cube = [
/// square(XY, offset = 0, y = false),
/// square(XZ, offset = 0, y = true) |> flipSurface(),
/// square(YZ, offset = 0, y = false),
/// square(XY, offset = sideLen, y = false),
/// square(XZ, offset = -sideLen, y = true),
/// square(YZ, offset = sideLen, y = false)
/// ]
///
/// // Via split + merge, create a solid cube from the 6 square surfaces (faces of the cube).
/// cubeSolid = split(cube, merge = true)
///
/// // We can delete faces using their face index, because there's no tags on this cube.
/// deleteFace(cubeSolid, faceIndices = [0, 1])
/// ```
/// ```kcl,sketchSolve
/// boxProfile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 5mm, var 0mm])
/// edge2 = line(start = [var 5mm, var 0mm], end = [var 5mm, var 5mm])
/// edge3 = line(start = [var 5mm, var 5mm], end = [var 0mm, var 5mm])
/// edge4 = line(start = [var 0mm, var 5mm], end = [var 0mm, var 0mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// horizontal(edge1)
/// vertical(edge2)
/// horizontal(edge3)
/// vertical(edge4)
/// }
///
/// box = extrude(region(segments = [boxProfile.edge1, boxProfile.edge2]), length = 4mm, tagEnd = $top)
/// openBox = deleteFace(box, faces = [top])
/// ```
@(impl = std_rust, feature_tree = true)
export fn deleteFace(
/// Target to delete a surface from.
@body: Solid,
/// Face to delete. This is the usual face representation, e.g. a tagged face.
faces?: [TaggedFace; 1+],
/// Face to delete.
/// The index is a stable ordering of faces, used when you can't get the
/// usual ID (UUID) of a face.
faceIndices?: [number(Count); 1+],
): Solid {}
/// Blend two surfaces together.
/// Use [bounded edges](/docs/kcl-std/types/std-types-BoundedEdge) to control the extents of the newly created surface, or tagged edges to use the full edge span.
/// ```kcl,legacySketch
/// sketch001 = startSketchOn(XY)
/// profile001 = startProfile(sketch001, at = [-2, 0])
/// |> angledLine(angle = 0deg, length = 4, tag = $rectangleSegmentA001)
/// |> extrude(length = 2, bodyType = SURFACE)
/// |> translate(y = 3, z = 2)
///
/// sketch002 = startSketchOn(XZ)
/// profile002 = startProfile(sketch002, at = [-1, 0])
/// |> angledLine(angle = 0deg, length = 2, tag = $rectangleSegmentA002)
/// |> extrude(length = 2, bodyType = SURFACE)
/// |> flipSurface()
///
/// edge001 = getBoundedEdge(profile001, edge = rectangleSegmentA001, lowerBound = 0.1, upperBound = 0.9)
/// edge002 = getBoundedEdge(profile002, edge = rectangleSegmentA002)
///
/// blend([edge001, edge002])
/// ```
///
/// Or blend the full edges directly with tagged edges (no `getBoundedEdge`):
/// ```kcl,legacySketch
/// sketch001 = startSketchOn(XY)
/// profile001 = startProfile(sketch001, at = [-2, 0])
/// |> angledLine(angle = 0deg, length = 4, tag = $rectangleSegmentA001)
/// |> extrude(length = 2, bodyType = SURFACE)
/// |> translate(y = 3, z = 2)
///
/// sketch002 = startSketchOn(XZ)
/// profile002 = startProfile(sketch002, at = [-1, 0])
/// |> angledLine(angle = 0deg, length = 2, tag = $rectangleSegmentA002)
/// |> extrude(length = 2, bodyType = SURFACE)
/// |> flipSurface()
///
/// blend([rectangleSegmentA001, rectangleSegmentA002])
/// ```
///
/// Experimental face API: edge specifier objects are supported for testing, but are not ready for generated or user-facing KCL yet; prefer tagged edges or bounded edges until point-and-click and migration support ships.
/// Sketch block tags work too:
/// ```kcl,sketchSolve
/// sketch001 = sketch(on = YZ) {
/// line1 = line(start = [var 4.1mm, var -0.1mm], end = [var 5.5mm, var 0mm])
/// line2 = line(start = [var 5.5mm, var 0mm], end = [var 5.5mm, var 3mm])
/// line3 = line(start = [var 5.5mm, var 3mm], end = [var 3.9mm, var 2.8mm])
/// line4 = line(start = [var 4.1mm, var 3mm], end = [var 4.5mm, var -0.2mm])
/// coincident([line1.end, line2.start])
/// coincident([line2.end, line3.start])
/// coincident([line3.end, line4.start])
/// coincident([line4.end, line1.start])
/// }
///
/// sketch002 = sketch(on = -XZ) {
/// line5 = line(start = [var -5.3mm, var -0.1mm], end = [var -3.5mm, var -0.1mm])
/// line6 = line(start = [var -3.5mm, var -0.1mm], end = [var -3.5mm, var 3.1mm])
/// line7 = line(start = [var -3.5mm, var 4.5mm], end = [var -5.4mm, var 4.5mm])
/// line8 = line(start = [var -5.3mm, var 3.1mm], end = [var -5.3mm, var -0.1mm])
/// coincident([line5.end, line6.start])
/// coincident([line6.end, line7.start])
/// coincident([line7.end, line8.start])
/// coincident([line8.end, line5.start])
/// }
///
/// region001 = region(segments = [sketch002.line5, sketch002.line6])
/// extrude001 = extrude(region001, length = -2mm, bodyType = SURFACE)
/// region002 = region(segments = [sketch001.line1, sketch001.line2])
/// extrude002 = extrude(region002, length = -2mm, bodyType = SURFACE)
///
/// myBlend = blend([extrude001.sketch.tags.line7, extrude002.sketch.tags.line3])
/// ```
@(impl = std_rust, feature_tree = true)
export fn blend(
/// The two edges that will be blended.
/// Tagged edges blend the full edge length. Experimental face API: edge specifier objects (`{ sideFaces = [...], endFaces? = [...], index? = 0 }`) are not ready for generated or user-facing KCL yet; prefer tagged edges or bounded edges until point-and-click and migration support ships.
@edges: [BoundedEdge | TaggedEdge | any; 2],
): Solid {}
/// ```kcl,legacySketch
/// @settings(defaultLengthUnit = mm)
///
/// beamSectionWidth = 40
/// beamSectionHeight = 95
/// beamLength = 142
/// beamCurvedRadius = 2000
/// beamCurvedArcLength = beamLength
/// beamBoxCutterInset = 8
/// beamForkCutterGap = 2
/// beamForkCutterTipExtension = beamBoxCutterInset + beamForkCutterGap
///
/// beamHalfWidth = beamSectionWidth / 2
/// beamHalfHeight = beamSectionHeight / 2
/// beamCurvedAngle = -(beamCurvedArcLength / beamCurvedRadius): number(rad)
/// beamForkCutterHalfWidth = beamHalfWidth + beamForkCutterGap
/// beamForkCutterHalfHeight = beamHalfHeight + beamForkCutterGap
/// beamForkCutterBackX = beamForkCutterHalfWidth
/// beamForkCutterOpenX = -beamForkCutterHalfWidth - beamForkCutterTipExtension
///
///
/// beamForkCutterStraightProfile = startSketchOn(XZ)
/// |> startProfile(at = [beamForkCutterOpenX, beamForkCutterHalfHeight])
/// |> line(
/// end = [beamForkCutterBackX - beamForkCutterOpenX, 0],
/// tag = $beamForkCutterTopStraightEdge,
/// )
/// |> line(end = [0, -2 * beamForkCutterHalfHeight], tag = $beamForkCutterBackStraightEdge)
/// |> line(
/// end = [beamForkCutterOpenX - beamForkCutterBackX, 0],
/// tag = $beamForkCutterBottomStraightEdge,
/// )
///
/// beamForkCutterStraight = extrude(
/// beamForkCutterStraightProfile,
/// length = beamLength,
/// bodyType = SURFACE,
/// )
///
/// beamForkCutterCurvedProfile = startSketchOn(XZ)
/// |> startProfile(at = [beamForkCutterOpenX, beamForkCutterHalfHeight])
/// |> line(
/// end = [beamForkCutterBackX - beamForkCutterOpenX, 0],
/// tag = $beamForkCutterTopCurvedEdge,
/// )
/// |> line(end = [0, -2 * beamForkCutterHalfHeight], tag = $beamForkCutterBackCurvedEdge)
/// |> line(
/// end = [beamForkCutterOpenX - beamForkCutterBackX, 0],
/// tag = $beamForkCutterBottomCurvedEdge,
/// )
///
/// curvedBeamAxis = {
/// direction = [0, 1],
/// origin = [beamCurvedRadius, 0]
/// }
///
/// beamForkCutterCurved = revolve(
/// beamForkCutterCurvedProfile,
/// axis = curvedBeamAxis,
/// angle = beamCurvedAngle,
/// bodyType = SURFACE,
/// )
///
/// beamForkCutterCurvedPlaced = beamForkCutterCurved
/// |> rotate(axis = Z, angle = -22deg, global = true)
/// |> translate(x = 93, y = 453, global = true)
///
/// beamForkCutterTopBlend = blend([
/// getBoundedEdge(beamForkCutterCurvedPlaced, edge = getOppositeEdge(beamForkCutterTopCurvedEdge)),
/// beamForkCutterTopStraightEdge,
/// ])
///
/// beamForkCutterBackBlend = blend([
/// getBoundedEdge(beamForkCutterCurvedPlaced, edge = getOppositeEdge(beamForkCutterBackCurvedEdge)),
/// beamForkCutterBackStraightEdge,
/// ])
///
/// beamForkCutterBottomBlend = blend([
/// getBoundedEdge(beamForkCutterCurvedPlaced, edge = getOppositeEdge(beamForkCutterBottomCurvedEdge)),
/// beamForkCutterBottomStraightEdge,
/// ])
///
/// bumperBeamForkCutter = [
/// beamForkCutterTopBlend,
/// beamForkCutterBackBlend,
/// beamForkCutterBottomBlend,
/// ]
/// |> joinSurfaces()
/// ```
/// Join multiple surfaces together into one body, or join together the results of a split into one body
@(impl = std_rust, feature_tree = true)
export fn joinSurfaces(
/// The bodies to join together
@selection: [Solid; 1+],
/// Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters.
tolerance?: number(Length),
): Solid {}