Files
modeling-app/rust/kcl-lib/std/sketch.kcl
Adam Chalmers 36c8ad439d KCL: Add diameter arg to circle (#7116)
Paul's been requesting this for a long time. Now that we're fully using keyword args, this is easy to do.

We should probably add a similar `diameter` arg to `arc`, `tangentialArc`, `polygon` etc. And _maybe_ to `fillet`, but that might not be as helpful.
2025-05-20 19:44:35 +00:00

308 lines
9.6 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.
center: Point2d,
/// The radius of the circle. Incompatible with `diameter`.
radius?: number(Length),
/// The diameter of the circle. Incompatible with `radius`.
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+] {}