replace tanArc(to) with tanArcToRelative (#3729)
* replace tanArc(to) with tanArcToRelative Closes #3319 * Handle invalid tanArcs
This commit is contained in:
@ -88,6 +88,7 @@ layout: manual
|
|||||||
* [`tan`](kcl/tan)
|
* [`tan`](kcl/tan)
|
||||||
* [`tangentialArc`](kcl/tangentialArc)
|
* [`tangentialArc`](kcl/tangentialArc)
|
||||||
* [`tangentialArcTo`](kcl/tangentialArcTo)
|
* [`tangentialArcTo`](kcl/tangentialArcTo)
|
||||||
|
* [`tangentialArcToRelative`](kcl/tangentialArcToRelative)
|
||||||
* [`tau`](kcl/tau)
|
* [`tau`](kcl/tau)
|
||||||
* [`toDegrees`](kcl/toDegrees)
|
* [`toDegrees`](kcl/toDegrees)
|
||||||
* [`toRadians`](kcl/toRadians)
|
* [`toRadians`](kcl/toRadians)
|
||||||
|
6713
docs/kcl/std.json
6713
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
@ -37,8 +37,7 @@ const example = extrude(10, exampleSketch)
|
|||||||
offset: number,
|
offset: number,
|
||||||
// Radius of the arc. Not to be confused with Raiders of the Lost Ark.
|
// Radius of the arc. Not to be confused with Raiders of the Lost Ark.
|
||||||
radius: number,
|
radius: number,
|
||||||
} |
|
}
|
||||||
[number, number]
|
|
||||||
```
|
```
|
||||||
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
|
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
|
||||||
```js
|
```js
|
||||||
|
863
docs/kcl/tangentialArcToRelative.md
Normal file
863
docs/kcl/tangentialArcToRelative.md
Normal file
File diff suppressed because one or more lines are too long
@ -2573,7 +2573,6 @@ impl ObjectExpression {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
dbg!(&format_items);
|
|
||||||
let end_indent = if is_in_pipe {
|
let end_indent = if is_in_pipe {
|
||||||
options.get_indentation_offset_pipe(indentation_level)
|
options.get_indentation_offset_pipe(indentation_level)
|
||||||
} else {
|
} else {
|
||||||
|
@ -495,6 +495,9 @@ where
|
|||||||
{
|
{
|
||||||
fn from_args(args: &'a Args, i: usize) -> Result<Self, KclError> {
|
fn from_args(args: &'a Args, i: usize) -> Result<Self, KclError> {
|
||||||
let Some(arg) = args.args.get(i) else { return Ok(None) };
|
let Some(arg) = args.args.get(i) else { return Ok(None) };
|
||||||
|
if crate::ast::types::KclNone::from_mem_item(arg).is_some() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
let Some(val) = T::from_mem_item(arg) else {
|
let Some(val) = T::from_mem_item(arg) else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
@ -620,6 +623,7 @@ impl_from_arg_via_json!(crate::std::polar::PolarCoordsData);
|
|||||||
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);
|
||||||
|
impl_from_arg_via_json!(crate::ast::types::KclNone);
|
||||||
impl_from_arg_via_json!(u32);
|
impl_from_arg_via_json!(u32);
|
||||||
impl_from_arg_via_json!(u64);
|
impl_from_arg_via_json!(u64);
|
||||||
impl_from_arg_via_json!(f64);
|
impl_from_arg_via_json!(f64);
|
||||||
|
@ -81,6 +81,7 @@ lazy_static! {
|
|||||||
Box::new(crate::std::sketch::Arc),
|
Box::new(crate::std::sketch::Arc),
|
||||||
Box::new(crate::std::sketch::TangentialArc),
|
Box::new(crate::std::sketch::TangentialArc),
|
||||||
Box::new(crate::std::sketch::TangentialArcTo),
|
Box::new(crate::std::sketch::TangentialArcTo),
|
||||||
|
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::patterns::PatternLinear2D),
|
Box::new(crate::std::patterns::PatternLinear2D),
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
BasePath, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup,
|
BasePath, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup,
|
||||||
SketchGroupSet, SketchSurface, SourceRange, TagEngineInfo, TagIdentifier, UserVal,
|
SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
utils::{
|
utils::{
|
||||||
@ -1634,8 +1634,6 @@ pub enum TangentialArcData {
|
|||||||
/// Offset of the arc, in degrees.
|
/// Offset of the arc, in degrees.
|
||||||
offset: f64,
|
offset: f64,
|
||||||
},
|
},
|
||||||
/// A point where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
|
|
||||||
Point([f64; 2]),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a tangential arc.
|
/// Draw a tangential arc.
|
||||||
@ -1728,13 +1726,6 @@ async fn inner_tangential_arc(
|
|||||||
.await?;
|
.await?;
|
||||||
(center, to.into(), ccw)
|
(center, to.into(), ccw)
|
||||||
}
|
}
|
||||||
TangentialArcData::Point(to) => {
|
|
||||||
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &to)).await?;
|
|
||||||
// TODO: Figure out these calculations.
|
|
||||||
let ccw = false;
|
|
||||||
let center = Point2d { x: 0.0, y: 0.0 };
|
|
||||||
(center, to, ccw)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_path = Path::TangentialArc {
|
let current_path = Path::TangentialArc {
|
||||||
@ -1775,35 +1766,24 @@ fn tan_arc_to(sketch_group: &SketchGroup, to: &[f64; 2]) -> ModelingCmd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn too_few_args(source_range: SourceRange) -> KclError {
|
|
||||||
KclError::Syntax(KclErrorDetails {
|
|
||||||
source_ranges: vec![source_range],
|
|
||||||
message: "too few arguments".to_owned(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_arg<I: Iterator>(it: &mut I, src: SourceRange) -> Result<I::Item, KclError> {
|
|
||||||
it.next().ok_or_else(|| too_few_args(src))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Draw a tangential arc to a specific point.
|
/// Draw a tangential arc to a specific point.
|
||||||
pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
||||||
let src = args.source_range;
|
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
|
super::args::FromArgs::from_args(&args, 0)?;
|
||||||
// Get arguments to function call
|
|
||||||
let mut it = args.args.iter();
|
|
||||||
let to: [f64; 2] = get_arg(&mut it, src)?.get_json()?;
|
|
||||||
let sketch_group: SketchGroup = get_arg(&mut it, src)?.get_json()?;
|
|
||||||
let tag = if let Ok(memory_item) = get_arg(&mut it, src) {
|
|
||||||
memory_item.get_json_opt()?
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_sketch_group = inner_tangential_arc_to(to, sketch_group, tag, args).await?;
|
let new_sketch_group = inner_tangential_arc_to(to, sketch_group, tag, args).await?;
|
||||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw a tangential arc to point some distance away..
|
||||||
|
pub async fn tangential_arc_to_relative(args: Args) -> Result<KclValue, KclError> {
|
||||||
|
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
|
super::args::FromArgs::from_args(&args, 0)?;
|
||||||
|
|
||||||
|
let new_sketch_group = inner_tangential_arc_to_relative(delta, sketch_group, tag, args).await?;
|
||||||
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
|
}
|
||||||
|
|
||||||
/// Starting at the current sketch's origin, draw a curved line segment along
|
/// Starting at the current sketch's origin, draw a curved line segment along
|
||||||
/// some part of an imaginary circle until it reaches the desired (x, y)
|
/// some part of an imaginary circle until it reaches the desired (x, y)
|
||||||
/// coordinates.
|
/// coordinates.
|
||||||
@ -1873,6 +1853,90 @@ async fn inner_tangential_arc_to(
|
|||||||
Ok(new_sketch_group)
|
Ok(new_sketch_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starting at the current sketch's origin, draw a curved line segment along
|
||||||
|
/// some part of an imaginary circle until it reaches a point the given (x, y)
|
||||||
|
/// distance away.
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// const exampleSketch = startSketchOn('XZ')
|
||||||
|
/// |> startProfileAt([0, 0], %)
|
||||||
|
/// |> angledLine({
|
||||||
|
/// angle: 45,
|
||||||
|
/// length: 10,
|
||||||
|
/// }, %)
|
||||||
|
/// |> tangentialArcToRelative([0, -10], %)
|
||||||
|
/// |> line([-10, 0], %)
|
||||||
|
/// |> close(%)
|
||||||
|
///
|
||||||
|
/// const example = extrude(10, exampleSketch)
|
||||||
|
/// ```
|
||||||
|
#[stdlib {
|
||||||
|
name = "tangentialArcToRelative",
|
||||||
|
}]
|
||||||
|
async fn inner_tangential_arc_to_relative(
|
||||||
|
delta: [f64; 2],
|
||||||
|
sketch_group: SketchGroup,
|
||||||
|
tag: Option<TagDeclarator>,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<SketchGroup, KclError> {
|
||||||
|
let from: Point2d = sketch_group.current_pen_position()?;
|
||||||
|
let tangent_info = sketch_group.get_tangential_info_from_paths();
|
||||||
|
let tan_previous_point = if tangent_info.is_center {
|
||||||
|
get_tangent_point_from_previous_arc(tangent_info.center_or_tangent_point, tangent_info.ccw, from.into())
|
||||||
|
} else {
|
||||||
|
tangent_info.center_or_tangent_point
|
||||||
|
};
|
||||||
|
let [dx, dy] = delta;
|
||||||
|
let result = get_tangential_arc_to_info(TangentialArcInfoInput {
|
||||||
|
arc_start_point: [from.x, from.y],
|
||||||
|
arc_end_point: [from.x + dx, from.y + dy],
|
||||||
|
tan_previous_point,
|
||||||
|
obtuse: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if result.center[0].is_infinite() {
|
||||||
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
message:
|
||||||
|
"could not sketch tangential arc, because its center would be infinitely far away in the X direction"
|
||||||
|
.to_owned(),
|
||||||
|
}));
|
||||||
|
} else if result.center[1].is_infinite() {
|
||||||
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
message:
|
||||||
|
"could not sketch tangential arc, because its center would be infinitely far away in the Y direction"
|
||||||
|
.to_owned(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?;
|
||||||
|
|
||||||
|
let current_path = Path::TangentialArcTo {
|
||||||
|
base: BasePath {
|
||||||
|
from: from.into(),
|
||||||
|
to: delta,
|
||||||
|
tag: tag.clone(),
|
||||||
|
geo_meta: GeoMeta {
|
||||||
|
id,
|
||||||
|
metadata: args.source_range.into(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
center: dbg!(result.center),
|
||||||
|
ccw: result.ccw > 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut new_sketch_group = sketch_group.clone();
|
||||||
|
if let Some(tag) = &tag {
|
||||||
|
new_sketch_group.add_tag(tag, ¤t_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_sketch_group.value.push(current_path);
|
||||||
|
|
||||||
|
Ok(new_sketch_group)
|
||||||
|
}
|
||||||
|
|
||||||
/// Data to draw a bezier curve.
|
/// Data to draw a bezier curve.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -9,40 +9,40 @@ let corner_radius = 5.0
|
|||||||
// because your wrist isn't a perfect cylindrical surface
|
// because your wrist isn't a perfect cylindrical surface
|
||||||
let brace_base = startSketchAt([corner_radius, 0])
|
let brace_base = startSketchAt([corner_radius, 0])
|
||||||
|> line([width - corner_radius, 0.0], %)
|
|> line([width - corner_radius, 0.0], %)
|
||||||
|> tangentialArc([corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, corner_radius], %)
|
||||||
|> yLine(25.0 - corner_radius, %)
|
|> yLine(25.0 - corner_radius, %)
|
||||||
|> tangentialArc([-corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|
||||||
|> xLine(-(d_wrist_circumference[0] - (corner_radius * 2)), %)
|
|> xLine(-(d_wrist_circumference[0] - (corner_radius * 2)), %)
|
||||||
|> tangentialArc([-corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|
||||||
|> yLine(length - 25.0 - 23.0 - (corner_radius * 2), %)
|
|> yLine(length - 25.0 - 23.0 - (corner_radius * 2), %)
|
||||||
|> tangentialArc([corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, corner_radius], %)
|
||||||
|> xLine(15.0 - (corner_radius * 2), %)
|
|> xLine(15.0 - (corner_radius * 2), %)
|
||||||
|> tangentialArc([corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, corner_radius], %)
|
||||||
|> yLine(23.0 - corner_radius, %)
|
|> yLine(23.0 - corner_radius, %)
|
||||||
|> tangentialArc([-corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|
||||||
|> xLine(-(hand_thickness + 15.0 + 15.0 - (corner_radius * 2)), %)
|
|> xLine(-(hand_thickness + 15.0 + 15.0 - (corner_radius * 2)), %)
|
||||||
|> tangentialArc([-corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|
||||||
|> yLine(-(23.0 - corner_radius), %)
|
|> yLine(-(23.0 - corner_radius), %)
|
||||||
|> tangentialArc([corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|
||||||
|> xLine(15.0 - (corner_radius * 2), %)
|
|> xLine(15.0 - (corner_radius * 2), %)
|
||||||
|> tangentialArc([corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|
||||||
|> yLine(-(length - 25.0 - 23.0 - (corner_radius * 2)), %)
|
|> yLine(-(length - 25.0 - 23.0 - (corner_radius * 2)), %)
|
||||||
|> tangentialArc([-corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|
||||||
|> xLine(-(d_wrist_circumference[1] + d_wrist_circumference[2] + d_wrist_circumference[3] - hand_thickness - corner_radius), %)
|
|> xLine(-(d_wrist_circumference[1] + d_wrist_circumference[2] + d_wrist_circumference[3] - hand_thickness - corner_radius), %)
|
||||||
|> tangentialArc([-corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|
||||||
|> yLine(-(25.0 - corner_radius), %)
|
|> yLine(-(25.0 - corner_radius), %)
|
||||||
|> tangentialArc([corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
let inner = startSketchAt([0, 0])
|
let inner = startSketchAt([0, 0])
|
||||||
|> xLine(1.0, %)
|
|> xLine(1.0, %)
|
||||||
|> tangentialArc([corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, corner_radius], %)
|
||||||
|> yLine(25.0 - (corner_radius * 2), %)
|
|> yLine(25.0 - (corner_radius * 2), %)
|
||||||
|> tangentialArc([-corner_radius, corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|
||||||
|> xLine(-1.0, %)
|
|> xLine(-1.0, %)
|
||||||
|> tangentialArc([-corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|
||||||
|> yLine(-(25.0 - (corner_radius * 2)), %)
|
|> yLine(-(25.0 - (corner_radius * 2)), %)
|
||||||
|> tangentialArc([corner_radius, -corner_radius], %)
|
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
let final = brace_base
|
let final = brace_base
|
||||||
|
@ -186,7 +186,7 @@ async fn kcl_test_negative_args() {
|
|||||||
async fn kcl_test_basic_tangential_arc_with_point() {
|
async fn kcl_test_basic_tangential_arc_with_point() {
|
||||||
let code = r#"const boxSketch = startSketchAt([0, 0])
|
let code = r#"const boxSketch = startSketchAt([0, 0])
|
||||||
|> line([0, 10], %)
|
|> line([0, 10], %)
|
||||||
|> tangentialArc([-5, 5], %)
|
|> tangentialArcToRelative([-5, 5], %)
|
||||||
|> line([5, -15], %)
|
|> line([5, -15], %)
|
||||||
|> extrude(10, %)
|
|> extrude(10, %)
|
||||||
"#;
|
"#;
|
||||||
@ -715,7 +715,7 @@ async fn kcl_test_error_sketch_on_arc_face() {
|
|||||||
let code = r#"fn cube = (pos, scale) => {
|
let code = r#"fn cube = (pos, scale) => {
|
||||||
const sg = startSketchOn('XY')
|
const sg = startSketchOn('XY')
|
||||||
|> startProfileAt(pos, %)
|
|> startProfileAt(pos, %)
|
||||||
|> tangentialArc([0, scale], %, $here)
|
|> tangentialArcToRelative([0, scale], %, $here)
|
||||||
|> line([scale, 0], %)
|
|> line([scale, 0], %)
|
||||||
|> line([0, -scale], %)
|
|> line([0, -scale], %)
|
||||||
|
|
||||||
@ -739,7 +739,7 @@ const part002 = startSketchOn(part001, part001.sketchGroup.tags.here)
|
|||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.err().unwrap().to_string(),
|
result.err().unwrap().to_string(),
|
||||||
r#"type: KclErrorDetails { source_ranges: [SourceRange([280, 333])], message: "Tag `here` is a non-planar surface" }"#
|
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([94, 139]), SourceRange([222, 238])], message: "could not sketch tangential arc, because its center would be infinitely far away in the X direction" }"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user