2D unclosed sketch Mirror (#3851)
* start of mirror Signed-off-by: Jess Frazelle <github@jessfraz.com> fmt Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> cleanup Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> add mirror Signed-off-by: Jess Frazelle <github@jessfraz.com> updates Signed-off-by: Jess Frazelle <github@jessfraz.com> updates Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix export tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix export tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * Look at this (photo)Graph *in the voice of Nickelback* * empty --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@ -64,6 +64,7 @@ layout: manual
|
|||||||
* [`m`](kcl/m)
|
* [`m`](kcl/m)
|
||||||
* [`max`](kcl/max)
|
* [`max`](kcl/max)
|
||||||
* [`min`](kcl/min)
|
* [`min`](kcl/min)
|
||||||
|
* [`mirror2d`](kcl/mirror2d)
|
||||||
* [`mm`](kcl/mm)
|
* [`mm`](kcl/mm)
|
||||||
* [`offsetPlane`](kcl/offsetPlane)
|
* [`offsetPlane`](kcl/offsetPlane)
|
||||||
* [`patternCircular2d`](kcl/patternCircular2d)
|
* [`patternCircular2d`](kcl/patternCircular2d)
|
||||||
|
652
docs/kcl/mirror2d.md
Normal file
@ -7,6 +7,7 @@ layout: manual
|
|||||||
Rotate a sketch around some provided axis, creating a solid from its extent.
|
Rotate a sketch around some provided axis, creating a solid from its extent.
|
||||||
|
|
||||||
This, like extrude, is able to create a 3-dimensional solid from a 2-dimensional sketch. However, unlike extrude, this creates a solid by using the extent of the sketch as its revolved around an axis rather than using the extent of the sketch linearly translated through a third dimension.
|
This, like extrude, is able to create a 3-dimensional solid from a 2-dimensional sketch. However, unlike extrude, this creates a solid by using the extent of the sketch as its revolved around an axis rather than using the extent of the sketch linearly translated through a third dimension.
|
||||||
|
Revolve occurs around a local sketch axis rather than a global axis.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
revolve(data: RevolveData, sketch_group: SketchGroup) -> ExtrudeGroup
|
revolve(data: RevolveData, sketch_group: SketchGroup) -> ExtrudeGroup
|
||||||
@ -143,10 +144,7 @@ const sketch001 = startSketchOn('XY')
|
|||||||
|
|
||||||
const part001 = revolve({
|
const part001 = revolve({
|
||||||
axis: {
|
axis: {
|
||||||
custom: {
|
custom: { axis: [0.0, 1.0], origin: [0.0, 0.0] }
|
||||||
axis: [0.0, 1.0, 0.0],
|
|
||||||
origin: [0.0, 0.0, 0.0]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, sketch001)
|
}, sketch001)
|
||||||
```
|
```
|
||||||
@ -163,16 +161,14 @@ const part001 = revolve({
|
|||||||
// Axis of revolution.
|
// Axis of revolution.
|
||||||
axis: "X" |
|
axis: "X" |
|
||||||
"Y" |
|
"Y" |
|
||||||
"Z" |
|
|
||||||
"-X" |
|
"-X" |
|
||||||
"-Y" |
|
"-Y" |
|
||||||
"-Z" |
|
|
||||||
{
|
{
|
||||||
custom: {
|
custom: {
|
||||||
// The axis.
|
// The axis.
|
||||||
axis: [number, number, number],
|
axis: [number, number],
|
||||||
// The origin.
|
// The origin.
|
||||||
origin: [number, number, number],
|
origin: [number, number],
|
||||||
},
|
},
|
||||||
} |
|
} |
|
||||||
uuid |
|
uuid |
|
||||||
|
8562
docs/kcl/std.json
@ -104,7 +104,7 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBe(482669)
|
.toBe(431341)
|
||||||
|
|
||||||
// clean up output.gltf
|
// clean up output.gltf
|
||||||
await fsp.rm('output.gltf')
|
await fsp.rm('output.gltf')
|
||||||
@ -178,7 +178,7 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBe(105022)
|
.toBe(102040)
|
||||||
|
|
||||||
// clean up output.gltf
|
// clean up output.gltf
|
||||||
await fsp.rm('output.gltf')
|
await fsp.rm('output.gltf')
|
||||||
|
@ -203,7 +203,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBe(482669)
|
.toBe(431341)
|
||||||
|
|
||||||
// clean up output.gltf
|
// clean up output.gltf
|
||||||
await fsp.rm('output.gltf')
|
await fsp.rm('output.gltf')
|
||||||
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 357 KiB |
Before Width: | Height: | Size: 613 KiB After Width: | Height: | Size: 577 KiB |
4
src/wasm-lib/Cargo.lock
generated
@ -690,7 +690,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
version = "0.1.27"
|
version = "0.1.28"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -1400,7 +1400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.18"
|
version = "0.2.19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.27"
|
version = "0.1.28"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -116,6 +116,7 @@ fn do_stdlib_inner(
|
|||||||
|
|
||||||
// Fail if the name is not camel case.
|
// Fail if the name is not camel case.
|
||||||
let whitelist = [
|
let whitelist = [
|
||||||
|
"mirror2d",
|
||||||
"patternLinear3d",
|
"patternLinear3d",
|
||||||
"patternLinear2d",
|
"patternLinear2d",
|
||||||
"patternCircular3d",
|
"patternCircular3d",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.18"
|
version = "0.2.19"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
@ -20,7 +20,7 @@ clap = { version = "4.5.18", default-features = false, optional = true, features
|
|||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
databake = { version = "0.1.8", features = ["derive"] }
|
databake = { version = "0.1.8", features = ["derive"] }
|
||||||
derive-docs = { version = "0.1.27", path = "../derive-docs" }
|
derive-docs = { version = "0.1.28", path = "../derive-docs" }
|
||||||
form_urlencoded = "1.2.1"
|
form_urlencoded = "1.2.1"
|
||||||
futures = { version = "0.3.30" }
|
futures = { version = "0.3.30" }
|
||||||
git_rev = "0.1.0"
|
git_rev = "0.1.0"
|
||||||
|
@ -645,6 +645,7 @@ impl_from_arg_via_json!(crate::std::import::ImportFormat);
|
|||||||
impl_from_arg_via_json!(crate::std::polar::PolarCoordsData);
|
impl_from_arg_via_json!(crate::std::polar::PolarCoordsData);
|
||||||
impl_from_arg_via_json!(crate::std::loft::LoftData);
|
impl_from_arg_via_json!(crate::std::loft::LoftData);
|
||||||
impl_from_arg_via_json!(crate::std::planes::StandardPlane);
|
impl_from_arg_via_json!(crate::std::planes::StandardPlane);
|
||||||
|
impl_from_arg_via_json!(crate::std::mirror::MirrorData);
|
||||||
impl_from_arg_via_json!(SketchGroup);
|
impl_from_arg_via_json!(SketchGroup);
|
||||||
impl_from_arg_via_json!(FaceTag);
|
impl_from_arg_via_json!(FaceTag);
|
||||||
impl_from_arg_via_json!(String);
|
impl_from_arg_via_json!(String);
|
||||||
|
@ -46,6 +46,15 @@ pub enum EdgeReference {
|
|||||||
Tag(Box<TagIdentifier>),
|
Tag(Box<TagIdentifier>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EdgeReference {
|
||||||
|
pub fn get_engine_id(&self, exec_state: &mut ExecState, args: &Args) -> Result<uuid::Uuid, KclError> {
|
||||||
|
match self {
|
||||||
|
EdgeReference::Uuid(uuid) => Ok(*uuid),
|
||||||
|
EdgeReference::Tag(tag) => Ok(args.get_tag_engine_info(exec_state, tag)?.id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create fillets on tagged paths.
|
/// Create fillets on tagged paths.
|
||||||
pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (data, extrude_group, tag): (FilletData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
let (data, extrude_group, tag): (FilletData, Box<ExtrudeGroup>, Option<TagDeclarator>) =
|
||||||
@ -134,10 +143,7 @@ async fn inner_fillet(
|
|||||||
|
|
||||||
let mut extrude_group = extrude_group.clone();
|
let mut extrude_group = extrude_group.clone();
|
||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = match edge_tag {
|
let edge_id = edge_tag.get_engine_id(exec_state, &args)?;
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
|
||||||
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
|
|
||||||
};
|
|
||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
args.batch_end_cmd(
|
args.batch_end_cmd(
|
||||||
|
154
src/wasm-lib/kcl/src/std/mirror.rs
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//! Standard library mirror.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use derive_docs::stdlib;
|
||||||
|
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
||||||
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
errors::KclError,
|
||||||
|
executor::{ExecState, KclValue, SketchGroup, SketchGroupSet},
|
||||||
|
std::{revolve::AxisOrEdgeReference, Args},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Data for a mirror.
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct MirrorData {
|
||||||
|
/// Axis to use as mirror.
|
||||||
|
pub axis: AxisOrEdgeReference,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mirror a sketch.
|
||||||
|
///
|
||||||
|
/// Only works on unclosed sketches for now.
|
||||||
|
pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
|
let (data, sketch_group_set): (MirrorData, SketchGroupSet) = args.get_data_and_sketch_group_set()?;
|
||||||
|
|
||||||
|
let sketch_groups = inner_mirror_2d(data, sketch_group_set, exec_state, args).await?;
|
||||||
|
Ok(sketch_groups.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mirror a sketch.
|
||||||
|
///
|
||||||
|
/// Only works on unclosed sketches for now.
|
||||||
|
///
|
||||||
|
/// Mirror occurs around a local sketch axis rather than a global axis.
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Mirror an un-closed sketch across the Y axis.
|
||||||
|
/// const sketch001 = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 10], %)
|
||||||
|
/// |> line([15, 0], %)
|
||||||
|
/// |> line([-7, -3], %)
|
||||||
|
/// |> line([9, -1], %)
|
||||||
|
/// |> line([-8, -5], %)
|
||||||
|
/// |> line([9, -3], %)
|
||||||
|
/// |> line([-8, -3], %)
|
||||||
|
/// |> line([9, -1], %)
|
||||||
|
/// |> line([-19, -0], %)
|
||||||
|
/// |> mirror2d({axis: 'Y'}, %)
|
||||||
|
///
|
||||||
|
/// const example = extrude(10, sketch001)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Mirror a un-closed sketch across the Y axis.
|
||||||
|
/// const sketch001 = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 8.5], %)
|
||||||
|
/// |> line([20, -8.5], %)
|
||||||
|
/// |> line([-20, -8.5], %)
|
||||||
|
/// |> mirror2d({axis: 'Y'}, %)
|
||||||
|
///
|
||||||
|
/// const example = extrude(10, sketch001)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Mirror a un-closed sketch across an edge.
|
||||||
|
/// const helper001 = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 0], %)
|
||||||
|
/// |> line([0, 10], %, $edge001)
|
||||||
|
///
|
||||||
|
/// const sketch001 = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 8.5], %)
|
||||||
|
/// |> line([20, -8.5], %)
|
||||||
|
/// |> line([-20, -8.5], %)
|
||||||
|
/// |> mirror2d({axis: edge001}, %)
|
||||||
|
///
|
||||||
|
/// const example = extrude(10, sketch001)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// // Mirror an un-closed sketch across a custom axis.
|
||||||
|
/// const sketch001 = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 8.5], %)
|
||||||
|
/// |> line([20, -8.5], %)
|
||||||
|
/// |> line([-20, -8.5], %)
|
||||||
|
/// |> mirror2d({
|
||||||
|
/// axis: {
|
||||||
|
/// custom: {
|
||||||
|
/// axis: [0.0, 1.0],
|
||||||
|
/// origin: [0.0, 0.0]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }, %)
|
||||||
|
///
|
||||||
|
/// const example = extrude(10, sketch001)
|
||||||
|
/// ```
|
||||||
|
#[stdlib {
|
||||||
|
name = "mirror2d",
|
||||||
|
}]
|
||||||
|
async fn inner_mirror_2d(
|
||||||
|
data: MirrorData,
|
||||||
|
sketch_group_set: SketchGroupSet,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<Vec<Box<SketchGroup>>, KclError> {
|
||||||
|
let starting_sketch_groups = match sketch_group_set {
|
||||||
|
SketchGroupSet::SketchGroup(sketch_group) => vec![sketch_group],
|
||||||
|
SketchGroupSet::SketchGroups(sketch_groups) => sketch_groups,
|
||||||
|
};
|
||||||
|
|
||||||
|
if args.ctx.is_mock {
|
||||||
|
return Ok(starting_sketch_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
match data.axis {
|
||||||
|
AxisOrEdgeReference::Axis(axis) => {
|
||||||
|
let (axis, origin) = axis.axis_and_origin()?;
|
||||||
|
|
||||||
|
args.batch_modeling_cmd(
|
||||||
|
uuid::Uuid::new_v4(),
|
||||||
|
ModelingCmd::from(mcmd::EntityMirror {
|
||||||
|
ids: starting_sketch_groups
|
||||||
|
.iter()
|
||||||
|
.map(|sketch_group| sketch_group.id)
|
||||||
|
.collect(),
|
||||||
|
axis,
|
||||||
|
point: origin,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
AxisOrEdgeReference::Edge(edge) => {
|
||||||
|
let edge_id = edge.get_engine_id(exec_state, &args)?;
|
||||||
|
|
||||||
|
args.batch_modeling_cmd(
|
||||||
|
uuid::Uuid::new_v4(),
|
||||||
|
ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
|
||||||
|
ids: starting_sketch_groups
|
||||||
|
.iter()
|
||||||
|
.map(|sketch_group| sketch_group.id)
|
||||||
|
.collect(),
|
||||||
|
edge_id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(starting_sketch_groups)
|
||||||
|
}
|
@ -12,6 +12,7 @@ pub mod import;
|
|||||||
pub mod kcl_stdlib;
|
pub mod kcl_stdlib;
|
||||||
pub mod loft;
|
pub mod loft;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
pub mod mirror;
|
||||||
pub mod patterns;
|
pub mod patterns;
|
||||||
pub mod planes;
|
pub mod planes;
|
||||||
pub mod polar;
|
pub mod polar;
|
||||||
@ -90,6 +91,7 @@ lazy_static! {
|
|||||||
Box::new(crate::std::sketch::TangentialArcToRelative),
|
Box::new(crate::std::sketch::TangentialArcToRelative),
|
||||||
Box::new(crate::std::sketch::BezierCurve),
|
Box::new(crate::std::sketch::BezierCurve),
|
||||||
Box::new(crate::std::sketch::Hole),
|
Box::new(crate::std::sketch::Hole),
|
||||||
|
Box::new(crate::std::mirror::Mirror2D),
|
||||||
Box::new(crate::std::patterns::PatternLinear2D),
|
Box::new(crate::std::patterns::PatternLinear2D),
|
||||||
Box::new(crate::std::patterns::PatternLinear3D),
|
Box::new(crate::std::patterns::PatternLinear3D),
|
||||||
Box::new(crate::std::patterns::PatternCircular2D),
|
Box::new(crate::std::patterns::PatternCircular2D),
|
||||||
|
@ -25,65 +25,57 @@ pub struct RevolveData {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub angle: Option<f64>,
|
pub angle: Option<f64>,
|
||||||
/// Axis of revolution.
|
/// Axis of revolution.
|
||||||
pub axis: RevolveAxis,
|
pub axis: AxisOrEdgeReference,
|
||||||
/// Tolerance for the revolve operation.
|
/// Tolerance for the revolve operation.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub tolerance: Option<f64>,
|
pub tolerance: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Axis of revolution or tagged edge.
|
/// Axis or tagged edge.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum RevolveAxis {
|
pub enum AxisOrEdgeReference {
|
||||||
/// Axis of revolution.
|
/// Axis and origin.
|
||||||
Axis(RevolveAxisAndOrigin),
|
Axis(AxisAndOrigin),
|
||||||
/// Tagged edge.
|
/// Tagged edge.
|
||||||
Edge(EdgeReference),
|
Edge(EdgeReference),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Axis of revolution.
|
/// Axis and origin.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum RevolveAxisAndOrigin {
|
pub enum AxisAndOrigin {
|
||||||
/// X-axis.
|
/// X-axis.
|
||||||
#[serde(rename = "X", alias = "x")]
|
#[serde(rename = "X", alias = "x")]
|
||||||
X,
|
X,
|
||||||
/// Y-axis.
|
/// Y-axis.
|
||||||
#[serde(rename = "Y", alias = "y")]
|
#[serde(rename = "Y", alias = "y")]
|
||||||
Y,
|
Y,
|
||||||
/// Z-axis.
|
|
||||||
#[serde(rename = "Z", alias = "z")]
|
|
||||||
Z,
|
|
||||||
/// Flip the X-axis.
|
/// Flip the X-axis.
|
||||||
#[serde(rename = "-X", alias = "-x")]
|
#[serde(rename = "-X", alias = "-x")]
|
||||||
NegX,
|
NegX,
|
||||||
/// Flip the Y-axis.
|
/// Flip the Y-axis.
|
||||||
#[serde(rename = "-Y", alias = "-y")]
|
#[serde(rename = "-Y", alias = "-y")]
|
||||||
NegY,
|
NegY,
|
||||||
/// Flip the Z-axis.
|
|
||||||
#[serde(rename = "-Z", alias = "-z")]
|
|
||||||
NegZ,
|
|
||||||
Custom {
|
Custom {
|
||||||
/// The axis.
|
/// The axis.
|
||||||
axis: [f64; 3],
|
axis: [f64; 2],
|
||||||
/// The origin.
|
/// The origin.
|
||||||
origin: [f64; 3],
|
origin: [f64; 2],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RevolveAxisAndOrigin {
|
impl AxisAndOrigin {
|
||||||
/// Get the axis and origin.
|
/// Get the axis and origin.
|
||||||
pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
|
pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
|
||||||
let (axis, origin) = match self {
|
let (axis, origin) = match self {
|
||||||
RevolveAxisAndOrigin::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
AxisAndOrigin::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]),
|
AxisAndOrigin::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]),
|
AxisAndOrigin::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
||||||
RevolveAxisAndOrigin::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
AxisAndOrigin::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
|
||||||
RevolveAxisAndOrigin::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
|
AxisAndOrigin::Custom { axis, origin } => ([axis[0], axis[1], 0.0], [origin[0], origin[1], 0.0]),
|
||||||
RevolveAxisAndOrigin::NegZ => ([0.0, 0.0, -1.0], [0.0, 0.0, 0.0]),
|
|
||||||
RevolveAxisAndOrigin::Custom { axis, origin } => (*axis, *origin),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
@ -117,6 +109,8 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
|||||||
/// than using the extent of the sketch linearly translated through a third
|
/// than using the extent of the sketch linearly translated through a third
|
||||||
/// dimension.
|
/// dimension.
|
||||||
///
|
///
|
||||||
|
/// Revolve occurs around a local sketch axis rather than a global axis.
|
||||||
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// const part001 = startSketchOn('XY')
|
/// const part001 = startSketchOn('XY')
|
||||||
/// |> startProfileAt([4, 12], %)
|
/// |> startProfileAt([4, 12], %)
|
||||||
@ -239,8 +233,8 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
|||||||
/// const part001 = revolve({
|
/// const part001 = revolve({
|
||||||
/// axis: {
|
/// axis: {
|
||||||
/// custom: {
|
/// custom: {
|
||||||
/// axis: [0.0, 1.0, 0.0],
|
/// axis: [0.0, 1.0],
|
||||||
/// origin: [0.0, 0.0, 0.0]
|
/// origin: [0.0, 0.0]
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }, sketch001)
|
/// }, sketch001)
|
||||||
@ -268,7 +262,7 @@ async fn inner_revolve(
|
|||||||
|
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
match data.axis {
|
match data.axis {
|
||||||
RevolveAxis::Axis(axis) => {
|
AxisOrEdgeReference::Axis(axis) => {
|
||||||
let (axis, origin) = axis.axis_and_origin()?;
|
let (axis, origin) = axis.axis_and_origin()?;
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
@ -283,11 +277,8 @@ async fn inner_revolve(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
RevolveAxis::Edge(edge) => {
|
AxisOrEdgeReference::Edge(edge) => {
|
||||||
let edge_id = match edge {
|
let edge_id = edge.get_engine_id(exec_state, &args)?;
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
|
||||||
EdgeReference::Tag(tag) => args.get_tag_engine_info(exec_state, &tag)?.id,
|
|
||||||
};
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
ModelingCmd::from(mcmd::RevolveAboutEdge {
|
ModelingCmd::from(mcmd::RevolveAboutEdge {
|
||||||
@ -309,40 +300,40 @@ mod tests {
|
|||||||
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::std::revolve::{RevolveAxis, RevolveAxisAndOrigin};
|
use crate::std::revolve::{AxisAndOrigin, AxisOrEdgeReference};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_revolve_axis() {
|
fn test_deserialize_revolve_axis() {
|
||||||
let data = RevolveAxis::Axis(RevolveAxisAndOrigin::X);
|
let data = AxisOrEdgeReference::Axis(AxisAndOrigin::X);
|
||||||
let mut str_json = serde_json::to_string(&data).unwrap();
|
let mut str_json = serde_json::to_string(&data).unwrap();
|
||||||
assert_eq!(str_json, "\"X\"");
|
assert_eq!(str_json, "\"X\"");
|
||||||
|
|
||||||
str_json = "\"Y\"".to_string();
|
str_json = "\"Y\"".to_string();
|
||||||
let data: RevolveAxis = serde_json::from_str(&str_json).unwrap();
|
let data: AxisOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||||
assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::Y));
|
assert_eq!(data, AxisOrEdgeReference::Axis(AxisAndOrigin::Y));
|
||||||
|
|
||||||
str_json = "\"-Y\"".to_string();
|
str_json = "\"-Y\"".to_string();
|
||||||
let data: RevolveAxis = serde_json::from_str(&str_json).unwrap();
|
let data: AxisOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||||
assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::NegY));
|
assert_eq!(data, AxisOrEdgeReference::Axis(AxisAndOrigin::NegY));
|
||||||
|
|
||||||
str_json = "\"-x\"".to_string();
|
str_json = "\"-x\"".to_string();
|
||||||
let data: RevolveAxis = serde_json::from_str(&str_json).unwrap();
|
let data: AxisOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||||
assert_eq!(data, RevolveAxis::Axis(RevolveAxisAndOrigin::NegX));
|
assert_eq!(data, AxisOrEdgeReference::Axis(AxisAndOrigin::NegX));
|
||||||
|
|
||||||
let data = RevolveAxis::Axis(RevolveAxisAndOrigin::Custom {
|
let data = AxisOrEdgeReference::Axis(AxisAndOrigin::Custom {
|
||||||
axis: [0.0, -1.0, 0.0],
|
axis: [0.0, -1.0],
|
||||||
origin: [1.0, 0.0, 2.0],
|
origin: [1.0, 0.0],
|
||||||
});
|
});
|
||||||
str_json = serde_json::to_string(&data).unwrap();
|
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]}}"#);
|
assert_eq!(str_json, r#"{"custom":{"axis":[0.0,-1.0],"origin":[1.0,0.0]}}"#);
|
||||||
|
|
||||||
str_json = r#"{"custom": {"axis": [0,-1,0], "origin": [1,0,2.0]}}"#.to_string();
|
str_json = r#"{"custom": {"axis": [0,-1], "origin": [1,2.0]}}"#.to_string();
|
||||||
let data: RevolveAxis = serde_json::from_str(&str_json).unwrap();
|
let data: AxisOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data,
|
data,
|
||||||
RevolveAxis::Axis(RevolveAxisAndOrigin::Custom {
|
AxisOrEdgeReference::Axis(AxisAndOrigin::Custom {
|
||||||
axis: [0.0, -1.0, 0.0],
|
axis: [0.0, -1.0],
|
||||||
origin: [1.0, 0.0, 2.0]
|
origin: [1.0, 2.0]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
@ -1012,7 +1012,7 @@ async fn kcl_test_simple_revolve_custom_axis() {
|
|||||||
|> line([0, -5.5], %)
|
|> line([0, -5.5], %)
|
||||||
|> line([-2, 0], %)
|
|> line([-2, 0], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> revolve({axis: {custom: {axis: [0, -1, 0], origin: [0,0,0]}}, angle: 180}, %)
|
|> revolve({axis: {custom: {axis: [0, -1], origin: [0,0]}}, angle: 180}, %)
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|