441 lines
13 KiB
Plaintext
441 lines
13 KiB
Plaintext
/// Sketching is the foundational activity for most KCL programs. A sketch is a two-dimensional
|
|
/// drawing made from paths or shapes. A sketch is always drawn on a surface (either an abstract
|
|
/// plane of a face of a solid). A sketch can be made into a solid by extruding it (or revolving, etc.).
|
|
///
|
|
/// This module contains functions for creating and manipulating sketches, and making them into solids.
|
|
|
|
@no_std
|
|
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
|
|
/// Construct a 2-dimensional circle, of the specified radius, centered at
|
|
/// the provided (x, y) origin point.
|
|
///
|
|
/// ```
|
|
/// exampleSketch = startSketchOn(-XZ)
|
|
/// |> circle(center = [0, 0], radius = 10)
|
|
///
|
|
/// example = extrude(exampleSketch, length = 5)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// exampleSketch = startSketchOn(XZ)
|
|
/// |> startProfile(at = [-15, 0])
|
|
/// |> line(end = [30, 0])
|
|
/// |> line(end = [0, 30])
|
|
/// |> line(end = [-30, 0])
|
|
/// |> close()
|
|
/// |> subtract2d(tool = circle(center = [0, 15], diameter = 10))
|
|
///
|
|
/// example = extrude(exampleSketch, length = 5)
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn circle(
|
|
/// Sketch to extend, or plane or surface to sketch on.
|
|
@sketch_or_surface: Sketch | Plane | Face,
|
|
/// The center of the circle.
|
|
@(snippetArray = ["0", "0"])
|
|
center: Point2d,
|
|
/// The radius of the circle. Incompatible with `diameter`.
|
|
radius?: number(Length),
|
|
/// The diameter of the circle. Incompatible with `radius`.
|
|
@(includeInSnippet = true)
|
|
diameter?: number(Length),
|
|
/// Create a new tag which refers to this circle.
|
|
tag?: tag,
|
|
): Sketch {}
|
|
|
|
/// Rotate a sketch around some provided axis, creating a solid from its extent.
|
|
///
|
|
/// This, like extrude, is able to create a 3-dimensional solid from a
|
|
/// 2-dimensional sketch. However, unlike extrude, this creates a solid
|
|
/// by using the extent of the sketch as its revolved around an axis rather
|
|
/// than using the extent of the sketch linearly translated through a third
|
|
/// dimension.
|
|
///
|
|
/// Revolve occurs around a local sketch axis rather than a global axis.
|
|
///
|
|
/// You can provide more than one sketch to revolve, and they will all be
|
|
/// revolved around the same axis.
|
|
///
|
|
/// ```
|
|
/// part001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [4, 12])
|
|
/// |> line(end = [2, 0])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [4, -6])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [-3.75, -4.5])
|
|
/// |> line(end = [0, -5.5])
|
|
/// |> line(end = [-2, 0])
|
|
/// |> close()
|
|
/// |> revolve(axis = Y) // default angle is 360
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // A donut shape.
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> circle( center = [15, 0], radius = 5 )
|
|
/// |> revolve(
|
|
/// angle = 360,
|
|
/// axis = Y,
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// part001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [4, 12])
|
|
/// |> line(end = [2, 0])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [4, -6])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [-3.75, -4.5])
|
|
/// |> line(end = [0, -5.5])
|
|
/// |> line(end = [-2, 0])
|
|
/// |> close()
|
|
/// |> revolve(axis = Y, angle = 180)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// part001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [4, 12])
|
|
/// |> line(end = [2, 0])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [4, -6])
|
|
/// |> line(end = [0, -6])
|
|
/// |> line(end = [-3.75, -4.5])
|
|
/// |> line(end = [0, -5.5])
|
|
/// |> line(end = [-2, 0])
|
|
/// |> close()
|
|
/// |> revolve(axis = Y, angle = 180)
|
|
///
|
|
/// part002 = startSketchOn(part001, face = END)
|
|
/// |> startProfile(at = [4.5, -5])
|
|
/// |> line(end = [0, 5])
|
|
/// |> line(end = [5, 0])
|
|
/// |> line(end = [0, -5])
|
|
/// |> close()
|
|
/// |> extrude(length = 5)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// box = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20])
|
|
/// |> line(end = [20, 0])
|
|
/// |> line(end = [0, -20])
|
|
/// |> close()
|
|
/// |> extrude(length = 20)
|
|
///
|
|
/// sketch001 = startSketchOn(box, face = END)
|
|
/// |> circle( center = [10,10], radius = 4 )
|
|
/// |> revolve(
|
|
/// angle = -90,
|
|
/// axis = Y
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// box = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20])
|
|
/// |> line(end = [20, 0])
|
|
/// |> line(end = [0, -20], tag = $revolveAxis)
|
|
/// |> close()
|
|
/// |> extrude(length = 20)
|
|
///
|
|
/// sketch001 = startSketchOn(box, face = END)
|
|
/// |> circle( center = [10,10], radius = 4 )
|
|
/// |> revolve(
|
|
/// angle = 90,
|
|
/// axis = getOppositeEdge(revolveAxis)
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// box = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20])
|
|
/// |> line(end = [20, 0])
|
|
/// |> line(end = [0, -20], tag = $revolveAxis)
|
|
/// |> close()
|
|
/// |> extrude(length = 20)
|
|
///
|
|
/// sketch001 = startSketchOn(box, face = END)
|
|
/// |> circle( center = [10,10], radius = 4 )
|
|
/// |> revolve(
|
|
/// angle = 90,
|
|
/// axis = getOppositeEdge(revolveAxis),
|
|
/// tolerance = 0.0001
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [10, 0])
|
|
/// |> line(end = [5, -5])
|
|
/// |> line(end = [5, 5])
|
|
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
/// |> close()
|
|
///
|
|
/// part001 = revolve(
|
|
/// sketch001,
|
|
/// axis = {
|
|
/// direction = [0.0, 1.0],
|
|
/// origin = [0.0, 0.0]
|
|
/// }
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // Revolve two sketches around the same axis.
|
|
///
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// profile001 = startProfile(sketch001, at = [4, 8])
|
|
/// |> xLine(length = 3)
|
|
/// |> yLine(length = -3)
|
|
/// |> xLine(length = -3)
|
|
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
/// |> close()
|
|
///
|
|
/// profile002 = startProfile(sketch001, at = [-5, 8])
|
|
/// |> xLine(length = 3)
|
|
/// |> yLine(length = -3)
|
|
/// |> xLine(length = -3)
|
|
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
/// |> close()
|
|
///
|
|
/// revolve(
|
|
/// [profile001, profile002],
|
|
/// axis = X,
|
|
/// )
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // Revolve around a path that has not been extruded.
|
|
///
|
|
/// profile001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20], tag = $revolveAxis)
|
|
/// |> line(end = [20, 0])
|
|
/// |> line(end = [0, -20])
|
|
/// |> close(%)
|
|
///
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> circle(center = [-10, 10], radius = 4)
|
|
/// |> revolve(angle = 90, axis = revolveAxis)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // Revolve around a path that has not been extruded or closed.
|
|
///
|
|
/// profile001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20], tag = $revolveAxis)
|
|
/// |> line(end = [20, 0])
|
|
///
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> circle(center = [-10, 10], radius = 4)
|
|
/// |> revolve(angle = 90, axis = revolveAxis)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // Symmetrically revolve around a path.
|
|
///
|
|
/// profile001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20], tag = $revolveAxis)
|
|
/// |> line(end = [20, 0])
|
|
///
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> circle(center = [-10, 10], radius = 4)
|
|
/// |> revolve(angle = 90, axis = revolveAxis, symmetric = true)
|
|
/// ```
|
|
///
|
|
/// ```
|
|
/// // Bidirectional revolve around a path.
|
|
///
|
|
/// profile001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, 20], tag = $revolveAxis)
|
|
/// |> line(end = [20, 0])
|
|
///
|
|
/// sketch001 = startSketchOn(XY)
|
|
/// |> circle(center = [-10, 10], radius = 4)
|
|
/// |> revolve(angle = 90, axis = revolveAxis, bidirectionalAngle = 50)
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn revolve(
|
|
/// The sketch or set of sketches that should be revolved
|
|
@sketches: [Sketch; 1+],
|
|
/// Axis of revolution.
|
|
axis: Axis2d | Edge,
|
|
/// Angle to revolve (in degrees). Default is 360.
|
|
angle?: number(Angle),
|
|
/// Tolerance for the revolve operation.
|
|
tolerance?: number(Length),
|
|
/// If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch.
|
|
symmetric?: bool,
|
|
/// If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored.
|
|
bidirectionalAngle?: number(Angle),
|
|
/// A named tag for the face at the start of the revolve, i.e. the original sketch.
|
|
tagStart?: tag,
|
|
/// A named tag for the face at the end of the revolve.
|
|
tagEnd?: tag,
|
|
): [Solid; 1+] {}
|
|
|
|
/// Just like `patternTransform`, but works on 2D sketches not 3D solids.
|
|
///
|
|
/// ```kcl
|
|
/// // Each instance will be shifted along the X axis.
|
|
/// fn transform(@id) {
|
|
/// return { translate = [4 * id, 0] }
|
|
/// }
|
|
///
|
|
/// // Sketch 4 circles.
|
|
/// sketch001 = startSketchOn(XZ)
|
|
/// |> circle(center = [0, 0], radius = 2)
|
|
/// |> patternTransform2d(instances = 4, transform = transform)
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn patternTransform2d(
|
|
/// The sketch(es) to duplicate.
|
|
@sketches: [Sketch; 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?: boolean = false,
|
|
): [Sketch; 1+] {}
|
|
|
|
/// Get the opposite edge to the edge given.
|
|
///
|
|
/// ```kcl
|
|
/// exampleSketch = startSketchOn(XZ)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 60,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> angledLine(
|
|
/// angle = 120,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> line(end = [-10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 240,
|
|
/// length = 10,
|
|
/// tag = $referenceEdge,
|
|
/// )
|
|
/// |> close()
|
|
///
|
|
/// example = extrude(exampleSketch, length = 5)
|
|
/// |> fillet(
|
|
/// radius = 3,
|
|
/// tags = [getOppositeEdge(referenceEdge)],
|
|
/// )
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn getOppositeEdge(
|
|
/// The tag of the edge you want to find the opposite edge of.
|
|
@edge: tag,
|
|
): Edge {}
|
|
|
|
/// Get the next adjacent edge to the edge given.
|
|
///
|
|
/// ```kcl
|
|
/// exampleSketch = startSketchOn(XZ)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 60,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> angledLine(
|
|
/// angle = 120,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> line(end = [-10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 240,
|
|
/// length = 10,
|
|
/// tag = $referenceEdge,
|
|
/// )
|
|
/// |> close()
|
|
///
|
|
/// example = extrude(exampleSketch, length = 5)
|
|
/// |> fillet(
|
|
/// radius = 3,
|
|
/// tags = [getNextAdjacentEdge(referenceEdge)],
|
|
/// )
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn getNextAdjacentEdge(
|
|
/// The tag of the edge you want to find the next adjacent edge of.
|
|
@edge: tag,
|
|
): Edge {}
|
|
|
|
/// Get the previous adjacent edge to the edge given.
|
|
///
|
|
/// ```kcl
|
|
/// exampleSketch = startSketchOn(XZ)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 60,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> angledLine(
|
|
/// angle = 120,
|
|
/// length = 10,
|
|
/// )
|
|
/// |> line(end = [-10, 0])
|
|
/// |> angledLine(
|
|
/// angle = 240,
|
|
/// length = 10,
|
|
/// tag = $referenceEdge,
|
|
/// )
|
|
/// |> close()
|
|
///
|
|
/// example = extrude(exampleSketch, length = 5)
|
|
/// |> fillet(
|
|
/// radius = 3,
|
|
/// tags = [getPreviousAdjacentEdge(referenceEdge)],
|
|
/// )
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn getPreviousAdjacentEdge(
|
|
/// The tag of the edge you want to find the previous adjacent edge of.
|
|
@edge: tag,
|
|
): Edge {}
|
|
|
|
/// Get the shared edge between two faces.
|
|
///
|
|
/// ```kcl
|
|
/// // Get an edge shared between two faces, created after a chamfer.
|
|
///
|
|
/// scale = 20
|
|
/// part001 = startSketchOn(XY)
|
|
/// |> startProfile(at = [0, 0])
|
|
/// |> line(end = [0, scale])
|
|
/// |> line(end = [scale, 0])
|
|
/// |> line(end = [0, -scale])
|
|
/// |> close(tag = $line0)
|
|
/// |> extrude(length = 20, tagEnd = $end0)
|
|
/// // We tag the chamfer to reference it later.
|
|
/// |> chamfer(length = 10, tags = [getOppositeEdge(line0)], tag = $chamfer0)
|
|
///
|
|
/// // Get the shared edge between the chamfer and the extrusion.
|
|
/// commonEdge = getCommonEdge(faces = [chamfer0, end0])
|
|
///
|
|
/// // Chamfer the shared edge.
|
|
/// // TODO: uncomment this when ssi for fillets lands
|
|
/// // chamfer(part001, length = 5, tags = [commonEdge])
|
|
/// ```
|
|
@(impl = std_rust)
|
|
export fn getCommonEdge(
|
|
/// The tags of the faces you want to find the common edge between.
|
|
faces: [tag; 2],
|
|
): Edge {}
|