Circle function and UI tool (#3860)

* circle

* fix another example

* fix bad comment

* toPoint fix

* cargo fmt

* resolve most of the tests

* fix last test

* missed circle in bracket

* remove console error

* fmt

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* trigger ci

* remove three dot menu for circle

* make sure circle can be extruded

* fix up after merge

* add extrude test for circle

* clean up

* typo

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"

This reverts commit 03f8eeb542.

* update docs again

* cmd bar test serialisation improvements

* tiny clean up

* fix after: Replace kittycad crate with kittycad-modeling-cmds

* fmt

* rename fix

* Update src/lib/toolbar.ts

Co-authored-by: Frank Noirot <frank@zoo.dev>

* add another error to list

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* image updates

* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)"

This reverts commit 505bb20bea.

* update markdown

* skip un reproducable windows test failure

* rust review

* leave issue todo comment

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
This commit is contained in:
Kurt Hutten
2024-09-23 22:42:51 +10:00
committed by GitHub
parent 7848d63177
commit f1b0e40388
122 changed files with 22670 additions and 512 deletions

View File

@ -1,3 +1,3 @@
const cylinder = startSketchOn('XY')
|> circle([0,0], 22, %)
|> circle({ center: [0, 0], radius: 22 }, %)
|> extrude(14, %)

View File

@ -61,8 +61,8 @@ const case = startSketchOn('XY')
fn m25Screw = (x, y, height) => {
const screw = startSketchOn("XY")
|> startProfileAt([0, 0], %)
|> circle([x, y], 2.5, %)
|> hole(circle([x, y], 1.25, %), %)
|> circle({ center: [x, y], radius: 2.5 }, %)
|> hole(circle({ center: [x, y], radius: 1.25 }, %), %)
|> extrude(height, %)
return screw
}

View File

