diff --git a/docs/kcl/getEdge.md b/docs/kcl/getEdge.md new file mode 100644 index 000000000..0c4324d4f --- /dev/null +++ b/docs/kcl/getEdge.md @@ -0,0 +1,178 @@ +--- +title: "getEdge" +excerpt: "Get an edge on a 3D solid." +layout: manual +--- + +Get an edge on a 3D solid. + + + +```js +getEdge(tag: String, extrude_group: ExtrudeGroup) -> Uuid +``` + +### Examples + +```js +const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 10], %) + |> line([10, 0], %) + |> line([0, -10], %, 'revolveAxis') + |> close(%) + |> extrude(10, %) + +const sketch001 = startSketchOn(box, "revolveAxis") + |> startProfileAt([5, 10], %) + |> line([0, -10], %) + |> line([2, 0], %) + |> line([0, 10], %) + |> close(%) + |> revolve({ + axis: getEdge('revolveAxis', box), + angle: 90 + }, %) +``` + +### Arguments + +* `tag`: `String` (REQUIRED) +* `extrude_group`: `ExtrudeGroup` - An extrude group is a collection of extrude surfaces. (REQUIRED) +```js +{ + // The id of the extrusion end cap + endCapId: uuid, + // The height of the extrude group. + height: number, + // The id of the extrude group. + id: uuid, + // The position of the extrude group. + position: [number, number, number], + // The rotation of the extrude group. + rotation: [number, number, number, number], + // The sketch group paths. + sketchGroupValues: [{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "ToPoint", +} | +{ + // arc's direction + ccw: string, + // the arc's center + center: [number, number], + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArcTo", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArc", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "Horizontal", + // 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: "AngledLineTo", + // 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: "Base", +}], + // The id of the extrusion start cap + startCapId: uuid, + // The extrude surfaces. + value: [{ + // The face id for the extrude plane. + faceId: uuid, + // The id of the geometry. + id: uuid, + // The name. + name: string, + // The position. + position: [number, number, number], + // The rotation. + rotation: [number, number, number, number], + // The source range. + sourceRange: [number, number], + type: "extrudePlane", +} | +{ + // The face id for the extrude plane. + faceId: uuid, + // The id of the geometry. + id: uuid, + // The name. + name: string, + // The position. + position: [number, number, number], + // The rotation. + rotation: [number, number, number, number], + // The source range. + sourceRange: [number, number], + type: "extrudeArc", +}], + // The x-axis of the extrude group base plane in the 3D space + xAxis: { + x: number, + y: number, + z: number, +}, + // The y-axis of the extrude group base plane in the 3D space + yAxis: { + x: number, + y: number, + z: number, +}, + // The z-axis of the extrude group base plane in the 3D space + zAxis: { + x: number, + y: number, + z: number, +}, +} +``` + +### Returns + +`Uuid` + + + diff --git a/docs/kcl/index.md b/docs/kcl/index.md index 3694d6f40..3db49bfcc 100644 --- a/docs/kcl/index.md +++ b/docs/kcl/index.md @@ -30,6 +30,7 @@ layout: manual * [`extrude`](kcl/extrude) * [`fillet`](kcl/fillet) * [`floor`](kcl/floor) +* [`getEdge`](kcl/getEdge) * [`getExtrudeWallTransform`](kcl/getExtrudeWallTransform) * [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge) * [`getOppositeEdge`](kcl/getOppositeEdge) @@ -56,6 +57,7 @@ layout: manual * [`patternLinear3d`](kcl/patternLinear3d) * [`pi`](kcl/pi) * [`pow`](kcl/pow) +* [`revolve`](kcl/revolve) * [`segAng`](kcl/segAng) * [`segEndX`](kcl/segEndX) * [`segEndY`](kcl/segEndY) diff --git a/docs/kcl/revolve.md b/docs/kcl/revolve.md new file mode 100644 index 000000000..56a0bc735 --- /dev/null +++ b/docs/kcl/revolve.md @@ -0,0 +1,404 @@ +--- +title: "revolve" +excerpt: "Revolve a sketch around an axis." +layout: manual +--- + +Revolve a sketch around an axis. + + + +```js +revolve(data: RevolveData, sketch_group: SketchGroup) -> ExtrudeGroup +``` + +### Examples + +```js +const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({ axis: 'y' }, %) // default angle is 360 +``` + +```js +const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({ axis: 'y', angle: 180 }, %) +``` + +```js +const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 20], %) + |> line([20, 0], %) + |> line([0, -20], %) + |> close(%) + |> extrude(20, %) + +const sketch001 = startSketchOn(box, "END") + |> circle([10, 10], 4, %) + |> revolve({ angle: -90, axis: 'y' }, %) +``` + +```js +const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 20], %) + |> line([20, 0], %) + |> line([0, -20], %, 'revolveAxis') + |> close(%) + |> extrude(20, %) + +const sketch001 = startSketchOn(box, "END") + |> circle([10, 10], 4, %) + |> revolve({ + angle: 90, + axis: getOppositeEdge('revolveAxis', box) + }, %) +``` + +### Arguments + +* `data`: `RevolveData` - Data for revolution surfaces. (REQUIRED) +```js +{ + // Angle to revolve (in degrees). Default is 360. + angle: number, + // Axis of revolution. + axis: "x" | +"y" | +"z" | +"-X" | +"-Y" | +"-Z" | +{ + custom: { + // The axis. + axis: [number, number, number], + // The origin. + origin: [number, number, number], +}, +} | +uuid | +string, +} +``` +* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED) +```js +{ + // The plane id or face id of the sketch group. + entityId: uuid, + // The id of the sketch group. + id: uuid, + // What the sketch is on (can be a plane or a face). + on: { + // The id of the plane. + id: uuid, + // Origin of the plane. + origin: { + x: number, + y: number, + z: number, +}, + type: "plane", + // Type for a plane. + value: "XY" | "XZ" | "YZ" | "Custom", + // What should the plane’s X axis be? + xAxis: { + x: number, + y: number, + z: number, +}, + // What should the plane’s Y axis be? + yAxis: { + x: number, + y: number, + z: number, +}, + // The z-axis (normal). + zAxis: { + x: number, + y: number, + z: number, +}, +} | +{ + // the face id the sketch is on + faceId: uuid, + // The id of the face. + id: uuid, + // The original sketch group id of the object we are sketching on. + sketchGroupId: uuid, + type: "face", + // The tag of the face. + value: string, + // What should the face’s X axis be? + xAxis: { + x: number, + y: number, + z: number, +}, + // What should the face’s Y axis be? + yAxis: { + x: number, + y: number, + z: number, +}, + // The z-axis (normal). + zAxis: { + x: number, + y: number, + z: number, +}, +}, + // The position of the sketch group. + position: [number, number, number], + // The rotation of the sketch group base plane. + 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: "ToPoint", +} | +{ + // arc's direction + ccw: string, + // the arc's center + center: [number, number], + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArcTo", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArc", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "Horizontal", + // 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: "AngledLineTo", + // 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: "Base", +}], + // The x-axis of the sketch group base plane in the 3D space + xAxis: { + x: number, + y: number, + z: number, +}, + // The y-axis of the sketch group base plane in the 3D space + yAxis: { + x: number, + y: number, + z: number, +}, + // The z-axis of the sketch group base plane in the 3D space + zAxis: { + x: number, + y: number, + z: number, +}, +} +``` + +### Returns + +`ExtrudeGroup` - An extrude group is a collection of extrude surfaces. +```js +{ + // The id of the extrusion end cap + endCapId: uuid, + // The height of the extrude group. + height: number, + // The id of the extrude group. + id: uuid, + // The position of the extrude group. + position: [number, number, number], + // The rotation of the extrude group. + rotation: [number, number, number, number], + // The sketch group paths. + sketchGroupValues: [{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "ToPoint", +} | +{ + // arc's direction + ccw: string, + // the arc's center + center: [number, number], + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArcTo", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "TangentialArc", +} | +{ + // The from point. + from: [number, number], + // The name of the path. + name: string, + // The to point. + to: [number, number], + type: "Horizontal", + // 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: "AngledLineTo", + // 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: "Base", +}], + // The id of the extrusion start cap + startCapId: uuid, + // The extrude surfaces. + value: [{ + // The face id for the extrude plane. + faceId: uuid, + // The id of the geometry. + id: uuid, + // The name. + name: string, + // The position. + position: [number, number, number], + // The rotation. + rotation: [number, number, number, number], + // The source range. + sourceRange: [number, number], + type: "extrudePlane", +} | +{ + // The face id for the extrude plane. + faceId: uuid, + // The id of the geometry. + id: uuid, + // The name. + name: string, + // The position. + position: [number, number, number], + // The rotation. + rotation: [number, number, number, number], + // The source range. + sourceRange: [number, number], + type: "extrudeArc", +}], + // The x-axis of the extrude group base plane in the 3D space + xAxis: { + x: number, + y: number, + z: number, +}, + // The y-axis of the extrude group base plane in the 3D space + yAxis: { + x: number, + y: number, + z: number, +}, + // The z-axis of the extrude group base plane in the 3D space + zAxis: { + x: number, + y: number, + z: number, +}, +} +``` + + + diff --git a/docs/kcl/std.json b/docs/kcl/std.json index 58e5397a7..5f878eec3 100644 --- a/docs/kcl/std.json +++ b/docs/kcl/std.json @@ -24200,12 +24200,12 @@ "description": "A string or a uuid.", "anyOf": [ { - "description": "A uuid.", + "description": "A uuid of an edge.", "type": "string", "format": "uuid" }, { - "description": "A string.", + "description": "A tag name of an edge.", "type": "string" } ] @@ -25765,6 +25765,792 @@ "const myVar = floor(4.5)" ] }, + { + "name": "getEdge", + "summary": "Get an edge on a 3D solid.", + "description": "", + "tags": [], + "args": [ + { + "name": "tag", + "type": "String", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "extrude_group", + "type": "ExtrudeGroup", + "schema": { + "description": "An extrude group is a collection of extrude surfaces.", + "type": "object", + "required": [ + "__meta", + "height", + "id", + "position", + "rotation", + "sketchGroupValues", + "value", + "xAxis", + "yAxis", + "zAxis" + ], + "properties": { + "__meta": { + "description": "Metadata.", + "type": "array", + "items": { + "description": "Metadata.", + "type": "object", + "required": [ + "sourceRange" + ], + "properties": { + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + } + }, + "endCapId": { + "description": "The id of the extrusion end cap", + "type": "string", + "format": "uuid", + "nullable": true + }, + "height": { + "description": "The height of the extrude group.", + "type": "number", + "format": "double" + }, + "id": { + "description": "The id of the extrude group.", + "type": "string", + "format": "uuid" + }, + "position": { + "description": "The position of the extrude group.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation of the extrude group.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sketchGroupValues": { + "description": "The sketch group paths.", + "type": "array", + "items": { + "description": "A path.", + "oneOf": [ + { + "description": "A path that goes to a point.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "ToPoint" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment that goes to a point", + "type": "object", + "required": [ + "__geoMeta", + "ccw", + "center", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "ccw": { + "description": "arc's direction", + "type": "boolean" + }, + "center": { + "description": "the arc's center", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArcTo" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArc" + ] + } + } + }, + { + "description": "A path that is horizontal.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type", + "x" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Horizontal" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double" + } + } + }, + { + "description": "An angled line to.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "AngledLineTo" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double", + "nullable": true + }, + "y": { + "description": "The y coordinate.", + "type": "number", + "format": "double", + "nullable": true + } + } + }, + { + "description": "A base path.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Base" + ] + } + } + } + ] + } + }, + "startCapId": { + "description": "The id of the extrusion start cap", + "type": "string", + "format": "uuid", + "nullable": true + }, + "value": { + "description": "The extrude surfaces.", + "type": "array", + "items": { + "description": "An extrude surface.", + "oneOf": [ + { + "description": "An extrude plane.", + "type": "object", + "required": [ + "faceId", + "id", + "name", + "position", + "rotation", + "sourceRange", + "type" + ], + "properties": { + "faceId": { + "description": "The face id for the extrude plane.", + "type": "string", + "format": "uuid" + }, + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "The name.", + "type": "string" + }, + "position": { + "description": "The position.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "extrudePlane" + ] + } + } + }, + { + "description": "An extruded arc.", + "type": "object", + "required": [ + "faceId", + "id", + "name", + "position", + "rotation", + "sourceRange", + "type" + ], + "properties": { + "faceId": { + "description": "The face id for the extrude plane.", + "type": "string", + "format": "uuid" + }, + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "The name.", + "type": "string" + }, + "position": { + "description": "The position.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "extrudeArc" + ] + } + } + } + ] + } + }, + "xAxis": { + "description": "The x-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "yAxis": { + "description": "The y-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "zAxis": { + "description": "The z-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + } + } + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "Uuid", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + }, + "unpublished": false, + "deprecated": false, + "examples": [ + "const box = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> line([10, 0], %)\n |> line([0, -10], %, 'revolveAxis')\n |> close(%)\n |> extrude(10, %)\n\nconst sketch001 = startSketchOn(box, \"revolveAxis\")\n |> startProfileAt([5, 10], %)\n |> line([0, -10], %)\n |> line([2, 0], %)\n |> line([0, 10], %)\n |> close(%)\n |> revolve({\n axis: getEdge('revolveAxis', box),\n angle: 90\n }, %)" + ] + }, { "name": "getExtrudeWallTransform", "summary": "Returns the extrude wall transform.", @@ -48504,6 +49290,1870 @@ "const myVar = pow(4, 2)" ] }, + { + "name": "revolve", + "summary": "Revolve a sketch around an axis.", + "description": "", + "tags": [], + "args": [ + { + "name": "data", + "type": "RevolveData", + "schema": { + "description": "Data for revolution surfaces.", + "type": "object", + "required": [ + "axis" + ], + "properties": { + "angle": { + "description": "Angle to revolve (in degrees). Default is 360.", + "default": null, + "type": "number", + "format": "double", + "nullable": true + }, + "axis": { + "description": "Axis of revolution.", + "anyOf": [ + { + "description": "Axis of revolution.", + "oneOf": [ + { + "description": "X-axis.", + "type": "string", + "enum": [ + "x" + ] + }, + { + "description": "Y-axis.", + "type": "string", + "enum": [ + "y" + ] + }, + { + "description": "Z-axis.", + "type": "string", + "enum": [ + "z" + ] + }, + { + "description": "Flip the X-axis.", + "type": "string", + "enum": [ + "-X" + ] + }, + { + "description": "Flip the Y-axis.", + "type": "string", + "enum": [ + "-Y" + ] + }, + { + "description": "Flip the Z-axis.", + "type": "string", + "enum": [ + "-Z" + ] + }, + { + "type": "object", + "required": [ + "custom" + ], + "properties": { + "custom": { + "type": "object", + "required": [ + "axis", + "origin" + ], + "properties": { + "axis": { + "description": "The axis.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "origin": { + "description": "The origin.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + } + } + } + }, + "additionalProperties": false + } + ] + }, + { + "description": "Tagged edge.", + "anyOf": [ + { + "description": "A uuid of an edge.", + "type": "string", + "format": "uuid" + }, + { + "description": "A tag name of an edge.", + "type": "string" + } + ] + } + ] + } + } + }, + "required": true + }, + { + "name": "sketch_group", + "type": "SketchGroup", + "schema": { + "description": "A sketch group is a collection of paths.", + "type": "object", + "required": [ + "__meta", + "id", + "on", + "position", + "rotation", + "start", + "value", + "xAxis", + "yAxis", + "zAxis" + ], + "properties": { + "__meta": { + "description": "Metadata.", + "type": "array", + "items": { + "description": "Metadata.", + "type": "object", + "required": [ + "sourceRange" + ], + "properties": { + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + } + }, + "entityId": { + "description": "The plane id or face id of the sketch group.", + "type": "string", + "format": "uuid", + "nullable": true + }, + "id": { + "description": "The id of the sketch group.", + "type": "string", + "format": "uuid" + }, + "on": { + "description": "What the sketch is on (can be a plane or a face).", + "oneOf": [ + { + "description": "A plane.", + "type": "object", + "required": [ + "__meta", + "id", + "origin", + "type", + "value", + "xAxis", + "yAxis", + "zAxis" + ], + "properties": { + "__meta": { + "type": "array", + "items": { + "description": "Metadata.", + "type": "object", + "required": [ + "sourceRange" + ], + "properties": { + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + } + }, + "id": { + "description": "The id of the plane.", + "type": "string", + "format": "uuid" + }, + "origin": { + "description": "Origin of the plane.", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "type": { + "type": "string", + "enum": [ + "plane" + ] + }, + "value": { + "description": "Type for a plane.", + "oneOf": [ + { + "type": "string", + "enum": [ + "XY", + "XZ", + "YZ" + ] + }, + { + "description": "A custom plane.", + "type": "string", + "enum": [ + "Custom" + ] + } + ] + }, + "xAxis": { + "description": "What should the plane’s X axis be?", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "yAxis": { + "description": "What should the plane’s Y axis be?", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "zAxis": { + "description": "The z-axis (normal).", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + } + } + }, + { + "description": "A face.", + "type": "object", + "required": [ + "__meta", + "faceId", + "id", + "sketchGroupId", + "type", + "value", + "xAxis", + "yAxis", + "zAxis" + ], + "properties": { + "__meta": { + "type": "array", + "items": { + "description": "Metadata.", + "type": "object", + "required": [ + "sourceRange" + ], + "properties": { + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + } + }, + "faceId": { + "description": "the face id the sketch is on", + "type": "string", + "format": "uuid" + }, + "id": { + "description": "The id of the face.", + "type": "string", + "format": "uuid" + }, + "sketchGroupId": { + "description": "The original sketch group id of the object we are sketching on.", + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string", + "enum": [ + "face" + ] + }, + "value": { + "description": "The tag of the face.", + "type": "string" + }, + "xAxis": { + "description": "What should the face’s X axis be?", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "yAxis": { + "description": "What should the face’s Y axis be?", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "zAxis": { + "description": "The z-axis (normal).", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + } + } + } + ] + }, + "position": { + "description": "The position of the sketch group.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation of the sketch group base plane.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "start": { + "description": "The starting path.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "value": { + "description": "The paths in the sketch group.", + "type": "array", + "items": { + "description": "A path.", + "oneOf": [ + { + "description": "A path that goes to a point.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "ToPoint" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment that goes to a point", + "type": "object", + "required": [ + "__geoMeta", + "ccw", + "center", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "ccw": { + "description": "arc's direction", + "type": "boolean" + }, + "center": { + "description": "the arc's center", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArcTo" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArc" + ] + } + } + }, + { + "description": "A path that is horizontal.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type", + "x" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Horizontal" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double" + } + } + }, + { + "description": "An angled line to.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "AngledLineTo" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double", + "nullable": true + }, + "y": { + "description": "The y coordinate.", + "type": "number", + "format": "double", + "nullable": true + } + } + }, + { + "description": "A base path.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Base" + ] + } + } + } + ] + } + }, + "xAxis": { + "description": "The x-axis of the sketch group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "yAxis": { + "description": "The y-axis of the sketch group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "zAxis": { + "description": "The z-axis of the sketch group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + } + } + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "ExtrudeGroup", + "schema": { + "description": "An extrude group is a collection of extrude surfaces.", + "type": "object", + "required": [ + "__meta", + "height", + "id", + "position", + "rotation", + "sketchGroupValues", + "value", + "xAxis", + "yAxis", + "zAxis" + ], + "properties": { + "__meta": { + "description": "Metadata.", + "type": "array", + "items": { + "description": "Metadata.", + "type": "object", + "required": [ + "sourceRange" + ], + "properties": { + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + } + }, + "endCapId": { + "description": "The id of the extrusion end cap", + "type": "string", + "format": "uuid", + "nullable": true + }, + "height": { + "description": "The height of the extrude group.", + "type": "number", + "format": "double" + }, + "id": { + "description": "The id of the extrude group.", + "type": "string", + "format": "uuid" + }, + "position": { + "description": "The position of the extrude group.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation of the extrude group.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sketchGroupValues": { + "description": "The sketch group paths.", + "type": "array", + "items": { + "description": "A path.", + "oneOf": [ + { + "description": "A path that goes to a point.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "ToPoint" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment that goes to a point", + "type": "object", + "required": [ + "__geoMeta", + "ccw", + "center", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "ccw": { + "description": "arc's direction", + "type": "boolean" + }, + "center": { + "description": "the arc's center", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArcTo" + ] + } + } + }, + { + "description": "A arc that is tangential to the last path segment", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "TangentialArc" + ] + } + } + }, + { + "description": "A path that is horizontal.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type", + "x" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Horizontal" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double" + } + } + }, + { + "description": "An angled line to.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "AngledLineTo" + ] + }, + "x": { + "description": "The x coordinate.", + "type": "number", + "format": "double", + "nullable": true + }, + "y": { + "description": "The y coordinate.", + "type": "number", + "format": "double", + "nullable": true + } + } + }, + { + "description": "A base path.", + "type": "object", + "required": [ + "__geoMeta", + "from", + "name", + "to", + "type" + ], + "properties": { + "__geoMeta": { + "description": "Metadata.", + "type": "object", + "required": [ + "id", + "sourceRange" + ], + "properties": { + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + } + } + }, + "from": { + "description": "The from point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "name": { + "description": "The name of the path.", + "type": "string" + }, + "to": { + "description": "The to point.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "Base" + ] + } + } + } + ] + } + }, + "startCapId": { + "description": "The id of the extrusion start cap", + "type": "string", + "format": "uuid", + "nullable": true + }, + "value": { + "description": "The extrude surfaces.", + "type": "array", + "items": { + "description": "An extrude surface.", + "oneOf": [ + { + "description": "An extrude plane.", + "type": "object", + "required": [ + "faceId", + "id", + "name", + "position", + "rotation", + "sourceRange", + "type" + ], + "properties": { + "faceId": { + "description": "The face id for the extrude plane.", + "type": "string", + "format": "uuid" + }, + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "The name.", + "type": "string" + }, + "position": { + "description": "The position.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "extrudePlane" + ] + } + } + }, + { + "description": "An extruded arc.", + "type": "object", + "required": [ + "faceId", + "id", + "name", + "position", + "rotation", + "sourceRange", + "type" + ], + "properties": { + "faceId": { + "description": "The face id for the extrude plane.", + "type": "string", + "format": "uuid" + }, + "id": { + "description": "The id of the geometry.", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "The name.", + "type": "string" + }, + "position": { + "description": "The position.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 3, + "minItems": 3 + }, + "rotation": { + "description": "The rotation.", + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "maxItems": 4, + "minItems": 4 + }, + "sourceRange": { + "description": "The source range.", + "type": "array", + "items": { + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "maxItems": 2, + "minItems": 2 + }, + "type": { + "type": "string", + "enum": [ + "extrudeArc" + ] + } + } + } + ] + } + }, + "xAxis": { + "description": "The x-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "yAxis": { + "description": "The y-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + }, + "zAxis": { + "description": "The z-axis of the extrude group base plane in the 3D space", + "type": "object", + "required": [ + "x", + "y", + "z" + ], + "properties": { + "x": { + "type": "number", + "format": "double" + }, + "y": { + "type": "number", + "format": "double" + }, + "z": { + "type": "number", + "format": "double" + } + } + } + } + }, + "required": true + }, + "unpublished": false, + "deprecated": false, + "examples": [ + "const part001 = startSketchOn('XY')\n |> startProfileAt([4, 12], %)\n |> line([2, 0], %)\n |> line([0, -6], %)\n |> line([4, -6], %)\n |> line([0, -6], %)\n |> line([-3.75, -4.5], %)\n |> line([0, -5.5], %)\n |> line([-2, 0], %)\n |> close(%)\n |> revolve({ axis: 'y' }, %) // default angle is 360", + "const part001 = startSketchOn('XY')\n |> startProfileAt([4, 12], %)\n |> line([2, 0], %)\n |> line([0, -6], %)\n |> line([4, -6], %)\n |> line([0, -6], %)\n |> line([-3.75, -4.5], %)\n |> line([0, -5.5], %)\n |> line([-2, 0], %)\n |> close(%)\n |> revolve({ axis: 'y', angle: 180 }, %)", + "const box = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 20], %)\n |> line([20, 0], %)\n |> line([0, -20], %)\n |> close(%)\n |> extrude(20, %)\n\nconst sketch001 = startSketchOn(box, \"END\")\n |> circle([10, 10], 4, %)\n |> revolve({ angle: -90, axis: 'y' }, %)", + "const box = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 20], %)\n |> line([20, 0], %)\n |> line([0, -20], %, 'revolveAxis')\n |> close(%)\n |> extrude(20, %)\n\nconst sketch001 = startSketchOn(box, \"END\")\n |> circle([10, 10], 4, %)\n |> revolve({\n angle: 90,\n axis: getOppositeEdge('revolveAxis', box)\n }, %)" + ] + }, { "name": "segAng", "summary": "Returns the angle of the segment.", diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-mm-2-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-mm-2-Google-Chrome-linux.png index ddabe104b..fe32d383f 100644 Binary files a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-mm-2-Google-Chrome-linux.png and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Client-side-scene-scale-should-match-engine-scale-mm-2-Google-Chrome-linux.png differ diff --git a/src/wasm-lib/Cargo.lock b/src/wasm-lib/Cargo.lock index 53c05a2d7..e46825d10 100644 --- a/src/wasm-lib/Cargo.lock +++ b/src/wasm-lib/Cargo.lock @@ -1896,9 +1896,9 @@ dependencies = [ [[package]] name = "kittycad" -version = "0.2.62" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6a3e37a902c099f3f077f1e75814339bf5d548151a675544366841a882377" +checksum = "93a332250e08fd715ad3d5826e04d36da1c5bb42d0c1b1ff1f0598278b9ebf3c" dependencies = [ "anyhow", "async-trait", diff --git a/src/wasm-lib/Cargo.toml b/src/wasm-lib/Cargo.toml index 598e77abe..0cc37ecd7 100644 --- a/src/wasm-lib/Cargo.toml +++ b/src/wasm-lib/Cargo.toml @@ -59,7 +59,7 @@ members = [ ] [workspace.dependencies] -kittycad = { version = "0.2.62", default-features = false, features = ["js", "requests"] } +kittycad = { version = "0.2.63", default-features = false, features = ["js", "requests"] } kittycad-execution-plan = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" } kittycad-execution-plan-macros = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" } kittycad-execution-plan-traits = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" } diff --git a/src/wasm-lib/kcl/src/std/extrude.rs b/src/wasm-lib/kcl/src/std/extrude.rs index 0817d2d58..7b5e2eabb 100644 --- a/src/wasm-lib/kcl/src/std/extrude.rs +++ b/src/wasm-lib/kcl/src/std/extrude.rs @@ -36,6 +36,7 @@ pub async fn extrude(args: Args) -> Result { }] async fn inner_extrude(length: f64, sketch_group: Box, args: Args) -> Result, KclError> { let id = uuid::Uuid::new_v4(); + // Extrude the element. args.send_modeling_cmd( id, @@ -47,6 +48,15 @@ async fn inner_extrude(length: f64, sketch_group: Box, args: Args) ) .await?; + do_post_extrude(sketch_group, length, id, args).await +} + +pub(crate) async fn do_post_extrude( + sketch_group: Box, + length: f64, + id: Uuid, + args: Args, +) -> Result, KclError> { // We need to do this after extrude for sketch on face. if let SketchSurface::Face(_) = sketch_group.on { // Disable the sketch mode. diff --git a/src/wasm-lib/kcl/src/std/fillet.rs b/src/wasm-lib/kcl/src/std/fillet.rs index 971933d74..4b84cd5b5 100644 --- a/src/wasm-lib/kcl/src/std/fillet.rs +++ b/src/wasm-lib/kcl/src/std/fillet.rs @@ -13,6 +13,8 @@ use crate::{ std::Args, }; +pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001; + /// Data for fillets. #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[ts(export)] @@ -21,18 +23,18 @@ pub struct FilletData { /// The radius of the fillet. pub radius: f64, /// The tags of the paths you want to fillet. - pub tags: Vec, + pub tags: Vec, } /// A string or a uuid. #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Ord, PartialOrd, Eq, Hash)] #[ts(export)] #[serde(untagged)] -pub enum StringOrUuid { - /// A uuid. - Uuid(Uuid), - /// A string. - String(String), +pub enum EdgeReference { + /// A uuid of an edge. + Uuid(uuid::Uuid), + /// A tag name of an edge. + Tag(String), } /// Create fillets on tagged paths. @@ -76,8 +78,8 @@ async fn inner_fillet( for tag in data.tags { let edge_id = match tag { - StringOrUuid::Uuid(uuid) => uuid, - StringOrUuid::String(tag) => { + EdgeReference::Uuid(uuid) => uuid, + EdgeReference::Tag(tag) => { extrude_group .sketch_group_values .iter() @@ -100,7 +102,7 @@ async fn inner_fillet( edge_id, object_id: extrude_group.id, radius: data.radius, - tolerance: 0.0000001, // We can let the user set this in the future. + tolerance: DEFAULT_TOLERANCE, // We can let the user set this in the future. }, ) .await?; diff --git a/src/wasm-lib/kcl/src/std/mod.rs b/src/wasm-lib/kcl/src/std/mod.rs index d66bb91f0..66c6c506f 100644 --- a/src/wasm-lib/kcl/src/std/mod.rs +++ b/src/wasm-lib/kcl/src/std/mod.rs @@ -7,6 +7,7 @@ pub mod import; pub mod kcl_stdlib; pub mod math; pub mod patterns; +pub mod revolve; pub mod segment; pub mod shapes; pub mod sketch; @@ -81,6 +82,8 @@ lazy_static! { Box::new(crate::std::fillet::GetNextAdjacentEdge), Box::new(crate::std::fillet::GetPreviousAdjacentEdge), Box::new(crate::std::helix::Helix), + Box::new(crate::std::revolve::Revolve), + Box::new(crate::std::revolve::GetEdge), Box::new(crate::std::import::Import), Box::new(crate::std::math::Cos), Box::new(crate::std::math::Sin), diff --git a/src/wasm-lib/kcl/src/std/revolve.rs b/src/wasm-lib/kcl/src/std/revolve.rs new file mode 100644 index 000000000..1ca91c749 --- /dev/null +++ b/src/wasm-lib/kcl/src/std/revolve.rs @@ -0,0 +1,341 @@ +//! Standard library revolution surfaces. + +use anyhow::Result; +use derive_docs::stdlib; +use kittycad::types::ModelingCmd; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::{ + errors::{KclError, KclErrorDetails}, + executor::{ExtrudeGroup, MemoryItem, SketchGroup, UserVal}, + std::{ + extrude::do_post_extrude, + fillet::{EdgeReference, DEFAULT_TOLERANCE}, + Args, + }, +}; + +/// Data for revolution surfaces. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] +#[ts(export)] +pub struct RevolveData { + /// Angle to revolve (in degrees). Default is 360. + #[serde(default)] + pub angle: Option, + /// Axis of revolution. + pub axis: RevolveAxis, +} + +/// Axis of revolution or tagged edge. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] +#[ts(export)] +#[serde(untagged)] +pub enum RevolveAxis { + /// Axis of revolution. + Axis(RevolveAxisAndOrigin), + /// Tagged edge. + Edge(EdgeReference), +} + +/// Axis of revolution. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] +#[ts(export)] +#[serde(rename_all = "camelCase")] +pub enum RevolveAxisAndOrigin { + /// X-axis. + #[serde(alias = "X")] + X, + /// Y-axis. + #[serde(alias = "Y")] + Y, + /// Z-axis. + #[serde(alias = "Z")] + Z, + /// Flip the X-axis. + #[serde(rename = "-X", alias = "-x")] + NegX, + /// Flip the Y-axis. + #[serde(rename = "-Y", alias = "-y")] + NegY, + /// Flip the Z-axis. + #[serde(rename = "-Z", alias = "-z")] + NegZ, + Custom { + /// The axis. + axis: [f64; 3], + /// The origin. + origin: [f64; 3], + }, +} + +impl RevolveAxisAndOrigin { + /// Get the axis and origin. + pub fn axis_and_origin(&self) -> Result<(kittycad::types::Point3D, kittycad::types::Point3D), KclError> { + let (axis, origin) = match self { + RevolveAxisAndOrigin::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::Z => ([0.0, 0.0, 1.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::NegZ => ([0.0, 0.0, -1.0], [0.0, 0.0, 0.0]), + RevolveAxisAndOrigin::Custom { axis, origin } => (*axis, *origin), + }; + + Ok(( + kittycad::types::Point3D { + x: axis[0], + y: axis[1], + z: axis[2], + }, + kittycad::types::Point3D { + x: origin[0], + y: origin[1], + z: origin[2], + }, + )) + } +} + +/// Revolve a sketch around an axis. +pub async fn revolve(args: Args) -> Result { + let (data, sketch_group): (RevolveData, Box) = args.get_data_and_sketch_group()?; + + let extrude_group = inner_revolve(data, sketch_group, args).await?; + Ok(MemoryItem::ExtrudeGroup(extrude_group)) +} + +/// Revolve a sketch around an axis. +/// +/// ```no_run +/// const part001 = startSketchOn('XY') +/// |> startProfileAt([4, 12], %) +/// |> line([2, 0], %) +/// |> line([0, -6], %) +/// |> line([4, -6], %) +/// |> line([0, -6], %) +/// |> line([-3.75, -4.5], %) +/// |> line([0, -5.5], %) +/// |> line([-2, 0], %) +/// |> close(%) +/// |> revolve({axis: 'y'}, %) // default angle is 360 +/// ``` +/// +/// ```no_run +/// const part001 = startSketchOn('XY') +/// |> startProfileAt([4, 12], %) +/// |> line([2, 0], %) +/// |> line([0, -6], %) +/// |> line([4, -6], %) +/// |> line([0, -6], %) +/// |> line([-3.75, -4.5], %) +/// |> line([0, -5.5], %) +/// |> line([-2, 0], %) +/// |> close(%) +/// |> revolve({axis: 'y', angle: 180}, %) +/// ``` +/// +/// ```no_run +/// const box = startSketchOn('XY') +/// |> startProfileAt([0, 0], %) +/// |> line([0, 20], %) +/// |> line([20, 0], %) +/// |> line([0, -20], %) +/// |> close(%) +/// |> extrude(20, %) +/// +/// const sketch001 = startSketchOn(box, "END") +/// |> circle([10,10], 4, %) +/// |> revolve({ +/// angle: -90, +/// axis: 'y' +/// }, %) +/// ``` +/// +/// ```no_run +/// const box = startSketchOn('XY') +/// |> startProfileAt([0, 0], %) +/// |> line([0, 20], %) +/// |> line([20, 0], %) +/// |> line([0, -20], %, 'revolveAxis') +/// |> close(%) +/// |> extrude(20, %) +/// +/// const sketch001 = startSketchOn(box, "END") +/// |> circle([10,10], 4, %) +/// |> revolve({ +/// angle: 90, +/// axis: getOppositeEdge('revolveAxis', box) +/// }, %) +/// +/// ``` +#[stdlib { + name = "revolve", +}] +async fn inner_revolve( + data: RevolveData, + sketch_group: Box, + args: Args, +) -> Result, KclError> { + if let Some(angle) = data.angle { + // Return an error if the angle is less than -360 or greater than 360. + if !(-360.0..=360.0).contains(&angle) { + return Err(KclError::Semantic(KclErrorDetails { + message: format!("Expected angle to be between -360 and 360, found `{}`", angle), + source_ranges: vec![args.source_range], + })); + } + } + + let angle = kittycad::types::Angle::from_degrees(data.angle.unwrap_or(360.0)); + + let id = uuid::Uuid::new_v4(); + match data.axis { + RevolveAxis::Axis(axis) => { + let (axis, origin) = axis.axis_and_origin()?; + args.send_modeling_cmd( + id, + ModelingCmd::Revolve { + angle, + target: sketch_group.id, + axis, + origin, + tolerance: DEFAULT_TOLERANCE, + axis_is_2d: true, + }, + ) + .await?; + } + RevolveAxis::Edge(edge) => { + let edge_id = match edge { + EdgeReference::Uuid(uuid) => uuid, + EdgeReference::Tag(tag) => { + sketch_group + .value + .iter() + .find(|p| p.get_name() == tag) + .ok_or_else(|| { + KclError::Type(KclErrorDetails { + message: format!("No edge found with tag: `{}`", tag), + source_ranges: vec![args.source_range], + }) + })? + .get_base() + .geo_meta + .id + } + }; + args.send_modeling_cmd( + id, + ModelingCmd::RevolveAboutEdge { + angle, + target: sketch_group.id, + edge_id, + tolerance: DEFAULT_TOLERANCE, + }, + ) + .await?; + } + } + + do_post_extrude(sketch_group, 0.0, id, args).await +} + +/// Get an edge on a 3D solid. +pub async fn get_edge(args: Args) -> Result { + let (tag, extrude_group): (String, Box) = args.get_data_and_extrude_group()?; + + let edge = inner_get_edge(tag, extrude_group, args.clone()).await?; + Ok(MemoryItem::UserVal(UserVal { + value: serde_json::to_value(edge).map_err(|e| { + KclError::Type(KclErrorDetails { + message: format!("Failed to convert Uuid to json: {}", e), + source_ranges: vec![args.source_range], + }) + })?, + meta: vec![args.source_range.into()], + })) +} + +/// Get an edge on a 3D solid. +/// +/// ```no_run +/// const box = startSketchOn('XY') +/// |> startProfileAt([0, 0], %) +/// |> line([0, 10], %) +/// |> line([10, 0], %) +/// |> line([0, -10], %, 'revolveAxis') +/// |> close(%) +/// |> extrude(10, %) +/// +/// const sketch001 = startSketchOn(box, "revolveAxis") +/// |> startProfileAt([5, 10], %) +/// |> line([0, -10], %) +/// |> line([2, 0], %) +/// |> line([0, 10], %) +/// |> close(%) +/// |> revolve({ axis: getEdge('revolveAxis', box), angle: 90 }, %) +/// ``` +#[stdlib { + name = "getEdge", +}] +async fn inner_get_edge(tag: String, extrude_group: Box, args: Args) -> Result { + let tagged_path = extrude_group + .sketch_group_values + .iter() + .find(|p| p.get_name() == tag) + .ok_or_else(|| { + KclError::Type(KclErrorDetails { + message: format!("No edge found with tag: `{}`", tag), + source_ranges: vec![args.source_range], + }) + })? + .get_base(); + + Ok(tagged_path.geo_meta.id) +} + +#[cfg(test)] +mod tests { + + use pretty_assertions::assert_eq; + + use crate::std::revolve::{RevolveAxis, RevolveAxisAndOrigin}; + + #[test] + fn test_deserialize_revolve_axis() { + let data = RevolveAxis::Axis(RevolveAxisAndOrigin::X); + let mut str_json = serde_json::to_string(&data).unwrap(); + assert_eq!(str_json, "\"x\""); + + str_json = "\"Y\"".to_string(); + let data: RevolveAxis = serde_json::from_str(&str_json).unwrap(); + assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::Y)); + + str_json = "\"-Y\"".to_string(); + let data: RevolveAxis = serde_json::from_str(&str_json).unwrap(); + assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::NegY)); + + str_json = "\"-x\"".to_string(); + let data: RevolveAxis = serde_json::from_str(&str_json).unwrap(); + assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::NegX)); + + let data = RevolveAxis::Axis(RevolveAxisAndOrigin::Custom { + axis: [0.0, -1.0, 0.0], + origin: [1.0, 0.0, 2.0], + }); + str_json = serde_json::to_string(&data).unwrap(); + assert_eq!(str_json, r#"{"custom":{"axis":[0.0,-1.0,0.0],"origin":[1.0,0.0,2.0]}}"#); + + str_json = r#"{"custom": {"axis": [0,-1,0], "origin": [1,0,2.0]}}"#.to_string(); + let data: RevolveAxis = serde_json::from_str(&str_json).unwrap(); + assert_eq!( + data, + RevolveAxis::Axis(RevolveAxisAndOrigin::Custom { + axis: [0.0, -1.0, 0.0], + origin: [1.0, 0.0, 2.0] + }) + ); + } +} diff --git a/src/wasm-lib/tests/executor/main.rs b/src/wasm-lib/tests/executor/main.rs index 33cec2614..5616b1428 100644 --- a/src/wasm-lib/tests/executor/main.rs +++ b/src/wasm-lib/tests/executor/main.rs @@ -1487,3 +1487,337 @@ async fn serial_test_big_number_angle_to_match_length_y() { 1.0, ); } + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_simple_revolve() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'y'}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_simple_revolve_uppercase() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'Y'}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve_uppercase.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_simple_revolve_negative() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: '-Y', angle: 180}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve_negative.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_bad_angle_low() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'y', angle: -455}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm).await; + + assert!(result.is_err()); + assert_eq!( + result.err().unwrap().to_string(), + r#"semantic: KclErrorDetails { source_ranges: [SourceRange([278, 314])], message: "Expected angle to be between -360 and 360, found `-455`" }"# + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_bad_angle_high() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'y', angle: 455}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm).await; + + assert!(result.is_err()); + assert_eq!( + result.err().unwrap().to_string(), + r#"semantic: KclErrorDetails { source_ranges: [SourceRange([278, 313])], message: "Expected angle to be between -360 and 360, found `455`" }"# + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_simple_revolve_custom_angle() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'y', angle: 180}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve_custom_angle.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_simple_revolve_custom_axis() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: {custom: {axis: [0, -1, 0], origin: [0,0,0]}}, angle: 180}, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve_custom_axis.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_on_edge() { + let code = r#"const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 10], %) + |> line([10, 0], %) + |> line([0, -10], %, 'revolveAxis') + |> close(%) + |> extrude(10, %) + +const sketch001 = startSketchOn(box, "end") + |> startProfileAt([5, 10], %) + |> line([0, -10], %) + |> line([2, 0], %) + |> line([0, 10], %) + |> close(%) + |> revolve({ axis: getOppositeEdge('revolveAxis', box), angle: 90 }, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/revolve_on_edge.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_on_edge_get_edge() { + let code = r#"const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 10], %) + |> line([10, 0], %) + |> line([0, -10], %, 'revolveAxis') + |> close(%) + |> extrude(10, %) + +const sketch001 = startSketchOn(box, "revolveAxis") + |> startProfileAt([5, 10], %) + |> line([0, -10], %) + |> line([2, 0], %) + |> line([0, 10], %) + |> close(%) + |> revolve({ axis: getEdge('revolveAxis', box), angle: 90 }, %) + +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/revolve_on_edge_get_edge.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_on_face_circle_edge() { + let code = r#"const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 20], %) + |> line([20, 0], %) + |> line([0, -20], %, 'revolveAxis') + |> close(%) + |> extrude(20, %) + +const sketch001 = startSketchOn(box, "END") + |> circle([10,10], 4, %) + |> revolve({ + angle: 90, + axis: getOppositeEdge('revolveAxis', box) + }, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/revolve_on_face_circle_edge.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_on_face_circle() { + let code = r#"const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 20], %) + |> line([20, 0], %, 'revolveAxis') + |> line([0, -20], %) + |> close(%) + |> extrude(20, %) + +const sketch001 = startSketchOn(box, "END") + |> circle([10,10], 4, %) + |> revolve({ + angle: -90, + axis: 'y' + }, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/revolve_on_face_circle.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_revolve_on_face() { + let code = r#"const box = startSketchOn('XY') + |> startProfileAt([0, 0], %) + |> line([0, 10], %) + |> line([10, 0], %) + |> line([0, -10], %) + |> close(%, 'revolveAxis') + |> extrude(10, %) + +const sketch001 = startSketchOn(box, "end") + |> startProfileAt([5, 10], %) + |> line([0, -10], %) + |> line([2, 0], %) + |> line([0, 10], %) + |> close(%) + |> revolve({ + axis: 'y', + angle: -90, + }, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/revolve_on_face.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_basic_revolve_circle() { + let code = r#"const sketch001 = startSketchOn('XY') + |> circle([15, 0], 5, %) + |> revolve({ + angle: 360, + axis: 'y' + }, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/basic_revolve_circle.png", &result, 1.0); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] // Ignore this test until https://github.com/KittyCAD/engine/pull/1930 is fixed +async fn serial_test_simple_revolve_sketch_on_edge() { + let code = r#"const part001 = startSketchOn('XY') + |> startProfileAt([4, 12], %) + |> line([2, 0], %) + |> line([0, -6], %) + |> line([4, -6], %) + |> line([0, -6], %) + |> line([-3.75, -4.5], %) + |> line([0, -5.5], %) + |> line([-2, 0], %) + |> close(%) + |> revolve({axis: 'y', angle: 180}, %) + +const part002 = startSketchOn(part001, 'end') + |> startProfileAt([4.5, -5], %) + |> line([0, 5], %) + |> line([5, 0], %) + |> line([0, -5], %) + |> close(%) + |> extrude(5, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image("tests/executor/outputs/simple_revolve_sketch_on_edge.png", &result, 1.0); +} diff --git a/src/wasm-lib/tests/executor/outputs/basic_revolve_circle.png b/src/wasm-lib/tests/executor/outputs/basic_revolve_circle.png new file mode 100644 index 000000000..75fb03c5d Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/basic_revolve_circle.png differ diff --git a/src/wasm-lib/tests/executor/outputs/revolve_on_edge.png b/src/wasm-lib/tests/executor/outputs/revolve_on_edge.png new file mode 100644 index 000000000..5e0bfe8b4 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/revolve_on_edge.png differ diff --git a/src/wasm-lib/tests/executor/outputs/revolve_on_edge_get_edge.png b/src/wasm-lib/tests/executor/outputs/revolve_on_edge_get_edge.png new file mode 100644 index 000000000..6745660fd Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/revolve_on_edge_get_edge.png differ diff --git a/src/wasm-lib/tests/executor/outputs/revolve_on_face.png b/src/wasm-lib/tests/executor/outputs/revolve_on_face.png new file mode 100644 index 000000000..2e49ddd62 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/revolve_on_face.png differ diff --git a/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle.png b/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle.png new file mode 100644 index 000000000..59ac89e97 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle.png differ diff --git a/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle_edge.png b/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle_edge.png new file mode 100644 index 000000000..c17a7e422 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/revolve_on_face_circle_edge.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve.png b/src/wasm-lib/tests/executor/outputs/simple_revolve.png new file mode 100644 index 000000000..b744ae5bc Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_angle.png b/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_angle.png new file mode 100644 index 000000000..1b04ef168 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_angle.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_axis.png b/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_axis.png new file mode 100644 index 000000000..8f5bbdee7 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve_custom_axis.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve_negative.png b/src/wasm-lib/tests/executor/outputs/simple_revolve_negative.png new file mode 100644 index 000000000..8f5bbdee7 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve_negative.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve_sketch_on_edge.png b/src/wasm-lib/tests/executor/outputs/simple_revolve_sketch_on_edge.png new file mode 100644 index 000000000..0a779dcf1 Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve_sketch_on_edge.png differ diff --git a/src/wasm-lib/tests/executor/outputs/simple_revolve_uppercase.png b/src/wasm-lib/tests/executor/outputs/simple_revolve_uppercase.png new file mode 100644 index 000000000..b744ae5bc Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/simple_revolve_uppercase.png differ