Allow same syntax for patterns as mirror revolve (#7054)
* allow named axis for patterns Signed-off-by: Jess Frazelle <github@jessfraz.com> * docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * images Signed-off-by: Jess Frazelle <github@jessfraz.com> * Fix typo Co-authored-by: Jonathan Tran <jonnytran@gmail.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev> Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
@ -156307,7 +156307,11 @@
|
|||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"examples": [
|
"examples": [
|
||||||
[
|
[
|
||||||
"exampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = 1)\n |> patternLinear2d(axis = [1, 0], instances = 7, distance = 4)\n\nexample = extrude(exampleSketch, length = 1)",
|
"// / Pattern using a named axis.\n\n\nexampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = 1)\n |> patternLinear2d(axis = X, instances = 7, distance = 4)\n\nexample = extrude(exampleSketch, length = 1)",
|
||||||
|
false
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"// / Pattern using a raw axis.\n\n\nexampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = 1)\n |> patternLinear2d(axis = [1, 0], instances = 7, distance = 4)\n\nexample = extrude(exampleSketch, length = 1)",
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -165963,7 +165967,11 @@
|
|||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"examples": [
|
"examples": [
|
||||||
[
|
[
|
||||||
"exampleSketch = startSketchOn(XZ)\n |> startProfile(at = [0, 0])\n |> line(end = [0, 2])\n |> line(end = [3, 1])\n |> line(end = [0, -4])\n |> close()\n\nexample = extrude(exampleSketch, length = 1)\n |> patternLinear3d(axis = [1, 0, 1], instances = 7, distance = 6)",
|
"// / Pattern using a named axis.\n\n\nexampleSketch = startSketchOn(XZ)\n |> startProfile(at = [0, 0])\n |> line(end = [0, 2])\n |> line(end = [3, 1])\n |> line(end = [0, -4])\n |> close()\n\nexample = extrude(exampleSketch, length = 1)\n |> patternLinear3d(axis = X, instances = 7, distance = 6)",
|
||||||
|
false
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"// / Pattern using a raw axis.\n\n\nexampleSketch = startSketchOn(XZ)\n |> startProfile(at = [0, 0])\n |> line(end = [0, 2])\n |> line(end = [3, 1])\n |> line(end = [0, -4])\n |> close()\n\nexample = extrude(exampleSketch, length = 1)\n |> patternLinear3d(axis = [1, 0, 1], instances = 7, distance = 6)",
|
||||||
false
|
false
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -1283,6 +1283,32 @@ impl<'a> FromKclValue<'a> for super::axis_or_reference::Axis3dOrEdgeReference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> FromKclValue<'a> for super::axis_or_reference::Axis2dOrPoint2d {
|
||||||
|
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||||
|
let case1 = |arg: &KclValue| {
|
||||||
|
let obj = arg.as_object()?;
|
||||||
|
let_field_of!(obj, direction);
|
||||||
|
let_field_of!(obj, origin);
|
||||||
|
Some(Self::Axis { direction, origin })
|
||||||
|
};
|
||||||
|
let case2 = <[TyF64; 2]>::from_kcl_val;
|
||||||
|
case1(arg).or_else(|| case2(arg).map(Self::Point))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromKclValue<'a> for super::axis_or_reference::Axis3dOrPoint3d {
|
||||||
|
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||||
|
let case1 = |arg: &KclValue| {
|
||||||
|
let obj = arg.as_object()?;
|
||||||
|
let_field_of!(obj, direction);
|
||||||
|
let_field_of!(obj, origin);
|
||||||
|
Some(Self::Axis { direction, origin })
|
||||||
|
};
|
||||||
|
let case2 = <[TyF64; 3]>::from_kcl_val;
|
||||||
|
case1(arg).or_else(|| case2(arg).map(Self::Point))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> FromKclValue<'a> for i64 {
|
impl<'a> FromKclValue<'a> for i64 {
|
||||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||||
match arg {
|
match arg {
|
||||||
|
@ -21,3 +21,41 @@ pub enum Axis3dOrEdgeReference {
|
|||||||
/// Tagged edge.
|
/// Tagged edge.
|
||||||
Edge(EdgeReference),
|
Edge(EdgeReference),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A 2D axis or a raw point2d.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Axis2dOrPoint2d {
|
||||||
|
/// 2D axis and origin.
|
||||||
|
Axis { direction: [TyF64; 2], origin: [TyF64; 2] },
|
||||||
|
/// Raw point2d.
|
||||||
|
Point([TyF64; 2]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Axis2dOrPoint2d {
|
||||||
|
/// Convert to a 2D axis.
|
||||||
|
pub fn to_point2d(&self) -> [TyF64; 2] {
|
||||||
|
match self {
|
||||||
|
Axis2dOrPoint2d::Axis { direction, origin: _ } => direction.clone(),
|
||||||
|
Axis2dOrPoint2d::Point(point) => point.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A 3D axis or a raw point3d.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Axis3dOrPoint3d {
|
||||||
|
/// 3D axis and origin.
|
||||||
|
Axis { direction: [TyF64; 3], origin: [TyF64; 3] },
|
||||||
|
/// Raw point3d.
|
||||||
|
Point([TyF64; 3]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Axis3dOrPoint3d {
|
||||||
|
/// Convert to a 3D axis.
|
||||||
|
pub fn to_point3d(&self) -> [TyF64; 3] {
|
||||||
|
match self {
|
||||||
|
Axis3dOrPoint3d::Axis { direction, origin: _ } => direction.clone(),
|
||||||
|
Axis3dOrPoint3d::Point(point) => point.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,7 +17,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Mirror a sketch.
|
/// Mirror a sketch.
|
||||||
///
|
|
||||||
pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||||
let axis = args.get_kw_arg_typed(
|
let axis = args.get_kw_arg_typed(
|
||||||
@ -34,7 +33,6 @@ pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Mirror a sketch.
|
/// Mirror a sketch.
|
||||||
///
|
|
||||||
async fn inner_mirror_2d(
|
async fn inner_mirror_2d(
|
||||||
sketches: Vec<Sketch>,
|
sketches: Vec<Sketch>,
|
||||||
axis: Axis2dOrEdgeReference,
|
axis: Axis2dOrEdgeReference,
|
||||||
|
@ -15,21 +15,24 @@ use kittycad_modeling_cmds::{
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
|
||||||
args::{Arg, KwArgs},
|
|
||||||
utils::{point_3d_to_mm, point_to_mm},
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
kcl_value::FunctionSource,
|
kcl_value::FunctionSource,
|
||||||
types::{NumericType, RuntimeType},
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
ExecState, Geometries, Geometry, KclObjectFields, KclValue, Sketch, Solid,
|
ExecState, Geometries, Geometry, KclObjectFields, KclValue, Sketch, Solid,
|
||||||
},
|
},
|
||||||
std::{args::TyF64, Args},
|
std::{
|
||||||
|
args::{Arg, KwArgs, TyF64},
|
||||||
|
axis_or_reference::Axis2dOrPoint2d,
|
||||||
|
utils::{point_3d_to_mm, point_to_mm},
|
||||||
|
Args,
|
||||||
|
},
|
||||||
ExecutorContext, SourceRange,
|
ExecutorContext, SourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::axis_or_reference::Axis3dOrPoint3d;
|
||||||
|
|
||||||
const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your geometry";
|
const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your geometry";
|
||||||
|
|
||||||
/// Repeat some 3D solid, changing each repetition slightly.
|
/// Repeat some 3D solid, changing each repetition slightly.
|
||||||
@ -742,9 +745,17 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
|
|||||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||||
let instances: u32 = args.get_kw_arg("instances")?;
|
let instances: u32 = args.get_kw_arg("instances")?;
|
||||||
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
||||||
let axis: [TyF64; 2] = args.get_kw_arg_typed("axis", &RuntimeType::point2d(), exec_state)?;
|
let axis: Axis2dOrPoint2d = args.get_kw_arg_typed(
|
||||||
|
"axis",
|
||||||
|
&RuntimeType::Union(vec![
|
||||||
|
RuntimeType::Primitive(PrimitiveType::Axis2d),
|
||||||
|
RuntimeType::point2d(),
|
||||||
|
]),
|
||||||
|
exec_state,
|
||||||
|
)?;
|
||||||
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?;
|
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?;
|
||||||
|
|
||||||
|
let axis = axis.to_point2d();
|
||||||
if axis[0].n == 0.0 && axis[1].n == 0.0 {
|
if axis[0].n == 0.0 && axis[1].n == 0.0 {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message:
|
message:
|
||||||
@ -762,6 +773,22 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
|
|||||||
/// of distance between each repetition, some specified number of times.
|
/// of distance between each repetition, some specified number of times.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
/// /// Pattern using a named axis.
|
||||||
|
///
|
||||||
|
/// exampleSketch = startSketchOn(XZ)
|
||||||
|
/// |> circle(center = [0, 0], radius = 1)
|
||||||
|
/// |> patternLinear2d(
|
||||||
|
/// axis = X,
|
||||||
|
/// instances = 7,
|
||||||
|
/// distance = 4
|
||||||
|
/// )
|
||||||
|
///
|
||||||
|
/// example = extrude(exampleSketch, length = 1)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// /// Pattern using a raw axis.
|
||||||
|
///
|
||||||
/// exampleSketch = startSketchOn(XZ)
|
/// exampleSketch = startSketchOn(XZ)
|
||||||
/// |> circle(center = [0, 0], radius = 1)
|
/// |> circle(center = [0, 0], radius = 1)
|
||||||
/// |> patternLinear2d(
|
/// |> patternLinear2d(
|
||||||
@ -821,9 +848,17 @@ pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result
|
|||||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||||
let instances: u32 = args.get_kw_arg("instances")?;
|
let instances: u32 = args.get_kw_arg("instances")?;
|
||||||
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
||||||
let axis: [TyF64; 3] = args.get_kw_arg_typed("axis", &RuntimeType::point3d(), exec_state)?;
|
let axis: Axis3dOrPoint3d = args.get_kw_arg_typed(
|
||||||
|
"axis",
|
||||||
|
&RuntimeType::Union(vec![
|
||||||
|
RuntimeType::Primitive(PrimitiveType::Axis3d),
|
||||||
|
RuntimeType::point3d(),
|
||||||
|
]),
|
||||||
|
exec_state,
|
||||||
|
)?;
|
||||||
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?;
|
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?;
|
||||||
|
|
||||||
|
let axis = axis.to_point3d();
|
||||||
if axis[0].n == 0.0 && axis[1].n == 0.0 && axis[2].n == 0.0 {
|
if axis[0].n == 0.0 && axis[1].n == 0.0 && axis[2].n == 0.0 {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message:
|
message:
|
||||||
@ -841,6 +876,26 @@ pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result
|
|||||||
/// of distance between each repetition, some specified number of times.
|
/// of distance between each repetition, some specified number of times.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
/// /// Pattern using a named axis.
|
||||||
|
///
|
||||||
|
/// exampleSketch = startSketchOn(XZ)
|
||||||
|
/// |> startProfile(at = [0, 0])
|
||||||
|
/// |> line(end = [0, 2])
|
||||||
|
/// |> line(end = [3, 1])
|
||||||
|
/// |> line(end = [0, -4])
|
||||||
|
/// |> close()
|
||||||
|
///
|
||||||
|
/// example = extrude(exampleSketch, length = 1)
|
||||||
|
/// |> patternLinear3d(
|
||||||
|
/// axis = X,
|
||||||
|
/// instances = 7,
|
||||||
|
/// distance = 6
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// /// Pattern using a raw axis.
|
||||||
|
///
|
||||||
/// exampleSketch = startSketchOn(XZ)
|
/// exampleSketch = startSketchOn(XZ)
|
||||||
/// |> startProfile(at = [0, 0])
|
/// |> startProfile(at = [0, 0])
|
||||||
/// |> line(end = [0, 2])
|
/// |> line(end = [0, 2])
|
||||||
|
After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 52 KiB |