@ -1,6 +1,7 @@
// A mounting bracket for the Focusrite Scarlett Solo audio interface
// This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material
// define constants in mm
const radius = 6.0
const width = 144.0
@ -79,10 +80,13 @@ const tabsR = startSketchOn(tabPlane)
|> line([0, -tabLength / 3 * 2], %, $edge12)
|> line([-tabWidth, -tabLength / 3], %, $edge13)
|> close(%, $edge14)
|> hole(circle([
width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> hole(circle({
center: [
width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2))
],
radius: holeDiam / 2
}, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,
@ -104,10 +108,13 @@ const tabsL = startSketchOn(tabPlane)
|> line([0, -tabLength / 3 * 2], %, $edge22)
|> line([tabWidth, -tabLength / 3], %, $edge23)
|> close(%, $edge24)
|> hole(circle([
-width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> hole(circle({
center: [
-width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2))
],
radius: holeDiam / 2
}, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,

View File

@ -80,10 +80,13 @@ const tabsR = startSketchOn(tabPlane)
|> line([0, -tabLength / 3 * 2], %, $edge12)
|> line([-tabWidth, -tabLength / 3], %, $edge13)
|> close(%, $edge14)
|> hole(circle([
width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> hole(circle({
center: [
width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2))
],
radius: holeDiam / 2
}, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,
@ -105,10 +108,13 @@ const tabsL = startSketchOn(tabPlane)
|> line([0, -tabLength / 3 * 2], %, $edge22)
|> line([tabWidth, -tabLength / 3], %, $edge23)
|> close(%, $edge24)
|> hole(circle([
-width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> hole(circle({
center: [
-width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2))
],
radius: holeDiam / 2
}, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn('XY')
|> circle([5, 5], 10, %)
|> circle({ center: [5, 5], radius: 10 }, %)
|> extrude(10, %)
|> helix({revolutions: 16, angle_start: 0, ccw: true}, %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn('XY')
|> circle([5, 5], 10, %)
|> circle({ center: [5, 5], radius: 10 }, %)
|> extrude(10, %)
|> helix({revolutions: 16, angle_start: 0}, %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn('XY')
|> circle([5, 5], 10, %)
|> circle({ center: [5, 5], radius: 10 }, %)
|> extrude(-10, %)
|> helix({revolutions: 16, angle_start: 0}, %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn('XY')
|> circle([5, 5], 10, %)
|> circle({ center: [5, 5], radius: 10 }, %)
|> extrude(10, %)
|> helix({revolutions: 16, angle_start: 0, length: 3}, %)

View File

@ -39,10 +39,10 @@ const shellExtrude = startSketchOn(s, "start")
|> extrude(-(height - t), %)
const peg = startSketchOn(s, "end")
|> circle([
|> circle({ center: [
-(total_width / 2 - wSegments),
-(total_length / 2 - lSegments)
], bumpDiam / 2, %)
], radius: bumpDiam / 2 }, %)
|> patternLinear2d({
axis: [1, 0],
repetitions: 5,

View File

@ -14,7 +14,7 @@ fn transform = (replicaId) => {
// Each layer is just a pretty thin cylinder with a fillet.
fn layer = () => {
return startSketchOn("XY") // or some other plane idk
|> circle([0, 0], 1, %, $tag1)
|> circle({ center: [0, 0], radius: 1 }, %, $tag1)
|> extrude(h, %)
// |> fillet({
// radius: h / 2.01,

View File

@ -30,22 +30,22 @@ fn caster = (originStart) => {
|> xLine(-3.543, %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
|> hole(circle([
|> hole(circle({ center: [
(3.543 - 2.756) / 2,
(3.543 - 2.756) / 2
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4}, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2 + 2.756,
(3.543 - 2.756) / 2
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4 }, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2,
(3.543 - 2.756) / 2 + 2.756
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4 }, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2 + 2.756,
(3.543 - 2.756) / 2 + 2.756
], 8.8 / 2 / 25.4, %), %)
], radius: 8.8 / 2 / 25.4 }, %), %)
|> extrude(-.25, %)
const sketch002c = startSketchOn(sketch001c, 'START')
@ -71,7 +71,7 @@ fn caster = (originStart) => {
}
}
const sketch003c = startSketchOn(plane002c)
|> circle([0, 1.2], 2.48 / 2, %)
|> circle({ center: [0, 1.2], radius 2.48 / 2 }, %)
const examplec = extrude(-1 - (3 / 16), sketch003c)
return examplec
}

View File

@ -28,22 +28,22 @@ fn caster = (originStart) => {
|> xLine(-3.543, %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
|> hole(circle([
|> hole(circle({ center: [
(3.543 - 2.756) / 2,
(3.543 - 2.756) / 2
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4 }, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2 + 2.756,
(3.543 - 2.756) / 2
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4 }, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2,
(3.543 - 2.756) / 2 + 2.756
], 8.8 / 2 / 25.4, %), %)
|> hole(circle([
], radius: 8.8 / 2 / 25.4 }, %), %)
|> hole(circle({ center: [
(3.543 - 2.756) / 2 + 2.756,
(3.543 - 2.756) / 2 + 2.756
], 8.8 / 2 / 25.4, %), %)
], radius: 8.8 / 2 / 25.4 }, %), %)
|> extrude(-.25, %)
const sketch002c = startSketchOn(sketch001c, 'START')
@ -69,7 +69,7 @@ fn caster = (originStart) => {
}
}
const sketch003c = startSketchOn(plane002c)
|> circle([0, 1.2], 2.48 / 2, %)
|> circle({ center: [0, 1.2], radisu: 2.48 / 2 }, %)
const examplec = extrude(-1 - (3 / 16), sketch003c)
return examplec
}

View File

@ -12,5 +12,5 @@ const part001 = cube([0,0], 20)
|> extrude(20, %)
const part002 = startSketchOn(part001, "end")
|> circle([0, 0], 5, %, $myCircle)
|> circle({ center: [0, 0], radius: 5 }, %, $myCircle)
|> extrude(5, %)

View File

@ -62,10 +62,10 @@ fn tr = (i) => {
// Create the pegs on the top of the base
const totalBumps = (wbumps * lbumps)-1
const peg = startSketchOn(s, 'end')
|> circle([
|> circle({ center: [
-(pitch*(wbumps-1)/2),
-(pitch*(lbumps-1)/2)
], bumpDiam / 2, %)
], radius: bumpDiam / 2 }, %)
|> patternLinear2d({
axis: [1, 0],
repetitions: wbumps-1,

View File

@ -0,0 +1,17 @@
const sketch002 = startSketchOn('XZ')
|> startProfileAt([-108.83, -57.48], %)
|> angledLine([0, 105.13], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
77.9
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> close(%)
const sketch001 = startSketchOn('XZ')
|> circle({
center: [318.33, 168.1],
radius: 182.8
}, %)

View File

@ -301,8 +301,8 @@ async fn kcl_test_holes() {
|> line([10, 0], %)
|> line([0, -10], %)
|> close(%)
|> hole(circle([2, 2], .5, %), %)
|> hole(circle([2, 8], .5, %), %)
|> hole(circle({ center: [2, 2], radius: .5 }, %), %)
|> hole(circle({ center: [2, 8], radius: .5 }, %), %)
|> extrude(2, %)
"#;
@ -354,10 +354,10 @@ 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, %), %)
|> hole(circle({ center: [-holeIndex, holeIndex], radius: holeRadius }, %), %)
|> hole(circle({ center: [holeIndex, holeIndex], radius: holeRadius }, %), %)
|> hole(circle({ center: [-holeIndex, -holeIndex], radius: holeRadius }, %), %)
|> hole(circle({ center: [holeIndex, -holeIndex], radius: holeRadius }, %), %)
|> extrude(2, %)
"#;
@ -367,7 +367,7 @@ const part = roundedRectangle([0, 0], 20, 20, 4)
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_top_level_expression() {
let code = r#"startSketchOn('XY') |> circle([0,0], 22, %) |> extrude(14, %)"#;
let code = r#"startSketchOn('XY') |> circle({ center: [0,0], radius: 22 }, %) |> extrude(14, %)"#;
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
assert_out("top_level_expression", &result);
@ -378,7 +378,7 @@ async fn kcl_test_patterns_linear_basic_with_math() {
let code = r#"const num = 12
const distance = 5
const part = startSketchOn('XY')
|> circle([0,0], 2, %)
|> circle({ center: [0,0], radius: 2 }, %)
|> patternLinear2d({axis: [0,1], repetitions: num -1, distance: distance - 1}, %)
|> extrude(1, %)
"#;
@ -390,7 +390,7 @@ const part = startSketchOn('XY')
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_patterns_linear_basic() {
let code = r#"const part = startSketchOn('XY')
|> circle([0,0], 2, %)
|> circle({ center: [0,0], radius: 2 }, %)
|> patternLinear2d({axis: [0,1], repetitions: 12, distance: 4}, %)
|> extrude(1, %)
"#;
@ -418,7 +418,7 @@ async fn kcl_test_patterns_linear_basic_3d() {
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_patterns_linear_basic_negative_distance() {
let code = r#"const part = startSketchOn('XY')
|> circle([0,0], 2, %)
|> circle({ center: [0,0], radius: 2 }, %)
|> patternLinear2d({axis: [0,1], repetitions: 12, distance: -2}, %)
|> extrude(1, %)
"#;
@ -430,7 +430,7 @@ async fn kcl_test_patterns_linear_basic_negative_distance() {
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_patterns_linear_basic_negative_axis() {
let code = r#"const part = startSketchOn('XY')
|> circle([0,0], 2, %)
|> circle({ center: [0,0], radius: 2 }, %)
|> patternLinear2d({axis: [0,-1], repetitions: 12, distance: 2}, %)
|> extrude(1, %)
"#;
@ -442,7 +442,7 @@ async fn kcl_test_patterns_linear_basic_negative_axis() {
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_patterns_linear_basic_holes() {
let code = r#"const circles = startSketchOn('XY')
|> circle([5, 5], 1, %)
|> circle({ center: [5, 5], radius: 1 }, %)
|> patternLinear2d({axis: [1,1], repetitions: 12, distance: 3}, %)
const rectangle = startSketchOn('XY')
@ -463,7 +463,7 @@ const rectangle = startSketchOn('XY')
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_patterns_circular_basic_2d() {
let code = r#"const part = startSketchOn('XY')
|> circle([0,0], 2, %)
|> circle({ center: [0,0], radius: 2 }, %)
|> patternCircular2d({center: [20, 20], repetitions: 12, arcDegrees: 210, rotateDuplicates: true}, %)
|> extrude(1, %)
"#;
@ -787,8 +787,8 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
|> line([10, 0], %)
|> line([0, -10], %)
|> close(%)
|> hole(circle([2, 2], .5), %)
|> hole(circle([2, 8], .5, %), %)
|> hole(circle({ center: [2, 2], radius: .5 }), %)
|> hole(circle({ center: [2, 8], radius: .5 }, %), %)
|> extrude(2, %)
"#;
@ -796,7 +796,7 @@ async fn kcl_test_stdlib_kcl_error_right_code_path() {
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([157, 175])], message: "Expected an argument at index 2" }"#,
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([157, 195])], message: "Expected an argument at index 1" }"#,
);
}
@ -816,7 +816,7 @@ const part001 = cube([0,0], 20)
|> extrude(20, %)
const part002 = startSketchOn(part001, "end")
|> circle([0, 0], 5, %)
|> circle({ center: [0, 0], radius: 5 }, %)
|> extrude(5, %)
"#;
@ -866,7 +866,7 @@ const part = rectShape([0, 0], 20, 20)
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([887, 936])], message: "Argument at index 0 was supposed to be type [f64; 2] but found string (text)" }"#,
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([887, 936])], message: "Argument at index 0 was supposed to be type kcl_lib::std::shapes::CircleData but found string (text)" }"#,
);
}
@ -1085,7 +1085,7 @@ async fn kcl_test_revolve_on_face_circle_edge() {
|> extrude(20, %)
const sketch001 = startSketchOn(box, "END")
|> circle([10,10], 4, %)
|> circle({ center: [10,10], radius: 4 }, %)
|> revolve({
angle: 90,
axis: getOppositeEdge(revolveAxis)
@ -1107,7 +1107,7 @@ async fn kcl_test_revolve_on_face_circle() {
|> extrude(20, %)
const sketch001 = startSketchOn(box, "END")
|> circle([10,10], 4, %)
|> circle({ center: [10,10], radius: 4 }, %)
|> revolve({
angle: -90,
axis: 'y'
@ -1147,7 +1147,7 @@ const sketch001 = startSketchOn(box, "end")
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_basic_revolve_circle() {
let code = r#"const sketch001 = startSketchOn('XY')
|> circle([15, 0], 5, %)
|> circle({ center: [15, 0], radius: 5 }, %)
|> revolve({
angle: 360,
axis: 'y'
@ -1271,10 +1271,10 @@ async fn kcl_test_member_expression_in_params() {
z_axis: { x: 0, y: 1, z: 0 }
}
})
|> circle([0, 0], capDia / 2, %)
|> circle({ center: [0, 0], radius: capDia / 2 }, %)
|> extrude(capHeadLength, %)
const screw = startSketchOn(screwHead, "start")
|> circle([0, 0], dia / 2, %)
|> circle({ center: [0, 0], radius: dia / 2 }, %)
|> extrude(length, %)
return screw
}
@ -1343,7 +1343,7 @@ async fn kcl_test_error_empty_start_sketch_on_string() {
|> extrude(100, %)
const secondSketch = startSketchOn(part001, '')
|> circle([-20, 50], 40, %)
|> circle({ center: [-20, 50], radius: 40 }, %)
|> extrude(20, %)
"#;
@ -1373,7 +1373,7 @@ fn squareHole = (l, w) => {
}
const extrusion = startSketchOn('XY')
|> circle([0, 0], dia/2, %)
|> circle({ center: [0, 0], radius: dia/2 }, %)
|> hole(squareHole(length, width, height), %)
|> extrude(height, %)
"#;
@ -1382,7 +1382,7 @@ const extrusion = startSketchOn('XY')
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([92, 364]), SourceRange([444, 477])], message: "Expected 2 arguments, got 3" }"#
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([92, 364]), SourceRange([464, 497])], message: "Expected 2 arguments, got 3" }"#
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB