holes (#848)
* start of holes Signed-off-by: Jess Frazelle <github@jessfraz.com> * update docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates; Signed-off-by: Jess Frazelle <github@jessfraz.com> * close it Signed-off-by: Jess Frazelle <github@jessfraz.com> * Fix holes in jess's branch (#857) tweak * holes Signed-off-by: Jess Frazelle <github@jessfraz.com> * bump version Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix image Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: mlfarrell <michael@kittycad.io>
This commit is contained in:
1327
docs/kcl/std.json
1327
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
214
docs/kcl/std.md
214
docs/kcl/std.md
@ -26,6 +26,7 @@
|
|||||||
* [`extrude`](#extrude)
|
* [`extrude`](#extrude)
|
||||||
* [`floor`](#floor)
|
* [`floor`](#floor)
|
||||||
* [`getExtrudeWallTransform`](#getExtrudeWallTransform)
|
* [`getExtrudeWallTransform`](#getExtrudeWallTransform)
|
||||||
|
* [`hole`](#hole)
|
||||||
* [`lastSegX`](#lastSegX)
|
* [`lastSegX`](#lastSegX)
|
||||||
* [`lastSegY`](#lastSegY)
|
* [`lastSegY`](#lastSegY)
|
||||||
* [`legAngX`](#legAngX)
|
* [`legAngX`](#legAngX)
|
||||||
@ -2023,6 +2024,219 @@ getExtrudeWallTransform(surface_name: string, extrude_group: ExtrudeGroup) -> Ex
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### hole
|
||||||
|
|
||||||
|
Use a sketch to cut a hole in another sketch.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
hole(hole_sketch_group: SketchGroup, sketch_group: SketchGroup) -> SketchGroup
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
* `hole_sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
// The id of the sketch group.
|
||||||
|
id: uuid,
|
||||||
|
// The plane id of the sketch group.
|
||||||
|
planeId: uuid,
|
||||||
|
// The position of the sketch group.
|
||||||
|
position: [number, number, number],
|
||||||
|
// The rotation of the sketch group.
|
||||||
|
rotation: [number, number, number, number],
|
||||||
|
// The starting path.
|
||||||
|
start: {
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// The paths in the sketch group.
|
||||||
|
value: [{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
// The y coordinate.
|
||||||
|
y: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
// The id of the sketch group.
|
||||||
|
id: uuid,
|
||||||
|
// The plane id of the sketch group.
|
||||||
|
planeId: uuid,
|
||||||
|
// The position of the sketch group.
|
||||||
|
position: [number, number, number],
|
||||||
|
// The rotation of the sketch group.
|
||||||
|
rotation: [number, number, number, number],
|
||||||
|
// The starting path.
|
||||||
|
start: {
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// The paths in the sketch group.
|
||||||
|
value: [{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
// The y coordinate.
|
||||||
|
y: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
* `SketchGroup` - A sketch group is a collection of paths.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
// The id of the sketch group.
|
||||||
|
id: uuid,
|
||||||
|
// The plane id of the sketch group.
|
||||||
|
planeId: uuid,
|
||||||
|
// The position of the sketch group.
|
||||||
|
position: [number, number, number],
|
||||||
|
// The rotation of the sketch group.
|
||||||
|
rotation: [number, number, number, number],
|
||||||
|
// The starting path.
|
||||||
|
start: {
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// The paths in the sketch group.
|
||||||
|
value: [{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
// The x coordinate.
|
||||||
|
x: number,
|
||||||
|
// The y coordinate.
|
||||||
|
y: number,
|
||||||
|
} |
|
||||||
|
{
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// The name of the path.
|
||||||
|
name: string,
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: string,
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### lastSegX
|
### lastSegX
|
||||||
|
|
||||||
Returns the last segment of x.
|
Returns the last segment of x.
|
||||||
|
2
src/wasm-lib/Cargo.lock
generated
2
src/wasm-lib/Cargo.lock
generated
@ -1390,7 +1390,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.34"
|
version = "0.1.35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language"
|
description = "KittyCAD Language"
|
||||||
version = "0.1.34"
|
version = "0.1.35"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ impl StdLib {
|
|||||||
Box::new(crate::std::sketch::TangentialArc),
|
Box::new(crate::std::sketch::TangentialArc),
|
||||||
Box::new(crate::std::sketch::TangentialArcTo),
|
Box::new(crate::std::sketch::TangentialArcTo),
|
||||||
Box::new(crate::std::sketch::BezierCurve),
|
Box::new(crate::std::sketch::BezierCurve),
|
||||||
|
Box::new(crate::std::sketch::Hole),
|
||||||
Box::new(crate::std::math::Cos),
|
Box::new(crate::std::math::Cos),
|
||||||
Box::new(crate::std::math::Sin),
|
Box::new(crate::std::math::Sin),
|
||||||
Box::new(crate::std::math::Tan),
|
Box::new(crate::std::math::Tan),
|
||||||
@ -230,6 +231,42 @@ impl Args {
|
|||||||
Ok((segment_name, sketch_group))
|
Ok((segment_name, sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sketch_groups(&self) -> Result<(Box<SketchGroup>, Box<SketchGroup>), KclError> {
|
||||||
|
let first_value = self.args.first().ok_or_else(|| {
|
||||||
|
KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
|
||||||
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let sketch_group = if let MemoryItem::SketchGroup(sg) = first_value {
|
||||||
|
sg.clone()
|
||||||
|
} else {
|
||||||
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
|
||||||
|
source_ranges: vec![self.source_range],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
let second_value = self.args.get(1).ok_or_else(|| {
|
||||||
|
KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let second_sketch_group = if let MemoryItem::SketchGroup(sg) = second_value {
|
||||||
|
sg.clone()
|
||||||
|
} else {
|
||||||
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
|
||||||
|
source_ranges: vec![self.source_range],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((sketch_group, second_sketch_group))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_sketch_group(&self) -> Result<Box<SketchGroup>, KclError> {
|
fn get_sketch_group(&self) -> Result<Box<SketchGroup>, KclError> {
|
||||||
let first_value = self.args.first().ok_or_else(|| {
|
let first_value = self.args.first().ok_or_else(|| {
|
||||||
KclError::Type(KclErrorDetails {
|
KclError::Type(KclErrorDetails {
|
||||||
|
@ -1395,6 +1395,50 @@ async fn inner_bezier_curve(
|
|||||||
Ok(new_sketch_group)
|
Ok(new_sketch_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use a sketch to cut a hole in another sketch.
|
||||||
|
pub async fn hole(args: Args) -> Result<MemoryItem, KclError> {
|
||||||
|
let (hole_sketch_group, sketch_group): (Box<SketchGroup>, Box<SketchGroup>) = args.get_sketch_groups()?;
|
||||||
|
|
||||||
|
let new_sketch_group = inner_hole(hole_sketch_group, sketch_group, args).await?;
|
||||||
|
Ok(MemoryItem::SketchGroup(new_sketch_group))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use a sketch to cut a hole in another sketch.
|
||||||
|
#[stdlib {
|
||||||
|
name = "hole",
|
||||||
|
}]
|
||||||
|
async fn inner_hole(
|
||||||
|
hole_sketch_group: Box<SketchGroup>,
|
||||||
|
sketch_group: Box<SketchGroup>,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<Box<SketchGroup>, KclError> {
|
||||||
|
//TODO: batch these (once we have batch)
|
||||||
|
|
||||||
|
args.send_modeling_cmd(
|
||||||
|
uuid::Uuid::new_v4(),
|
||||||
|
ModelingCmd::Solid2DAddHole {
|
||||||
|
object_id: sketch_group.id,
|
||||||
|
hole_id: hole_sketch_group.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
//suggestion (mike)
|
||||||
|
//we also hide the source hole since its essentially "consumed" by this operation
|
||||||
|
args.send_modeling_cmd(
|
||||||
|
uuid::Uuid::new_v4(),
|
||||||
|
ModelingCmd::ObjectVisible {
|
||||||
|
object_id: hole_sketch_group.id,
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO: should we modify the sketch group to include the hole data, probably?
|
||||||
|
|
||||||
|
Ok(sketch_group)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
@ -431,3 +431,76 @@ const part004 = startSketchOn('YZ')
|
|||||||
let result = execute_and_snapshot(code).await.unwrap();
|
let result = execute_and_snapshot(code).await.unwrap();
|
||||||
twenty_twenty::assert_image("tests/executor/outputs/lots_of_planes.png", &result, 0.999);
|
twenty_twenty::assert_image("tests/executor/outputs/lots_of_planes.png", &result, 0.999);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn serial_test_holes() {
|
||||||
|
let code = r#"fn circle = (pos, radius) => {
|
||||||
|
const sg = startSketchOn('XY')
|
||||||
|
|> startProfileAt(pos, %)
|
||||||
|
|> arc({angle_end: 360, angle_start: 0, radius: radius}, %)
|
||||||
|
|> close(%)
|
||||||
|
|
||||||
|
return sg
|
||||||
|
}
|
||||||
|
|
||||||
|
const square = startSketchOn('XY')
|
||||||
|
|> startProfileAt([0, 0], %)
|
||||||
|
|> line([0, 10], %)
|
||||||
|
|> line([10, 0], %)
|
||||||
|
|> line([0, -10], %)
|
||||||
|
|> close(%)
|
||||||
|
|> hole(circle([2, 2], .5), %)
|
||||||
|
|> hole(circle([2, 8], .5), %)
|
||||||
|
|> extrude(2, %)
|
||||||
|
|
||||||
|
show(square)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = execute_and_snapshot(code).await.unwrap();
|
||||||
|
twenty_twenty::assert_image("tests/executor/outputs/holes.png", &result, 0.999);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn serial_test_rounded_with_holes() {
|
||||||
|
let code = r#"fn circle = (pos, radius) => {
|
||||||
|
const sg = startSketchOn('XY')
|
||||||
|
|> startProfileAt([pos[0] + radius, pos[1]], %)
|
||||||
|
|> arc({
|
||||||
|
angle_end: 360,
|
||||||
|
angle_start: 0,
|
||||||
|
radius: radius
|
||||||
|
}, %)
|
||||||
|
|> close(%)
|
||||||
|
return sg
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roundedRectangle = (pos, w, l, cornerRadius) => {
|
||||||
|
const rr = startSketchOn('XY')
|
||||||
|
|> startProfileAt([pos[0] - w/2, 0], %)
|
||||||
|
|> lineTo([pos[0] - w/2, pos[1] - l/2 + cornerRadius], %)
|
||||||
|
|> tangentialArcTo([pos[0] - w/2 + cornerRadius, pos[1] - l/2], %)
|
||||||
|
|> lineTo([pos[0] + w/2 - cornerRadius, pos[1] - l/2], %)
|
||||||
|
|> tangentialArcTo([pos[0] + w/2, pos[1] - l/2 + cornerRadius], %)
|
||||||
|
|> lineTo([pos[0] + w/2, pos[1] + l/2 - cornerRadius], %)
|
||||||
|
|> tangentialArcTo([pos[0] + w/2 - cornerRadius, pos[1] + l/2], %)
|
||||||
|
|> lineTo([pos[0] - w/2 + cornerRadius, pos[1] + l/2], %)
|
||||||
|
|> tangentialArcTo([pos[0] - w/2, pos[1] + l/2 - cornerRadius], %)
|
||||||
|
|> close(%)
|
||||||
|
return rr
|
||||||
|
}
|
||||||
|
|
||||||
|
const holeRadius = 1
|
||||||
|
const holeIndex = 6
|
||||||
|
|
||||||
|
const part = roundedRectangle([0, 0], 20, 20, 4)
|
||||||
|
|> hole(circle([-holeIndex, holeIndex], holeRadius), %)
|
||||||
|
|> hole(circle([holeIndex, holeIndex], holeRadius), %)
|
||||||
|
|> hole(circle([-holeIndex, -holeIndex], holeRadius), %)
|
||||||
|
|> hole(circle([holeIndex, -holeIndex], holeRadius), %)
|
||||||
|
|> extrude(2, %)
|
||||||
|
|
||||||
|
show(part)"#;
|
||||||
|
|
||||||
|
let result = execute_and_snapshot(code).await.unwrap();
|
||||||
|
twenty_twenty::assert_image("tests/executor/outputs/rounded_with_holes.png", &result, 0.999);
|
||||||
|
}
|
||||||
|
BIN
src/wasm-lib/tests/executor/outputs/holes.png
Normal file
BIN
src/wasm-lib/tests/executor/outputs/holes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
BIN
src/wasm-lib/tests/executor/outputs/rounded_with_holes.png
Normal file
BIN
src/wasm-lib/tests/executor/outputs/rounded_with_holes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
Reference in New Issue
Block a user