/// 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) import Face 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. /// /// ``` /// 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) /// ], /// ) /// ``` /// /// ``` /// 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) /// ], /// ) /// ``` @(impl = std_rust) 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 tags: [Edge; 1+], /// The tolerance for this fillet tolerance?: number(Length), /// Create a new tag which refers to this fillet tag?: TagDecl, ): 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. /// /// ``` /// // 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) /// ], /// ) /// ``` /// /// ``` /// // 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) /// ``` @(impl = std_rust) export fn chamfer( /// The solid whose edges should be chamfered @solid: Solid, /// The length of the chamfer length: number(Length), /// The paths you want to chamfer tags: [Edge; 1+], /// Create a new tag which refers to this chamfer tag?: TagDecl, ): 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. /// /// ``` /// // 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, /// ) /// ``` /// /// ``` /// // 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, /// ) /// ``` /// /// ``` /// // 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, /// ) /// ``` /// /// ``` /// // 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, /// ) /// ``` /// /// ``` /// // 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) /// ``` /// /// ``` /// // 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) /// ``` /// /// ``` /// // 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) /// ``` @(impl = std_rust) 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. /// /// ``` /// // Hollow a basic sketch. /// firstSketch = startSketchOn(XY) /// |> startProfile(at = [-12, 12]) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// |> extrude(length = 6) /// |> hollow (thickness = 0.25) /// ``` /// /// ``` /// // Hollow a basic sketch. /// firstSketch = startSketchOn(-XZ) /// |> startProfile(at = [-12, 12]) /// |> line(end = [24, 0]) /// |> line(end = [0, -24]) /// |> line(end = [-24, 0]) /// |> close() /// |> extrude(length = 6) /// |> hollow (thickness = 0.5) /// ``` /// /// ``` /// // 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) export fn hollow( /// Which solid to hollow out @solid: Solid, /// The thickness of the remaining shell thickness: number(Length), ): Solid {} /// Repeat a 3-dimensional solid, changing it each time. /// /// Replicates the 3D solid, 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") /// /// ```kcl /// // 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 /// // 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 /// 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 /// 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 /// // 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, 0], /// } /// } /// // 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 /// 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) /// ``` @(impl = std_rust) export fn patternTransform( /// The solid(s) to duplicate. @solids: [Solid; 1+], /// 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; 1+] {} /// Repeat a 3-dimensional solid along a linear path, with a dynamic amount /// of distance between each repetition, some specified number of times. /// /// ```kcl /// /// 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 /// /// 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 /// // 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 /// // 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) export fn patternLinear3d( /// The solid(s) to duplicate. @solids: [Solid; 1+], /// 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; 1+] {} /// Repeat a 3-dimensional solid 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 /// /// 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 /// /// 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) export fn patternCircular3d( /// The solid(s) to pattern. @solids: [Solid; 1+], /// 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. @(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; 1+] {} /// Union two or more solids into a single solid. /// /// ```kcl /// // 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 /// // 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 /// // 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) export fn union( /// The solids to union. @solids: [Solid; 2+], /// The tolerance to use for the union operation. tolerance?: number(Length), ): [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. /// /// ```kcl /// // 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 /// // 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) export fn intersect( /// The solids to intersect. @solids: [Solid; 2+], /// The tolerance to use for the intersection operation. tolerance?: number(Length), ): [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. /// /// ```kcl /// // Subtract a cylinder from a cube 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) /// /// subtractedPart = subtract([part001], tools=[part002]) /// ``` /// /// ```kcl /// // Subtract a cylinder from a cube 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: subtract([part001], tools=[part002]) /// subtractedPart = part001 - part002 /// ``` @(impl = std_rust) export fn subtract( /// The solids to use as the base to subtract from. @solids: [Solid; 1+], /// The solids to subtract. tools: [Solid], /// The tolerance to use for the subtraction operation. tolerance?: number(Length), ): [Solid; 1+] {} /// Set the appearance of a solid. This only works on solids, not sketches or individual paths. /// /// This will work on any solid, including extruded solids, revolved solids, and shelled solids. /// /// ```kcl /// // 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 /// // 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 /// // 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 /// // 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 /// // 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 /// // 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 /// // 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 /// // 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 /// // Color the result of a sweep. /// /// // Create a path for the sweep. /// sweepPath = startSketchOn(XZ) /// |> startProfile(at = [0.05, 0.05]) /// |> line(end = [0, 7]) /// |> tangentialArc(angle = 90deg, radius = 5) /// |> line(end = [-3, 0]) /// |> tangentialArc(angle = -90deg, radius = 5) /// |> line(end = [0, 7]) /// /// pipeHole = startSketchOn(XY) /// |> circle( /// center = [0, 0], /// radius = 1.5, /// ) /// /// sweepSketch = startSketchOn(XY) /// |> circle( /// center = [0, 0], /// radius = 2, /// ) /// |> subtract2d(tool = pipeHole) /// |> sweep(path = sweepPath) /// |> appearance( /// color = "#ff0000", /// metalness = 50, /// roughness = 50 /// ) /// ``` /// /// ```kcl /// // Change the appearance of an imported model. /// /// import "tests/inputs/cube.sldprt" as cube /// /// cube /// |> appearance( /// color = "#ff0000", /// metalness = 50, /// roughness = 50 /// ) /// ``` @(impl = std_rust) export fn appearance( /// The The solid(s) whose appearance is being set. @solids: [Solid; 1+] | ImportedGeometry, /// Color of the new material, a hex string like '#ff0000'. color: string, /// Metalness of the new material, a percentage like 95.7. metalness?: number(Count), /// Roughness of the new material, a percentage like 95.7. roughness?: number(Count), ): [Solid; 1+] | ImportedGeometry {}