Move axes to std constants; move helix, revolve, and mirror2d to be declared in KCL (#6105)
Move axes to std constants; move helix, revolve, and mirror2d to be declated in KCL Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -75,7 +75,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// This will work on any solid, including extruded solids, revolved solids, and shelled solids.
|
||||
/// ```no_run
|
||||
/// // Add color to an extruded solid.
|
||||
/// exampleSketch = startSketchOn("XZ")
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(endAbsolute = [10, 0])
|
||||
/// |> line(endAbsolute = [0, 10])
|
||||
@ -89,9 +89,9 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Add color to a revolved solid.
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// sketch001 = startSketchOn(XY)
|
||||
/// |> circle( center = [15, 0], radius = 5 )
|
||||
/// |> revolve( angle = 360, axis = 'y')
|
||||
/// |> revolve( angle = 360, axis = Y)
|
||||
/// |> appearance(
|
||||
/// color = '#ff0000',
|
||||
/// metalness = 90,
|
||||
@ -102,7 +102,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// ```no_run
|
||||
/// // Add color to different solids.
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// return startSketchOn(XY)
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
@ -122,7 +122,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// ```no_run
|
||||
/// // You can set the appearance before or after you shell it will yield the same result.
|
||||
/// // This example shows setting the appearance _after_ the shell.
|
||||
/// firstSketch = startSketchOn('XY')
|
||||
/// firstSketch = startSketchOn(XY)
|
||||
/// |> startProfileAt([-12, 12], %)
|
||||
/// |> line(end = [24, 0])
|
||||
/// |> line(end = [0, -24])
|
||||
@ -145,7 +145,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// ```no_run
|
||||
/// // You can set the appearance before or after you shell it will yield the same result.
|
||||
/// // This example shows setting the appearance _before_ the shell.
|
||||
/// firstSketch = startSketchOn('XY')
|
||||
/// firstSketch = startSketchOn(XY)
|
||||
/// |> startProfileAt([-12, 12], %)
|
||||
/// |> line(end = [24, 0])
|
||||
/// |> line(end = [0, -24])
|
||||
@ -168,7 +168,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// ```no_run
|
||||
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
||||
/// // This example shows _before_ the pattern.
|
||||
/// exampleSketch = startSketchOn('XZ')
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 2])
|
||||
/// |> line(end = [3, 1])
|
||||
@ -191,7 +191,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// ```no_run
|
||||
/// // Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.
|
||||
/// // This example shows _after_ the pattern.
|
||||
/// exampleSketch = startSketchOn('XZ')
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 2])
|
||||
/// |> line(end = [3, 1])
|
||||
@ -213,7 +213,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Color the result of a 2D pattern that was extruded.
|
||||
/// exampleSketch = startSketchOn('XZ')
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfileAt([.5, 25], %)
|
||||
/// |> line(end = [0, 5])
|
||||
/// |> line(end = [-1, 0])
|
||||
@ -238,7 +238,7 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// // Color the result of a sweep.
|
||||
///
|
||||
/// // Create a path for the sweep.
|
||||
/// sweepPath = startSketchOn('XZ')
|
||||
/// sweepPath = startSketchOn(XZ)
|
||||
/// |> startProfileAt([0.05, 0.05], %)
|
||||
/// |> line(end = [0, 7])
|
||||
/// |> tangentialArc({
|
||||
@ -252,13 +252,13 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// }, %)
|
||||
/// |> line(end = [0, 7])
|
||||
///
|
||||
/// pipeHole = startSketchOn('XY')
|
||||
/// pipeHole = startSketchOn(XY)
|
||||
/// |> circle(
|
||||
/// center = [0, 0],
|
||||
/// radius = 1.5,
|
||||
/// )
|
||||
///
|
||||
/// sweepSketch = startSketchOn('XY')
|
||||
/// sweepSketch = startSketchOn(XY)
|
||||
/// |> circle(
|
||||
/// center = [0, 0],
|
||||
/// radius = 2,
|
||||
|
@ -164,6 +164,22 @@ impl Args {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_kw_arg_opt_typed<T>(
|
||||
&self,
|
||||
label: &str,
|
||||
ty: &RuntimeType,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<Option<T>, KclError>
|
||||
where
|
||||
T: for<'a> FromKclValue<'a>,
|
||||
{
|
||||
if self.kw_args.labeled.get(label).is_none() {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
self.get_kw_arg_typed(label, ty, exec_state).map(Some)
|
||||
}
|
||||
|
||||
/// Get a keyword argument. If not set, returns Err.
|
||||
pub(crate) fn get_kw_arg<'a, T>(&'a self, label: &str) -> Result<T, KclError>
|
||||
where
|
||||
@ -685,37 +701,6 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_and_sketches<'a, T>(
|
||||
&'a self,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<(T, Vec<Sketch>), KclError>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + FromArgs<'a>,
|
||||
{
|
||||
let data: T = FromArgs::from_args(self, 0)?;
|
||||
let Some(arg1) = self.args.get(1) else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "Expected one or more sketches for second argument".to_owned(),
|
||||
source_ranges: vec![self.source_range],
|
||||
}));
|
||||
};
|
||||
let sarg = arg1
|
||||
.value
|
||||
.coerce(&RuntimeType::sketches(), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected one or more sketches for second argument, found {}",
|
||||
arg1.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
let sketches = match sarg {
|
||||
KclValue::HomArray { value, .. } => value.iter().map(|v| v.as_sketch().unwrap().clone()).collect(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok((data, sketches))
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_and_sketch_and_tag<'a, T>(
|
||||
&'a self,
|
||||
exec_state: &mut ExecState,
|
||||
@ -1593,50 +1578,6 @@ impl<'a> FromKclValue<'a> for super::sketch::SketchData {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::axis_or_reference::AxisAndOrigin2d {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
// Case 1: predefined planes.
|
||||
if let Some(s) = arg.as_str() {
|
||||
return match s {
|
||||
"X" | "x" => Some(Self::X),
|
||||
"Y" | "y" => Some(Self::Y),
|
||||
"-X" | "-x" => Some(Self::NegX),
|
||||
"-Y" | "-y" => Some(Self::NegY),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
// Case 2: custom planes.
|
||||
let obj = arg.as_object()?;
|
||||
let_field_of!(obj, custom, &KclObjectFields);
|
||||
let_field_of!(custom, origin);
|
||||
let_field_of!(custom, axis);
|
||||
Some(Self::Custom { axis, origin })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::axis_or_reference::AxisAndOrigin3d {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
// Case 1: predefined planes.
|
||||
if let Some(s) = arg.as_str() {
|
||||
return match s {
|
||||
"X" | "x" => Some(Self::X),
|
||||
"Y" | "y" => Some(Self::Y),
|
||||
"Z" | "z" => Some(Self::Z),
|
||||
"-X" | "-x" => Some(Self::NegX),
|
||||
"-Y" | "-y" => Some(Self::NegY),
|
||||
"-Z" | "-z" => Some(Self::NegZ),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
// Case 2: custom planes.
|
||||
let obj = arg.as_object()?;
|
||||
let_field_of!(obj, custom, &KclObjectFields);
|
||||
let_field_of!(custom, origin);
|
||||
let_field_of!(custom, axis);
|
||||
Some(Self::Custom { axis, origin })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::fillet::EdgeReference {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let id = arg.as_uuid().map(Self::Uuid);
|
||||
@ -1647,25 +1588,27 @@ impl<'a> FromKclValue<'a> for super::fillet::EdgeReference {
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::axis_or_reference::Axis2dOrEdgeReference {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let case1 = super::axis_or_reference::AxisAndOrigin2d::from_kcl_val;
|
||||
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 = super::fillet::EdgeReference::from_kcl_val;
|
||||
case1(arg).map(Self::Axis).or_else(|| case2(arg).map(Self::Edge))
|
||||
case1(arg).or_else(|| case2(arg).map(Self::Edge))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::axis_or_reference::Axis3dOrEdgeReference {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let case1 = super::axis_or_reference::AxisAndOrigin3d::from_kcl_val;
|
||||
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 = super::fillet::EdgeReference::from_kcl_val;
|
||||
case1(arg).map(Self::Axis).or_else(|| case2(arg).map(Self::Edge))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::mirror::Mirror2dData {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let obj = arg.as_object()?;
|
||||
let_field_of!(obj, axis);
|
||||
Some(Self { axis })
|
||||
case1(arg).or_else(|| case2(arg).map(Self::Edge))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ async fn call_map_closure(
|
||||
ctxt: &ExecutorContext,
|
||||
) -> Result<KclValue, KclError> {
|
||||
let output = map_fn
|
||||
.call(exec_state, ctxt, vec![Arg::synthetic(input)], source_range)
|
||||
.call(None, exec_state, ctxt, vec![Arg::synthetic(input)], source_range)
|
||||
.await?;
|
||||
let source_ranges = vec![source_range];
|
||||
let output = output.ok_or_else(|| {
|
||||
@ -202,7 +202,9 @@ async fn call_reduce_closure(
|
||||
) -> Result<KclValue, KclError> {
|
||||
// Call the reduce fn for this repetition.
|
||||
let reduce_fn_args = vec![Arg::synthetic(elem), Arg::synthetic(start)];
|
||||
let transform_fn_return = reduce_fn.call(exec_state, ctxt, reduce_fn_args, source_range).await?;
|
||||
let transform_fn_return = reduce_fn
|
||||
.call(None, exec_state, ctxt, reduce_fn_args, source_range)
|
||||
.await?;
|
||||
|
||||
// Unpack the returned transform object.
|
||||
let source_ranges = vec![source_range];
|
||||
|
@ -1,233 +1,21 @@
|
||||
//! Types for referencing an axis or edge.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcmc::length_unit::LengthUnit;
|
||||
use kittycad_modeling_cmds::{self as kcmc};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{errors::KclError, std::fillet::EdgeReference};
|
||||
use crate::std::fillet::EdgeReference;
|
||||
|
||||
/// A 2D axis or tagged edge.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Axis2dOrEdgeReference {
|
||||
/// 2D axis and origin.
|
||||
Axis(AxisAndOrigin2d),
|
||||
Axis { direction: [f64; 2], origin: [f64; 2] },
|
||||
/// Tagged edge.
|
||||
Edge(EdgeReference),
|
||||
}
|
||||
|
||||
/// A 2D axis and origin.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum AxisAndOrigin2d {
|
||||
/// X-axis.
|
||||
#[serde(rename = "X", alias = "x")]
|
||||
X,
|
||||
/// Y-axis.
|
||||
#[serde(rename = "Y", alias = "y")]
|
||||
Y,
|
||||
/// Flip the X-axis.
|
||||
#[serde(rename = "-X", alias = "-x")]
|
||||
NegX,
|
||||
/// Flip the Y-axis.
|
||||
#[serde(rename = "-Y", alias = "-y")]
|
||||
NegY,
|
||||
Custom {
|
||||
/// The axis.
|
||||
axis: [f64; 2],
|
||||
/// The origin.
|
||||
origin: [f64; 2],
|
||||
},
|
||||
}
|
||||
|
||||
impl AxisAndOrigin2d {
|
||||
/// Get the axis and origin.
|
||||
pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
|
||||
let (axis, origin) = match self {
|
||||
AxisAndOrigin2d::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin2d::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin2d::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin2d::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin2d::Custom { axis, origin } => ([axis[0], axis[1], 0.0], [origin[0], origin[1], 0.0]),
|
||||
};
|
||||
|
||||
Ok((
|
||||
kcmc::shared::Point3d {
|
||||
x: axis[0],
|
||||
y: axis[1],
|
||||
z: axis[2],
|
||||
},
|
||||
kcmc::shared::Point3d {
|
||||
x: LengthUnit(origin[0]),
|
||||
y: LengthUnit(origin[1]),
|
||||
z: LengthUnit(origin[2]),
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// A 3D axis or tagged edge.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Axis3dOrEdgeReference {
|
||||
/// 3D axis and origin.
|
||||
Axis(AxisAndOrigin3d),
|
||||
Axis { direction: [f64; 3], origin: [f64; 3] },
|
||||
/// Tagged edge.
|
||||
Edge(EdgeReference),
|
||||
}
|
||||
|
||||
/// A 3D axis and origin.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum AxisAndOrigin3d {
|
||||
/// X-axis.
|
||||
#[serde(rename = "X", alias = "x")]
|
||||
X,
|
||||
/// Y-axis.
|
||||
#[serde(rename = "Y", alias = "y")]
|
||||
Y,
|
||||
/// Z-axis.
|
||||
#[serde(rename = "Z", 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 AxisAndOrigin3d {
|
||||
/// Get the axis and origin.
|
||||
pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
|
||||
let (axis, origin) = match self {
|
||||
AxisAndOrigin3d::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::Z => ([0.0, 0.0, 1.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::NegX => ([-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::NegY => ([0.0, -1.0, 0.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::NegZ => ([0.0, 0.0, -1.0], [0.0, 0.0, 0.0]),
|
||||
AxisAndOrigin3d::Custom { axis, origin } => {
|
||||
([axis[0], axis[1], axis[2]], [origin[0], origin[1], origin[2]])
|
||||
}
|
||||
};
|
||||
|
||||
Ok((
|
||||
kcmc::shared::Point3d {
|
||||
x: axis[0],
|
||||
y: axis[1],
|
||||
z: axis[2],
|
||||
},
|
||||
kcmc::shared::Point3d {
|
||||
x: LengthUnit(origin[0]),
|
||||
y: LengthUnit(origin[1]),
|
||||
z: LengthUnit(origin[2]),
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::std::axis_or_reference::{
|
||||
Axis2dOrEdgeReference, Axis3dOrEdgeReference, AxisAndOrigin2d, AxisAndOrigin3d,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_revolve_axis_2d() {
|
||||
let data = Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::X);
|
||||
let mut str_json = serde_json::to_string(&data).unwrap();
|
||||
assert_eq!(str_json, "\"X\"");
|
||||
|
||||
str_json = "\"Y\"".to_string();
|
||||
let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Y));
|
||||
|
||||
str_json = "\"-Y\"".to_string();
|
||||
let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::NegY));
|
||||
|
||||
str_json = "\"-x\"".to_string();
|
||||
let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::NegX));
|
||||
|
||||
let data = Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Custom {
|
||||
axis: [0.0, -1.0],
|
||||
origin: [1.0, 0.0],
|
||||
});
|
||||
str_json = serde_json::to_string(&data).unwrap();
|
||||
assert_eq!(str_json, r#"{"custom":{"axis":[0.0,-1.0],"origin":[1.0,0.0]}}"#);
|
||||
|
||||
str_json = r#"{"custom": {"axis": [0,-1], "origin": [1,2.0]}}"#.to_string();
|
||||
let data: Axis2dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(
|
||||
data,
|
||||
Axis2dOrEdgeReference::Axis(AxisAndOrigin2d::Custom {
|
||||
axis: [0.0, -1.0],
|
||||
origin: [1.0, 2.0]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_revolve_axis_3d() {
|
||||
let data = Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::X);
|
||||
let mut str_json = serde_json::to_string(&data).unwrap();
|
||||
assert_eq!(str_json, "\"X\"");
|
||||
|
||||
str_json = "\"Y\"".to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Y));
|
||||
|
||||
str_json = "\"Z\"".to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Z));
|
||||
|
||||
str_json = "\"-Y\"".to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegY));
|
||||
|
||||
str_json = "\"-x\"".to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegX));
|
||||
|
||||
str_json = "\"-z\"".to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(data, Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::NegZ));
|
||||
|
||||
let data = Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Custom {
|
||||
axis: [0.0, -1.0, 0.0],
|
||||
origin: [1.0, 0.0, 0.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,0.0]}}"#);
|
||||
|
||||
str_json = r#"{"custom": {"axis": [0,-1,0], "origin": [1,2.0,0]}}"#.to_string();
|
||||
let data: Axis3dOrEdgeReference = serde_json::from_str(&str_json).unwrap();
|
||||
assert_eq!(
|
||||
data,
|
||||
Axis3dOrEdgeReference::Axis(AxisAndOrigin3d::Custom {
|
||||
axis: [0.0, -1.0, 0.0],
|
||||
origin: [1.0, 2.0, 0.0]
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
//! Standard library helices.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_derive_docs::stdlib;
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
||||
|
||||
use crate::{
|
||||
errors::KclError,
|
||||
execution::{ExecState, Helix as HelixValue, KclValue, Solid},
|
||||
execution::{
|
||||
types::{PrimitiveType, RuntimeType},
|
||||
ExecState, Helix as HelixValue, KclValue, Solid,
|
||||
},
|
||||
std::{axis_or_reference::Axis3dOrEdgeReference, Args},
|
||||
};
|
||||
|
||||
@ -17,7 +19,14 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
let revolutions = args.get_kw_arg("revolutions")?;
|
||||
let ccw = args.get_kw_arg_opt("ccw")?;
|
||||
let radius = args.get_kw_arg_opt("radius")?;
|
||||
let axis = args.get_kw_arg_opt("axis")?;
|
||||
let axis: Option<Axis3dOrEdgeReference> = args.get_kw_arg_opt_typed(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
RuntimeType::Primitive(PrimitiveType::Axis3d),
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let length = args.get_kw_arg_opt("length")?;
|
||||
let cylinder = args.get_kw_arg_opt("cylinder")?;
|
||||
|
||||
@ -84,100 +93,6 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
Ok(KclValue::Helix { value })
|
||||
}
|
||||
|
||||
/// Create a helix.
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Create a helix around the Z axis.
|
||||
/// helixPath = helix(
|
||||
/// angleStart = 0,
|
||||
/// ccw = true,
|
||||
/// revolutions = 5,
|
||||
/// length = 10,
|
||||
/// radius = 5,
|
||||
/// axis = 'Z',
|
||||
/// )
|
||||
///
|
||||
///
|
||||
/// // Create a spring by sweeping around the helix path.
|
||||
/// springSketch = startSketchOn('YZ')
|
||||
/// |> circle( center = [0, 0], radius = 0.5)
|
||||
/// |> sweep(path = helixPath)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Create a helix around an edge.
|
||||
/// helper001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 10], tag = $edge001)
|
||||
///
|
||||
/// helixPath = helix(
|
||||
/// angleStart = 0,
|
||||
/// ccw = true,
|
||||
/// revolutions = 5,
|
||||
/// length = 10,
|
||||
/// radius = 5,
|
||||
/// axis = edge001,
|
||||
/// )
|
||||
///
|
||||
/// // Create a spring by sweeping around the helix path.
|
||||
/// springSketch = startSketchOn('XY')
|
||||
/// |> circle( center = [0, 0], radius = 0.5 )
|
||||
/// |> sweep(path = helixPath)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Create a helix around a custom axis.
|
||||
/// helixPath = helix(
|
||||
/// angleStart = 0,
|
||||
/// ccw = true,
|
||||
/// revolutions = 5,
|
||||
/// length = 10,
|
||||
/// radius = 5,
|
||||
/// axis = {
|
||||
/// custom = {
|
||||
/// axis = [0, 0, 1.0],
|
||||
/// origin = [0, 0.25, 0]
|
||||
/// }
|
||||
/// }
|
||||
/// )
|
||||
///
|
||||
/// // Create a spring by sweeping around the helix path.
|
||||
/// springSketch = startSketchOn('XY')
|
||||
/// |> circle( center = [0, 0], radius = 1 )
|
||||
/// |> sweep(path = helixPath)
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Create a helix on a cylinder.
|
||||
///
|
||||
/// part001 = startSketchOn('XY')
|
||||
/// |> circle( center= [5, 5], radius= 10 )
|
||||
/// |> extrude(length = 10)
|
||||
///
|
||||
/// helix(
|
||||
/// angleStart = 0,
|
||||
/// ccw = true,
|
||||
/// revolutions = 16,
|
||||
/// cylinder = part001,
|
||||
/// )
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "helix",
|
||||
keywords = true,
|
||||
unlabeled_first = false,
|
||||
args = {
|
||||
revolutions = { docs = "Number of revolutions."},
|
||||
angle_start = { docs = "Start angle (in degrees)."},
|
||||
ccw = { docs = "Is the helix rotation counter clockwise? The default is `false`.", include_in_snippet = false},
|
||||
radius = { docs = "Radius of the helix.", include_in_snippet = true},
|
||||
axis = { docs = "Axis to use for the helix.", include_in_snippet = true},
|
||||
length = { docs = "Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used.", include_in_snippet = true},
|
||||
cylinder = { docs = "Cylinder to create the helix on.", include_in_snippet = false},
|
||||
},
|
||||
feature_tree_operation = true,
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn inner_helix(
|
||||
revolutions: f64,
|
||||
@ -221,9 +136,7 @@ async fn inner_helix(
|
||||
.await?;
|
||||
} else if let (Some(axis), Some(radius)) = (axis, radius) {
|
||||
match axis {
|
||||
Axis3dOrEdgeReference::Axis(axis) => {
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
|
||||
Axis3dOrEdgeReference::Axis { direction, origin } => {
|
||||
// Make sure they gave us a length.
|
||||
let Some(length) = length else {
|
||||
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
|
||||
@ -240,8 +153,16 @@ async fn inner_helix(
|
||||
length: LengthUnit(length),
|
||||
revolutions,
|
||||
start_angle: Angle::from_degrees(angle_start),
|
||||
axis,
|
||||
center: origin,
|
||||
axis: Point3d {
|
||||
x: direction[0],
|
||||
y: direction[1],
|
||||
z: direction[2],
|
||||
},
|
||||
center: Point3d {
|
||||
x: LengthUnit(origin[0]),
|
||||
y: LengthUnit(origin[1]),
|
||||
z: LengthUnit(origin[2]),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -1,109 +1,39 @@
|
||||
//! Standard library mirror.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_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 kittycad_modeling_cmds::{self as kcmc, length_unit::LengthUnit, shared::Point3d};
|
||||
|
||||
use crate::{
|
||||
errors::KclError,
|
||||
execution::{ExecState, KclValue, Sketch},
|
||||
execution::{
|
||||
types::{PrimitiveType, RuntimeType},
|
||||
ExecState, KclValue, Sketch,
|
||||
},
|
||||
std::{axis_or_reference::Axis2dOrEdgeReference, Args},
|
||||
};
|
||||
|
||||
/// Data for a mirror.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Mirror2dData {
|
||||
/// Axis to use as mirror.
|
||||
pub axis: Axis2dOrEdgeReference,
|
||||
}
|
||||
|
||||
/// 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_set): (Mirror2dData, Vec<Sketch>) = args.get_data_and_sketches(exec_state)?;
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis = args.get_kw_arg_typed(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
RuntimeType::Primitive(PrimitiveType::Axis2d),
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
|
||||
let sketches = inner_mirror_2d(data, sketch_set, exec_state, args).await?;
|
||||
let sketches = inner_mirror_2d(sketches, axis, exec_state, args).await?;
|
||||
Ok(sketches.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.
|
||||
/// sketch001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 10], %)
|
||||
/// |> line(end = [15, 0])
|
||||
/// |> line(end = [-7, -3])
|
||||
/// |> line(end = [9, -1])
|
||||
/// |> line(end = [-8, -5])
|
||||
/// |> line(end = [9, -3])
|
||||
/// |> line(end = [-8, -3])
|
||||
/// |> line(end = [9, -1])
|
||||
/// |> line(end = [-19, -0])
|
||||
/// |> mirror2d({axis = 'Y'}, %)
|
||||
///
|
||||
/// example = extrude(sketch001, length = 10)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Mirror a un-closed sketch across the Y axis.
|
||||
/// sketch001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 8.5], %)
|
||||
/// |> line(end = [20, -8.5])
|
||||
/// |> line(end = [-20, -8.5])
|
||||
/// |> mirror2d({axis = 'Y'}, %)
|
||||
///
|
||||
/// example = extrude(sketch001, length = 10)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Mirror a un-closed sketch across an edge.
|
||||
/// helper001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 10], tag = $edge001)
|
||||
///
|
||||
/// sketch001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 8.5], %)
|
||||
/// |> line(end = [20, -8.5])
|
||||
/// |> line(end = [-20, -8.5])
|
||||
/// |> mirror2d({axis = edge001}, %)
|
||||
///
|
||||
/// // example = extrude(sketch001, length = 10)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Mirror an un-closed sketch across a custom axis.
|
||||
/// sketch001 = startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 8.5], %)
|
||||
/// |> line(end = [20, -8.5])
|
||||
/// |> line(end = [-20, -8.5])
|
||||
/// |> mirror2d({
|
||||
/// axis = {
|
||||
/// custom = {
|
||||
/// axis = [0.0, 1.0],
|
||||
/// origin = [0.0, 0.0]
|
||||
/// }
|
||||
/// }
|
||||
/// }, %)
|
||||
///
|
||||
/// example = extrude(sketch001, length = 10)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "mirror2d",
|
||||
}]
|
||||
async fn inner_mirror_2d(
|
||||
data: Mirror2dData,
|
||||
sketches: Vec<Sketch>,
|
||||
axis: Axis2dOrEdgeReference,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Sketch>, KclError> {
|
||||
@ -113,16 +43,22 @@ async fn inner_mirror_2d(
|
||||
return Ok(starting_sketches);
|
||||
}
|
||||
|
||||
match data.axis {
|
||||
Axis2dOrEdgeReference::Axis(axis) => {
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
|
||||
match axis {
|
||||
Axis2dOrEdgeReference::Axis { direction, origin } => {
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.next_uuid(),
|
||||
ModelingCmd::from(mcmd::EntityMirror {
|
||||
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
|
||||
axis,
|
||||
point: origin,
|
||||
axis: Point3d {
|
||||
x: direction[0],
|
||||
y: direction[1],
|
||||
z: 0.0,
|
||||
},
|
||||
point: Point3d {
|
||||
x: LengthUnit(origin[0]),
|
||||
y: LengthUnit(origin[1]),
|
||||
z: LengthUnit(0.0),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
@ -26,7 +26,6 @@ pub mod shell;
|
||||
pub mod sketch;
|
||||
pub mod sweep;
|
||||
pub mod transform;
|
||||
pub mod types;
|
||||
pub mod units;
|
||||
pub mod utils;
|
||||
|
||||
@ -96,7 +95,6 @@ lazy_static! {
|
||||
Box::new(crate::std::sketch::TangentialArcToRelative),
|
||||
Box::new(crate::std::sketch::BezierCurve),
|
||||
Box::new(crate::std::sketch::Hole),
|
||||
Box::new(crate::std::mirror::Mirror2D),
|
||||
Box::new(crate::std::patterns::PatternLinear2D),
|
||||
Box::new(crate::std::patterns::PatternLinear3D),
|
||||
Box::new(crate::std::patterns::PatternCircular2D),
|
||||
@ -113,10 +111,8 @@ lazy_static! {
|
||||
Box::new(crate::std::edge::GetNextAdjacentEdge),
|
||||
Box::new(crate::std::edge::GetPreviousAdjacentEdge),
|
||||
Box::new(crate::std::edge::GetCommonEdge),
|
||||
Box::new(crate::std::helix::Helix),
|
||||
Box::new(crate::std::shell::Shell),
|
||||
Box::new(crate::std::shell::Hollow),
|
||||
Box::new(crate::std::revolve::Revolve),
|
||||
Box::new(crate::std::sweep::Sweep),
|
||||
Box::new(crate::std::loft::Loft),
|
||||
Box::new(crate::std::planes::OffsetPlane),
|
||||
@ -177,6 +173,7 @@ pub fn get_stdlib_fn(name: &str) -> Option<Box<dyn StdLibFn>> {
|
||||
pub struct StdFnProps {
|
||||
pub name: String,
|
||||
pub deprecated: bool,
|
||||
pub include_in_feature_tree: bool,
|
||||
}
|
||||
|
||||
impl StdFnProps {
|
||||
@ -184,8 +181,14 @@ impl StdFnProps {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
deprecated: false,
|
||||
include_in_feature_tree: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn include_in_feature_tree(mut self) -> Self {
|
||||
self.include_in_feature_tree = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProps) {
|
||||
@ -206,6 +209,18 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
|e, a| Box::pin(crate::std::shapes::circle(e, a)),
|
||||
StdFnProps::default("std::sketch::circle"),
|
||||
),
|
||||
("prelude", "helix") => (
|
||||
|e, a| Box::pin(crate::std::helix::helix(e, a)),
|
||||
StdFnProps::default("std::helix").include_in_feature_tree(),
|
||||
),
|
||||
("sketch", "mirror2d") => (
|
||||
|e, a| Box::pin(crate::std::mirror::mirror_2d(e, a)),
|
||||
StdFnProps::default("std::sketch::mirror2d"),
|
||||
),
|
||||
("prelude", "revolve") => (
|
||||
|e, a| Box::pin(crate::std::revolve::revolve(e, a)),
|
||||
StdFnProps::default("std::revolve").include_in_feature_tree(),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -217,6 +232,9 @@ pub(crate) fn std_ty(path: &str, fn_name: &str) -> (PrimitiveType, StdFnProps) {
|
||||
("prelude", "Plane") => (PrimitiveType::Plane, StdFnProps::default("std::Plane")),
|
||||
("prelude", "Face") => (PrimitiveType::Face, StdFnProps::default("std::Face")),
|
||||
("prelude", "Helix") => (PrimitiveType::Helix, StdFnProps::default("std::Helix")),
|
||||
("prelude", "Edge") => (PrimitiveType::Edge, StdFnProps::default("std::Edge")),
|
||||
("prelude", "Axis2d") => (PrimitiveType::Axis2d, StdFnProps::default("std::Axis2d")),
|
||||
("prelude", "Axis3d") => (PrimitiveType::Axis3d, StdFnProps::default("std::Axis3d")),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +437,7 @@ async fn make_transform<T: GeometryTrait>(
|
||||
};
|
||||
let transform_fn_args = vec![Arg::synthetic(repetition_num)];
|
||||
let transform_fn_return = transform
|
||||
.call(exec_state, ctxt, transform_fn_args, source_range)
|
||||
.call(None, exec_state, ctxt, transform_fn_args, source_range)
|
||||
.await?;
|
||||
|
||||
// Unpack the returned transform object.
|
||||
|
@ -1,14 +1,16 @@
|
||||
//! Standard library revolution surfaces.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_derive_docs::stdlib;
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||
use kittycad_modeling_cmds::{self as kcmc};
|
||||
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
||||
|
||||
use super::DEFAULT_TOLERANCE;
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{types::RuntimeType, ExecState, KclValue, Sketch, Solid},
|
||||
execution::{
|
||||
types::{PrimitiveType, RuntimeType},
|
||||
ExecState, KclValue, Sketch, Solid,
|
||||
},
|
||||
parsing::ast::types::TagNode,
|
||||
std::{axis_or_reference::Axis2dOrEdgeReference, extrude::do_post_extrude, Args},
|
||||
};
|
||||
@ -16,7 +18,14 @@ use crate::{
|
||||
/// Revolve a sketch or set of sketches around an axis.
|
||||
pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis: Axis2dOrEdgeReference = args.get_kw_arg("axis")?;
|
||||
let axis = args.get_kw_arg_typed(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
RuntimeType::Primitive(PrimitiveType::Axis2d),
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let angle = args.get_kw_arg_opt("angle")?;
|
||||
let tolerance = args.get_kw_arg_opt("tolerance")?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
@ -26,215 +35,6 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
Ok(value.into())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Revolve occurs around a local sketch axis rather than a global axis.
|
||||
///
|
||||
/// You can provide more than one sketch to revolve, and they will all be
|
||||
/// revolved around the same axis.
|
||||
///
|
||||
/// ```no_run
|
||||
/// part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([4, 12], %)
|
||||
/// |> line(end = [2, 0])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [4, -6])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [-3.75, -4.5])
|
||||
/// |> line(end = [0, -5.5])
|
||||
/// |> line(end = [-2, 0])
|
||||
/// |> close()
|
||||
/// |> revolve(axis = 'y') // default angle is 360
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // A donut shape.
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// |> circle( center = [15, 0], radius = 5 )
|
||||
/// |> revolve(
|
||||
/// angle = 360,
|
||||
/// axis = 'y'
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([4, 12], %)
|
||||
/// |> line(end = [2, 0])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [4, -6])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [-3.75, -4.5])
|
||||
/// |> line(end = [0, -5.5])
|
||||
/// |> line(end = [-2, 0])
|
||||
/// |> close()
|
||||
/// |> revolve(axis = 'y', angle = 180)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([4, 12], %)
|
||||
/// |> line(end = [2, 0])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [4, -6])
|
||||
/// |> line(end = [0, -6])
|
||||
/// |> line(end = [-3.75, -4.5])
|
||||
/// |> line(end = [0, -5.5])
|
||||
/// |> line(end = [-2, 0])
|
||||
/// |> close()
|
||||
/// |> revolve(axis = 'y', angle = 180)
|
||||
///
|
||||
/// part002 = startSketchOn(part001, 'end')
|
||||
/// |> startProfileAt([4.5, -5], %)
|
||||
/// |> line(end = [0, 5])
|
||||
/// |> line(end = [5, 0])
|
||||
/// |> line(end = [0, -5])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 5)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// box = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20])
|
||||
/// |> line(end = [20, 0])
|
||||
/// |> line(end = [0, -20])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 20)
|
||||
///
|
||||
/// sketch001 = startSketchOn(box, "END")
|
||||
/// |> circle( center = [10,10], radius = 4 )
|
||||
/// |> revolve(
|
||||
/// angle = -90,
|
||||
/// axis = 'y'
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// box = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20])
|
||||
/// |> line(end = [20, 0])
|
||||
/// |> line(end = [0, -20], tag = $revolveAxis)
|
||||
/// |> close()
|
||||
/// |> extrude(length = 20)
|
||||
///
|
||||
/// sketch001 = startSketchOn(box, "END")
|
||||
/// |> circle( center = [10,10], radius = 4 )
|
||||
/// |> revolve(
|
||||
/// angle = 90,
|
||||
/// axis = getOppositeEdge(revolveAxis)
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// box = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20])
|
||||
/// |> line(end = [20, 0])
|
||||
/// |> line(end = [0, -20], tag = $revolveAxis)
|
||||
/// |> close()
|
||||
/// |> extrude(length = 20)
|
||||
///
|
||||
/// sketch001 = startSketchOn(box, "END")
|
||||
/// |> circle( center = [10,10], radius = 4 )
|
||||
/// |> revolve(
|
||||
/// angle = 90,
|
||||
/// axis = getOppositeEdge(revolveAxis),
|
||||
/// tolerance = 0.0001
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([10, 0], %)
|
||||
/// |> line(end = [5, -5])
|
||||
/// |> line(end = [5, 5])
|
||||
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
/// |> close()
|
||||
///
|
||||
/// part001 = revolve(
|
||||
/// sketch001,
|
||||
/// axis = {
|
||||
/// custom: {
|
||||
/// axis = [0.0, 1.0],
|
||||
/// origin: [0.0, 0.0]
|
||||
/// }
|
||||
/// }
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Revolve two sketches around the same axis.
|
||||
///
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// profile001 = startProfileAt([4, 8], sketch001)
|
||||
/// |> xLine(length = 3)
|
||||
/// |> yLine(length = -3)
|
||||
/// |> xLine(length = -3)
|
||||
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
/// |> close()
|
||||
///
|
||||
/// profile002 = startProfileAt([-5, 8], sketch001)
|
||||
/// |> xLine(length = 3)
|
||||
/// |> yLine(length = -3)
|
||||
/// |> xLine(length = -3)
|
||||
/// |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
/// |> close()
|
||||
///
|
||||
/// revolve(
|
||||
/// [profile001, profile002],
|
||||
/// axis = "X",
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Revolve around a path that has not been extruded.
|
||||
///
|
||||
/// profile001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20], tag = $revolveAxis)
|
||||
/// |> line(end = [20, 0])
|
||||
/// |> line(end = [0, -20])
|
||||
/// |> close(%)
|
||||
///
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// |> circle(center = [-10, 10], radius = 4)
|
||||
/// |> revolve(angle = 90, axis = revolveAxis)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Revolve around a path that has not been extruded or closed.
|
||||
///
|
||||
/// profile001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20], tag = $revolveAxis)
|
||||
/// |> line(end = [20, 0])
|
||||
///
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// |> circle(center = [-10, 10], radius = 4)
|
||||
/// |> revolve(angle = 90, axis = revolveAxis)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "revolve",
|
||||
feature_tree_operation = true,
|
||||
keywords = true,
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
sketches = { docs = "The sketch or set of sketches that should be revolved" },
|
||||
axis = { docs = "Axis of revolution." },
|
||||
angle = { docs = "Angle to revolve (in degrees). Default is 360." },
|
||||
tolerance = { docs = "Tolerance for the revolve operation." },
|
||||
tag_start = { docs = "A named tag for the face at the start of the revolve, i.e. the original sketch" },
|
||||
tag_end = { docs = "A named tag for the face at the end of the revolve" },
|
||||
}
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn inner_revolve(
|
||||
sketches: Vec<Sketch>,
|
||||
@ -265,15 +65,22 @@ async fn inner_revolve(
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
match &axis {
|
||||
Axis2dOrEdgeReference::Axis(axis) => {
|
||||
let (axis, origin) = axis.axis_and_origin()?;
|
||||
Axis2dOrEdgeReference::Axis { direction, origin } => {
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::Revolve {
|
||||
angle,
|
||||
target: sketch.id.into(),
|
||||
axis,
|
||||
origin,
|
||||
axis: Point3d {
|
||||
x: direction[0],
|
||||
y: direction[1],
|
||||
z: 0.0,
|
||||
},
|
||||
origin: Point3d {
|
||||
x: LengthUnit(origin[0]),
|
||||
y: LengthUnit(origin[1]),
|
||||
z: LengthUnit(0.0),
|
||||
},
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
axis_is_2d: true,
|
||||
}),
|
||||
|
@ -1021,7 +1021,7 @@ pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<K
|
||||
/// |> line(end = [-2, 0])
|
||||
/// |> close()
|
||||
///
|
||||
/// example = revolve(exampleSketch, axis = 'y', angle = 180)
|
||||
/// example = revolve(exampleSketch, axis = Y, angle = 180)
|
||||
///
|
||||
/// exampleSketch002 = startSketchOn(example, 'end')
|
||||
/// |> startProfileAt([4.5, -5], %)
|
||||
@ -1047,7 +1047,7 @@ pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<K
|
||||
/// |> line(end = [-2, 0])
|
||||
/// |> close()
|
||||
///
|
||||
/// example = revolve(exampleSketch, axis = 'y', angle = 180, tagEnd = $end01)
|
||||
/// example = revolve(exampleSketch, axis = Y, angle = 180, tagEnd = $end01)
|
||||
///
|
||||
/// exampleSketch002 = startSketchOn(example, end01)
|
||||
/// |> startProfileAt([4.5, -5], %)
|
||||
|
@ -55,7 +55,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// // Create a pipe using a sweep.
|
||||
///
|
||||
/// // Create a path for the sweep.
|
||||
/// sweepPath = startSketchOn('XZ')
|
||||
/// sweepPath = startSketchOn(XZ)
|
||||
/// |> startProfileAt([0.05, 0.05], %)
|
||||
/// |> line(end = [0, 7])
|
||||
/// |> tangentialArc({
|
||||
@ -70,13 +70,13 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// |> line(end = [0, 7])
|
||||
///
|
||||
/// // Create a hole for the pipe.
|
||||
/// pipeHole = startSketchOn('XY')
|
||||
/// pipeHole = startSketchOn(XY)
|
||||
/// |> circle(
|
||||
/// center = [0, 0],
|
||||
/// radius = 1.5,
|
||||
/// )
|
||||
///
|
||||
/// sweepSketch = startSketchOn('XY')
|
||||
/// sweepSketch = startSketchOn(XY)
|
||||
/// |> circle(
|
||||
/// center = [0, 0],
|
||||
/// radius = 2,
|
||||
@ -95,12 +95,12 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// revolutions = 4,
|
||||
/// length = 10,
|
||||
/// radius = 5,
|
||||
/// axis = 'Z',
|
||||
/// axis = Z,
|
||||
/// )
|
||||
///
|
||||
///
|
||||
/// // Create a spring by sweeping around the helix path.
|
||||
/// springSketch = startSketchOn('YZ')
|
||||
/// springSketch = startSketchOn(YZ)
|
||||
/// |> circle( center = [0, 0], radius = 1)
|
||||
/// |> sweep(path = helixPath)
|
||||
/// ```
|
||||
@ -108,7 +108,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// ```
|
||||
/// // Sweep two sketches along the same path.
|
||||
///
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// sketch001 = startSketchOn(XY)
|
||||
/// rectangleSketch = startProfileAt([-200, 23.86], sketch001)
|
||||
/// |> angledLine([0, 73.47], %, $rectangleSegmentA001)
|
||||
/// |> angledLine([
|
||||
@ -124,7 +124,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
///
|
||||
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
|
||||
///
|
||||
/// sketch002 = startSketchOn('YZ')
|
||||
/// sketch002 = startSketchOn(YZ)
|
||||
/// sweepPath = startProfileAt([0, 0], sketch002)
|
||||
/// |> yLine(length = 231.81)
|
||||
/// |> tangentialArc({
|
||||
@ -138,7 +138,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// ```
|
||||
/// // Sectionally sweep one sketch along the path
|
||||
///
|
||||
/// sketch001 = startSketchOn('XY')
|
||||
/// sketch001 = startSketchOn(XY)
|
||||
/// circleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)
|
||||
///
|
||||
/// sketch002 = startSketchOn('YZ')
|
||||
|
@ -1 +0,0 @@
|
||||
|
Reference in New Issue
Block a user