replace tanArc(to) with tanArcToRelative (#3729)

* replace tanArc(to) with tanArcToRelative

Closes #3319

* Handle invalid tanArcs
This commit is contained in:
Adam Chalmers
2024-08-30 13:44:20 -05:00
committed by GitHub
parent 403e074249
commit a4cf68c661
11 changed files with 7688 additions and 64 deletions

View File

@ -88,6 +88,7 @@ layout: manual
* [`tan`](kcl/tan)
* [`tangentialArc`](kcl/tangentialArc)
* [`tangentialArcTo`](kcl/tangentialArcTo)
* [`tangentialArcToRelative`](kcl/tangentialArcToRelative)
* [`tau`](kcl/tau)
* [`toDegrees`](kcl/toDegrees)
* [`toRadians`](kcl/toRadians)

File diff suppressed because it is too large Load Diff

View File

@ -37,8 +37,7 @@ const example = extrude(10, exampleSketch)
offset: number,
// Radius of the arc. Not to be confused with Raiders of the Lost Ark.
radius: number,
} |
[number, number]
}
```
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js

File diff suppressed because one or more lines are too long

View File

@ -2573,7 +2573,6 @@ impl ObjectExpression {
}
})
.collect();
dbg!(&format_items);
let end_indent = if is_in_pipe {
options.get_indentation_offset_pipe(indentation_level)
} else {

View File

@ -495,6 +495,9 @@ where
{
fn from_args(args: &'a Args, i: usize) -> Result<Self, KclError> {
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 {
return Err(KclError::Semantic(KclErrorDetails {
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!(FaceTag);
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!(u64);
impl_from_arg_via_json!(f64);

View File

@ -81,6 +81,7 @@ lazy_static! {
Box::new(crate::std::sketch::Arc),
Box::new(crate::std::sketch::TangentialArc),
Box::new(crate::std::sketch::TangentialArcTo),
Box::new(crate::std::sketch::TangentialArcToRelative),
Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::sketch::Hole),
Box::new(crate::std::patterns::PatternLinear2D),

View File

@ -14,7 +14,7 @@ use crate::{
errors::{KclError, KclErrorDetails},
executor::{
BasePath, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, SketchGroup,
SketchGroupSet, SketchSurface, SourceRange, TagEngineInfo, TagIdentifier, UserVal,
SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
},
std::{
utils::{
@ -1634,8 +1634,6 @@ pub enum TangentialArcData {
/// Offset of the arc, in degrees.
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.
@ -1728,13 +1726,6 @@ async fn inner_tangential_arc(
.await?;
(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 {
@ -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.
pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
let src = args.source_range;
// 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 (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
super::args::FromArgs::from_args(&args, 0)?;
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))
}
/// 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
/// some part of an imaginary circle until it reaches the desired (x, y)
/// coordinates.
@ -1873,6 +1853,90 @@ async fn inner_tangential_arc_to(
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, &current_path);
}
new_sketch_group.value.push(current_path);
Ok(new_sketch_group)
}
/// Data to draw a bezier curve.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -9,40 +9,40 @@ let corner_radius = 5.0
// because your wrist isn't a perfect cylindrical surface
let brace_base = startSketchAt([corner_radius, 0])
|> line([width - corner_radius, 0.0], %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcToRelative([corner_radius, 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)), %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|> 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), %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcToRelative([corner_radius, 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)), %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|> yLine(-(23.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|> 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)), %)
|> 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), %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|> yLine(-(25.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|> close(%)
let inner = startSketchAt([0, 0])
|> xLine(1.0, %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcToRelative([corner_radius, corner_radius], %)
|> yLine(25.0 - (corner_radius * 2), %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcToRelative([-corner_radius, corner_radius], %)
|> xLine(-1.0, %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcToRelative([-corner_radius, -corner_radius], %)
|> yLine(-(25.0 - (corner_radius * 2)), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcToRelative([corner_radius, -corner_radius], %)
|> close(%)
let final = brace_base

View File

@ -186,7 +186,7 @@ async fn kcl_test_negative_args() {
async fn kcl_test_basic_tangential_arc_with_point() {
let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %)
|> tangentialArc([-5, 5], %)
|> tangentialArcToRelative([-5, 5], %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
@ -715,7 +715,7 @@ async fn kcl_test_error_sketch_on_arc_face() {
let code = r#"fn cube = (pos, scale) => {
const sg = startSketchOn('XY')
|> startProfileAt(pos, %)
|> tangentialArc([0, scale], %, $here)
|> tangentialArcToRelative([0, scale], %, $here)
|> line([scale, 0], %)
|> line([0, -scale], %)
@ -739,7 +739,7 @@ const part002 = startSketchOn(part001, part001.sketchGroup.tags.here)
assert!(result.is_err());
assert_eq!(
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" }"#
);
}