Move solids functions to KCL (#7214)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
//! Constructive Solid Geometry (CSG) operations.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_derive_docs::stdlib;
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||
use kittycad_modeling_cmds::{
|
||||
self as kcmc,
|
||||
@ -34,85 +33,6 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
/// Union two or more solids into a single solid.
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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])
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "union",
|
||||
feature_tree_operation = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to union."},
|
||||
tolerance = {docs = "The tolerance to use for the union operation."},
|
||||
},
|
||||
tags = ["solid"]
|
||||
}]
|
||||
pub(crate) async fn inner_union(
|
||||
solids: Vec<Solid>,
|
||||
tolerance: Option<TyF64>,
|
||||
@ -178,66 +98,6 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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])
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "intersect",
|
||||
feature_tree_operation = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to intersect."},
|
||||
tolerance = {docs = "The tolerance to use for the intersection operation."},
|
||||
},
|
||||
tags = ["solid"]
|
||||
}]
|
||||
pub(crate) async fn inner_intersect(
|
||||
solids: Vec<Solid>,
|
||||
tolerance: Option<TyF64>,
|
||||
@ -297,67 +157,6 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
/// Subtract removes tool solids from base solids, leaving the remaining material.
|
||||
///
|
||||
/// Performs a boolean 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.
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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])
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "subtract",
|
||||
feature_tree_operation = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to use as the base to subtract from."},
|
||||
tools = {docs = "The solids to subtract."},
|
||||
tolerance = {docs = "The tolerance to use for the subtraction operation."},
|
||||
},
|
||||
tags = ["solid"]
|
||||
}]
|
||||
pub(crate) async fn inner_subtract(
|
||||
solids: Vec<Solid>,
|
||||
tools: Vec<Solid>,
|
||||
|
@ -77,9 +77,7 @@ lazy_static! {
|
||||
Box::new(crate::std::sketch::BezierCurve),
|
||||
Box::new(crate::std::sketch::Subtract2D),
|
||||
Box::new(crate::std::patterns::PatternLinear2D),
|
||||
Box::new(crate::std::patterns::PatternLinear3D),
|
||||
Box::new(crate::std::patterns::PatternCircular2D),
|
||||
Box::new(crate::std::patterns::PatternCircular3D),
|
||||
Box::new(crate::std::edge::GetOppositeEdge),
|
||||
Box::new(crate::std::edge::GetNextAdjacentEdge),
|
||||
Box::new(crate::std::edge::GetPreviousAdjacentEdge),
|
||||
@ -91,9 +89,6 @@ lazy_static! {
|
||||
Box::new(crate::std::transform::Scale),
|
||||
Box::new(crate::std::transform::Translate),
|
||||
Box::new(crate::std::transform::Rotate),
|
||||
Box::new(crate::std::csg::Intersect),
|
||||
Box::new(crate::std::csg::Union),
|
||||
Box::new(crate::std::csg::Subtract),
|
||||
];
|
||||
}
|
||||
|
||||
@ -258,6 +253,30 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
|e, a| Box::pin(crate::std::shell::hollow(e, a)),
|
||||
StdFnProps::default("std::solid::hollow").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "union") => (
|
||||
|e, a| Box::pin(crate::std::csg::union(e, a)),
|
||||
StdFnProps::default("std::solid::union").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "intersect") => (
|
||||
|e, a| Box::pin(crate::std::csg::intersect(e, a)),
|
||||
StdFnProps::default("std::solid::intersect").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "subtract") => (
|
||||
|e, a| Box::pin(crate::std::csg::subtract(e, a)),
|
||||
StdFnProps::default("std::solid::subtract").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "patternTransform") => (
|
||||
|e, a| Box::pin(crate::std::patterns::pattern_transform(e, a)),
|
||||
StdFnProps::default("std::solid::patternTransform").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "patternLinear3d") => (
|
||||
|e, a| Box::pin(crate::std::patterns::pattern_linear_3d(e, a)),
|
||||
StdFnProps::default("std::solid::patternLinear3d").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "patternCircular3d") => (
|
||||
|e, a| Box::pin(crate::std::patterns::pattern_circular_3d(e, a)),
|
||||
StdFnProps::default("std::solid::patternCircular3d").include_in_feature_tree(),
|
||||
),
|
||||
("array", "map") => (
|
||||
|e, a| Box::pin(crate::std::array::map(e, a)),
|
||||
StdFnProps::default("std::array::map"),
|
||||
@ -278,10 +297,6 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
|e, a| Box::pin(crate::std::clone::clone(e, a)),
|
||||
StdFnProps::default("std::clone").include_in_feature_tree(),
|
||||
),
|
||||
("solid", "patternTransform") => (
|
||||
|e, a| Box::pin(crate::std::patterns::pattern_transform(e, a)),
|
||||
StdFnProps::default("std::solid::patternTransform").include_in_feature_tree(),
|
||||
),
|
||||
("sketch", "patternTransform2d") => (
|
||||
|e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
|
||||
StdFnProps::default("std::sketch::patternTransform2d"),
|
||||
|
@ -647,110 +647,6 @@ pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
/// Repeat a 3-dimensional solid along a linear path, with a dynamic amount
|
||||
/// of distance between each repetition, some specified number of times.
|
||||
///
|
||||
/// ```no_run
|
||||
/// /// 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
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// /// 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
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ///
|
||||
/// ```no_run
|
||||
/// // 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,
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // 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
|
||||
/// )
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternLinear3d",
|
||||
feature_tree_operation = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
solids = { docs = "The solid(s) to duplicate" },
|
||||
instances = { docs = "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." },
|
||||
distance = { docs = "Distance between each repetition. Also known as 'spacing'."},
|
||||
axis = { docs = "The axis of the pattern. A 3D vector.", snippet_value_array = ["1", "0", "0"] },
|
||||
use_original = { docs = "If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false." },
|
||||
},
|
||||
tags = ["solid"]
|
||||
}]
|
||||
async fn inner_pattern_linear_3d(
|
||||
solids: Vec<Solid>,
|
||||
instances: u32,
|
||||
@ -1039,57 +935,6 @@ pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Resu
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// ```no_run
|
||||
/// /// 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
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// /// 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
|
||||
/// )
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternCircular3d",
|
||||
feature_tree_operation = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
solids = { docs = "Which solid(s) to pattern" },
|
||||
instances = { docs = "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."},
|
||||
axis = { docs = "The axis around which to make the pattern. This is a 3D vector", snippet_value_array = ["1", "0", "0"]},
|
||||
center = { docs = "The center about which to make the pattern. This is a 3D vector.", snippet_value_array = ["0", "0", "0"]},
|
||||
arc_degrees = { docs = "The arc angle (in degrees) to place the repetitions. Must be greater than 0. Defaults to 360."},
|
||||
rotate_duplicates = { docs = "Whether or not to rotate the duplicates as they are copied. Defaults to true."},
|
||||
use_original = { docs = "If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false."},
|
||||
},
|
||||
tags = ["solid"]
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn inner_pattern_circular_3d(
|
||||
solids: Vec<Solid>,
|
||||
|
Reference in New Issue
Block a user