/// Functions for sketch-solve using constraints. This module's items are for
/// use within sketch blocks.
///
/// ```kcl,inline,sketchSolve
/// triangle = sketch(on = XY) {
/// line1 = line(start = [var -0.05mm, var -0.01mm], end = [var 3.88mm, var 0.81mm])
/// line2 = line(start = [var 3.88mm, var 0.81mm], end = [var 0.92mm, var 4.67mm])
/// coincident([line1.end, line2.start])
/// line3 = line(start = [var 0.92mm, var 4.67mm], end = [var -0.03mm, var -0.04mm])
/// coincident([line2.end, line3.start])
/// coincident([line1.start, line3.end])
/// horizontal(line1)
/// equalLength([line2, line3])
/// }
///
/// triangleRegion = region(point = [0.5mm, 0.5mm], sketch = triangle)
/// extrude(triangleRegion, length = 5)
/// ```
///
/// In the above example, the `sketch(on = XY) { ... }` is called the sketch
/// block. Inside the curly braces, all the functions and constants in this
/// module are in scope and available.
///
/// Values introduced with `var` are only initial guesses for the solver.
/// They are starting positions or starting sizes, not locked values, and the
/// solver is free to change them in the final solved sketch.
///
/// For that reason, initial guesses should always be literals. Do not use
/// identifiers, constant references, or computed expressions as initial
/// guesses. For example, use `var 0mm` or `var 10mm`, not `var width`,
/// `var baseRadius`, or `var (plateWidth / 2)`.
///
/// If a value must stay fixed, put that value in the constraint itself.
/// Constants and expressions belong in `distance`, `radius`, `diameter`,
/// `horizontalDistance`, `verticalDistance`, and similar constraint
/// functions, because those are what actually constrain the solved result.
@no_std
@settings(defaultLengthUnit = mm, kclVersion = 1.0, experimentalFeatures = allow)
import Point2d, Segment from "std::types"
/// The origin point in a sketch.
export ORIGIN = [0mm, 0mm]: Point2d
/// Create a point in a sketch.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// inside = point(at = [var 1mm, var 1mm])
/// }
///
/// solid = extrude(region(point = profile.inside), length = 2)
/// ```
@(impl = std_rust_constrainable, feature_tree = true)
export fn point(
/// The point's position in the sketch's local 2D coordinate system.
at: Point2d,
): Segment {}
/// Create a straight line segment in a sketch.
///
/// ```kcl,sketchSolve
/// profile = 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 3mm])
/// edge3 = line(start = [var 5mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constrainable, feature_tree = true)
export fn line(
/// The segment's start point in sketch coordinates.
start: Point2d,
/// The segment's end point in sketch coordinates.
end: Point2d,
/// Whether this segment is construction geometry rather than part of the modeled profile.
construction?: bool,
): Segment {}
/// Create a circular arc. The arc segment always sweeps counterclockwise from start to end.
/// To change direction, swap the start and end points.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// base = line(start = [var -5mm, var 0mm], end = [var 5mm, var 0mm])
/// top = arc(start = [var 5mm, var 0mm], end = [var -5mm, var 0mm], center = [var 0mm, var 5mm])
/// coincident([base.end, top.start])
/// coincident([base.start, top.end])
/// }
///
/// solid = extrude(region(point = [0mm, 2mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constrainable, feature_tree = true)
export fn arc(
/// The point where the arc begins.
start: Point2d,
/// The point where the arc ends.
end: Point2d,
/// The center of the circle the arc lies on.
center: Point2d,
/// Whether this segment is construction geometry rather than part of the modeled profile.
construction?: bool,
): Segment {}
/// Create a circle in a sketch. The circle segment always has a starting point
/// and sweeps counterclockwise from it.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// circle1 = circle(start = [var 2mm, var 0mm], center = [var 0mm, var 0mm], construction = true)
/// edge1 = line(start = [var -3mm, var -2mm], end = [var 3mm, var -2mm])
/// edge2 = line(start = [var 3mm, var -2mm], end = [var 3mm, var 2mm])
/// edge3 = line(start = [var 3mm, var 2mm], end = [var -3mm, var 2mm])
/// edge4 = line(start = [var -3mm, var 2mm], end = [var -3mm, var -2mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// }
///
/// solid = extrude(region(point = [0mm, 0mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constrainable, feature_tree = true)
export fn circle(
/// A point on the circle that sets where the circle starts.
start: Point2d,
/// The center of the circle.
center: Point2d,
/// Whether this segment is construction geometry rather than part of the modeled profile.
construction?: bool,
): Segment {}
/// Constrain points, or a point and a segment to be coincident.
///
/// Supports two points, or one point and one segment (line/arc).
/// A single `Point2d` (e.g. `[1mm, 2.5mm]`) can be used to pin a point to a fixed position.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn coincident(
/// Two points, or one point and one line/arc segment, that should occupy the same location.
@points: [Segment | Point2d; 2],
) {}
/// Constrain the distance between two points.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// distance([edge1.start, edge2.end]) == 5mm
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn distance(
/// Two sketch points, or one sketch point and `ORIGIN`, whose separation should match the value set with `==`.
@points: [Segment | Point2d; 2],
) {}
/// Constrain the radius of an arc segment.
/// Accepts a single arc segment and constrains the distance from its center to its start point.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// base = line(start = [var -4mm, var 0mm], end = [var 4mm, var 0mm])
/// arch = arc(start = [var 4mm, var 0mm], end = [var -4mm, var 0mm], center = [var 0mm, var 0mm])
/// coincident([base.end, arch.start])
/// coincident([base.start, arch.end])
/// radius(arch) == 4mm
/// }
///
/// solid = extrude(region(point = [0mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn radius(
/// The arc segment whose radius should match the value set with `==`.
@points: Segment,
) {}
/// Constrain the diameter of an arc or circle segment.
/// Accepts a single arc or circle segment and constrains the distance from its center to its start point.
/// Note: Diameter uses the same solver constraint as radius (distance between two points),
/// but is stored as a separate constraint type for proper UI display.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// guide = circle(start = [var 2mm, var 0mm], center = [var 0mm, var 0mm], construction = true)
/// diameter(guide) == 4mm
/// edge1 = line(start = [var -3mm, var -2mm], end = [var 3mm, var -2mm])
/// edge2 = line(start = [var 3mm, var -2mm], end = [var 3mm, var 2mm])
/// edge3 = line(start = [var 3mm, var 2mm], end = [var -3mm, var 2mm])
/// edge4 = line(start = [var -3mm, var 2mm], end = [var -3mm, var -2mm])
/// coincident([edge1.end, edge2.start])
/// coincident([edge2.end, edge3.start])
/// coincident([edge3.end, edge4.start])
/// coincident([edge4.end, edge1.start])
/// }
///
/// solid = extrude(region(point = [0mm, 0mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn diameter(
/// The arc or circle segment whose diameter should match the value set with `==`.
@points: Segment,
) {}
/// Constrain the horizontal distance between two points.
///
/// ```kcl,sketchSolve
/// profile = 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])
/// horizontalDistance([edge4.start, edge2.start]) == 6mm
/// }
///
/// solid = extrude(region(point = [3mm, 2mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn horizontalDistance(
/// Two sketch points, or one sketch point and `ORIGIN`, whose X-axis separation should match the value set with `==`.
@points: [Segment | Point2d; 2],
) {}
/// Constrain the vertical distance between two points.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 5mm])
/// edge3 = line(start = [var 4mm, 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])
/// verticalDistance([edge1.start, edge4.start]) == 5mm
/// }
///
/// solid = extrude(region(point = [2mm, 2mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn verticalDistance(
/// Two sketch points, or one sketch point and `ORIGIN`, whose Y-axis separation should match the value set with `==`.
@points: [Segment | Point2d; 2],
) {}
/// Constrain lines to have equal length.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// base = line(start = [var -3mm, var 0mm], end = [var 3mm, var 0mm])
/// side1 = line(start = [var 3mm, var 0mm], end = [var 0mm, var 4mm])
/// side2 = line(start = [var 0mm, var 4mm], end = [var -3mm, var 0mm])
/// coincident([base.end, side1.start])
/// coincident([side1.end, side2.start])
/// coincident([side2.end, base.start])
/// horizontal(base)
/// equalLength([side1, side2])
/// }
///
/// solid = extrude(region(point = [0mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn equalLength(
/// Two or more line segments that should all share the same length.
@lines: [Segment; 2+],
) {}
/// Constrain circular segments to have equal radius.
///
/// ```kcl,sketchSolve
/// sketch1 = sketch(on = XY) {
/// circle1 = circle(start = [var -2mm, var 0mm], center = [var -6mm, var 0mm])
/// circle2 = circle(start = [var 10mm, var 0mm], center = [var 6mm, var 0mm])
/// equalRadius([circle1, circle2])
/// tangent([circle1, circle2])
/// }
///
/// solid1 = extrude(region(point = sketch1.circle1.center, sketch = sketch1), length = 2)
/// solid2 = extrude(region(point = sketch1.circle2.center, sketch = sketch1), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn equalRadius(
/// Two or more arc or circle segments that should share the same radius.
@input: [Segment; 2+],
) {}
/// Constrain lines to be parallel.
///
/// Currently limited to two lines.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// base = line(start = [var 0mm, var 0mm], end = [var 5mm, var 0mm])
/// right = line(start = [var 5mm, var 0mm], end = [var 4mm, var 3mm])
/// top = line(start = [var 4mm, var 3mm], end = [var 1mm, var 3mm])
/// left = line(start = [var 1mm, var 3mm], end = [var 0mm, var 0mm])
/// coincident([base.end, right.start])
/// coincident([right.end, top.start])
/// coincident([top.end, left.start])
/// coincident([left.end, base.start])
/// parallel([base, top])
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn parallel(
/// The line segments that should remain parallel. Currently limited to two lines.
@input: [Segment; 2+],
) {}
/// Constrain lines to be perpendicular.
///
/// Currently limited to two lines.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// perpendicular([edge1, edge2])
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn perpendicular(
/// The line segments that should remain perpendicular. Currently limited to two lines.
@input: [Segment; 2+],
) {}
/// Constrain lines to meet at a given angle.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm])
/// line3 = line(start = [var 2mm, var 3.464mm], end = [var 4mm, var 0mm])
/// coincident([line1.start, line2.start])
/// coincident([line2.end, line3.start])
/// coincident([line3.end, line1.end])
/// angle([line1, line2]) == 60deg
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn angle(
/// The two line segments whose relative angle should match the value set with `==`.
@input: [Segment; 2],
) {}
/// Constrain two segments to be tangent.
///
/// Supported input type pairs (unordered):
/// - `Line` / `Circle`
/// - `Line` / `CircularArc`
/// - `Circle` / `Circle`
/// - `Circle` / `CircularArc`
/// - `CircularArc` / `CircularArc`
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// guideArc = arc(start = [var 0mm, var 2mm], end = [var 2mm, var 0mm], center = [var 2mm, var 2mm])
/// tangentLine = line(start = [var 0mm, var 2mm], end = [var 0mm, var 4mm])
/// tangent([tangentLine, guideArc])
/// coincident([tangentLine.start, guideArc.start])
/// line1 = line(start = [var 0mm, var 4mm], end = [var 2mm, var 0mm])
/// coincident([guideArc.end, line1.end])
/// coincident([tangentLine.end, line1.start])
/// }
///
/// solid = extrude(region(point = [1mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn tangent(
/// Two supported line/arc/circle segments that should touch without crossing.
@input: [Segment; 2],
) {}
/// Constrain a point to be fixed to a position.
///
/// `fixed()` is an alias for `coincident()`. By convention, `fixed()` is used when one of the points is a known location, not solved with constraints and not another point in the sketch.
///
/// See [coincident()](/docs/kcl-std/functions/std-sketch2-coincident) for more info.
@(doc_category = "functions")
export fixed = coincident
/// Constrain a line to be horizontal.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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)
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn horizontal(
/// The line segment that should remain horizontal.
@input: Segment,
) {}
/// Constrain a line to be vertical.
///
/// ```kcl,sketchSolve
/// profile = sketch(on = XY) {
/// edge1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm])
/// edge2 = line(start = [var 4mm, var 0mm], end = [var 4mm, var 3mm])
/// edge3 = line(start = [var 4mm, var 3mm], end = [var 0mm, var 3mm])
/// edge4 = line(start = [var 0mm, var 3mm], 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])
/// vertical(edge2)
/// }
///
/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2)
/// ```
@(impl = std_rust_constraint, feature_tree = true)
export fn vertical(
/// The line segment that should remain vertical.
@input: Segment,
) {}