Compare commits

...

12 Commits

20 changed files with 85 additions and 78 deletions

View File

@ -223895,6 +223895,14 @@
},
"required": true
},
{
"name": "relative",
"type": "bool",
"schema": {
"type": "boolean"
},
"required": true
},
{
"name": "sketch_group",
"type": "SketchGroup",
@ -230575,7 +230583,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArcTo([15, 15], %)\n |> line([10, -15], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArcTo([15, 15], false, %)\n |> line([10, -15], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{

View File

@ -9,7 +9,7 @@ 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.
```js
tangentialArcTo(to: [number], sketch_group: SketchGroup, tag?: TagDeclarator) -> SketchGroup
tangentialArcTo(to: [number], relative: bool, sketch_group: SketchGroup, tag?: TagDeclarator) -> SketchGroup
```
### Examples
@ -18,7 +18,7 @@ tangentialArcTo(to: [number], sketch_group: SketchGroup, tag?: TagDeclarator) ->
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 60, length: 10 }, %)
|> tangentialArcTo([15, 15], %)
|> tangentialArcTo([15, 15], false, %)
|> line([10, -15], %)
|> close(%)
@ -30,6 +30,7 @@ const example = extrude(10, exampleSketch)
### Arguments
* `to`: `[number]` (REQUIRED)
* `relative`: `bool` (REQUIRED)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{

View File

@ -594,7 +594,7 @@ test.describe(
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
code += `
|> tangentialArcTo([21.7, -2.44], %)`
|> tangentialArcTo([21.7, -2.44], false, %)`
await expect(u.codeLocator).toHaveText(code)
// click tangential arc tool again to unequip it
@ -697,7 +697,7 @@ test.describe(
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
code += `
|> tangentialArcTo([551.2, -62.01], %)`
|> tangentialArcTo([551.2, -62.01], false, %)`
await expect(u.codeLocator).toHaveText(code)
await page

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -84,7 +84,7 @@ export const TEST_CODE_GIZMO = `const part001 = startSketchOn('XZ')
intersectTag: a,
offset: 0
}, %)
|> tangentialArcTo([13.14 + 0, 13.14], %)
|> tangentialArcTo([13.14 + 0, 13.14], false, %)
|> close(%)
|> extrude(5 + 7, %)
`

View File

@ -200,7 +200,7 @@ test.describe('Testing segment overlays', () => {
intersectTag: a,
offset: 9
}, %)
|> tangentialArcTo([5 + 3.14 + 13, 20 + 3.14], %)
|> tangentialArcTo([5 + 3.14 + 13, 20 + 3.14], false, %)
`
)
})
@ -438,7 +438,7 @@ const part001 = startSketchOn('XZ')
intersectTag: a,
offset: 9
}, %)
|> tangentialArcTo([3.14 + 13, 3.14], %)
|> tangentialArcTo([3.14 + 13, 3.14], false, %)
`
)
localStorage.setItem('disableAxis', 'true')
@ -566,7 +566,7 @@ const part001 = startSketchOn('XZ')
intersectTag: a,
offset: 9
}, %)
|> tangentialArcTo([3.14 + 13, 1.14], %)
|> tangentialArcTo([3.14 + 13, 1.14], false, %)
`
)
localStorage.setItem('disableAxis', 'true')
@ -722,7 +722,7 @@ const part001 = startSketchOn('XZ')
intersectTag: a,
offset: 9
}, %)
|> tangentialArcTo([3.14 + 13, -3.14], %)
|> tangentialArcTo([3.14 + 13, -3.14], false, %)
`
)
localStorage.setItem('disableAxis', 'true')
@ -755,9 +755,10 @@ const part001 = startSketchOn('XZ')
await clickConstrained({
hoverPos: { x: tangentialArcTo.x, y: tangentialArcTo.y },
constraintType: 'xAbsolute',
expectBeforeUnconstrained: 'tangentialArcTo([3.14 + 13, -3.14], %)',
expectAfterUnconstrained: 'tangentialArcTo([16.14, -3.14], %)',
expectFinal: 'tangentialArcTo([xAbs001, -3.14], %)',
expectBeforeUnconstrained:
'tangentialArcTo([3.14 + 13, -3.14], false, %)',
expectAfterUnconstrained: 'tangentialArcTo([16.14, -3.14], false, %)',
expectFinal: 'tangentialArcTo([xAbs001, -3.14], false, %)',
ang: ang + 180,
steps: 6,
locator: '[data-overlay-toolbar-index="12"]',
@ -766,9 +767,11 @@ const part001 = startSketchOn('XZ')
await clickUnconstrained({
hoverPos: { x: tangentialArcTo.x, y: tangentialArcTo.y },
constraintType: 'yAbsolute',
expectBeforeUnconstrained: 'tangentialArcTo([xAbs001, -3.14], %)',
expectAfterUnconstrained: 'tangentialArcTo([xAbs001, yAbs001], %)',
expectFinal: 'tangentialArcTo([xAbs001, -3.14], %)',
expectBeforeUnconstrained:
'tangentialArcTo([xAbs001, -3.14], false, %)',
expectAfterUnconstrained:
'tangentialArcTo([xAbs001, yAbs001], false, %)',
expectFinal: 'tangentialArcTo([xAbs001, -3.14], false, %)',
ang: ang + 180,
steps: 10,
locator: '[data-overlay-toolbar-index="12"]',
@ -835,7 +838,7 @@ const part001 = startSketchOn('XZ')
intersectTag: a,
offset: 9
}, %)
|> tangentialArcTo([3.14 + 13, 1.14], %)
|> tangentialArcTo([3.14 + 13, 1.14], false, %)
`
)
localStorage.setItem('disableAxis', 'true')
@ -866,7 +869,7 @@ const part001 = startSketchOn('XZ')
let ang = await u.getAngle(`[data-overlay-index="${12}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], %)',
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], false, %)',
stdLibFnName: 'tangentialArcTo',
ang: ang + 180,
steps: 6,

View File

@ -479,7 +479,7 @@ const sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
intersectTag: a,
offset: 0
}, %)
|> tangentialArcTo([13.14 + 0, 13.14], %)
|> tangentialArcTo([13.14 + 0, 13.14], false, %)
|> close(%)
|> extrude(5 + 7, %)
`
@ -683,7 +683,7 @@ const extrude001 = extrude(10, sketch001)`
},
{
pos: [1107, 161],
expectedCode: 'tangentialArcTo([167.95, -28.85], %)',
expectedCode: 'tangentialArcTo([167.95, -28.85], false, %)',
},
] as const
await page.addInitScript(

View File

@ -584,7 +584,7 @@ describe('Testing removeSingleConstraintInfo', () => {
intersectTag: a,
offset: 0 + 0
}, %)
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|> tangentialArcTo([3.14 + 0, 13.14 + 0], false, %)`
test.each([
[' line([3 + 0, 4], %)', 'arrayIndex', 1],
[
@ -626,7 +626,7 @@ describe('Testing removeSingleConstraintInfo', () => {
'objectProperty',
'offset',
],
['tangentialArcTo([3.14 + 0, 13.14], %)', 'arrayIndex', 1],
['tangentialArcTo([3.14 + 0, 13.14], false, %)', 'arrayIndex', 1],
])('stdlib fn: %s', async (expectedFinish, key, value) => {
const ast = parse(code)
if (err(ast)) throw ast

View File

@ -473,7 +473,7 @@ export function splitPathAtPipeExpression(pathToNode: PathToNode): {
return splitPathAtPipeExpression(pathToNode.slice(0, -1))
}
export function createLiteral(value: string | number): Literal {
export function createLiteral(value: string | number | boolean): Literal {
return {
type: 'Literal',
start: 0,

View File

@ -270,7 +270,7 @@ describe('testing getConstraintInfo', () => {
intersectTag: 'a',
offset: 0
}, %)
|> tangentialArcTo([3.14, 13.14], %)`
|> tangentialArcTo([3.14, 13.14], false, %)`
const ast = parse(code)
test.each([
[
@ -629,7 +629,7 @@ describe('testing getConstraintInfo', () => {
intersectTag: 'a',
offset: 0
}, %)
|> tangentialArcTo([3.14, 13.14], %)`
|> tangentialArcTo([3.14, 13.14], false, %)`
const ast = parse(code)
test.each([
[
@ -783,7 +783,7 @@ describe('testing getConstraintInfo', () => {
intersectTag: 'a',
offset: 0 + 0
}, %)
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|> tangentialArcTo([3.14 + 0, 13.14 + 0], false, %)`
const ast = parse(code)
test.each([
[

View File

@ -309,7 +309,7 @@ function singleRawValueHelper(
]
}
function getTag(index = 2): SketchLineHelper['getTag'] {
function getTag(index = 3): SketchLineHelper['getTag'] {
return (callExp: CallExpression) => {
if (callExp.type !== 'CallExpression')
return new Error('Not a CallExpression')
@ -812,6 +812,7 @@ export const tangentialArcTo: SketchLineHelper = {
}
const newLine = createCallExpression('tangentialArcTo', [
createArrayExpression([toX, toY]),
createLiteral(false),
createPipeSubstitution(),
])
if (pipe.type === 'PipeExpression') {
@ -849,8 +850,8 @@ export const tangentialArcTo: SketchLineHelper = {
pathToNode,
}
},
getTag: getTag(),
addTag: addTag(),
getTag: getTag(3),
addTag: addTag(3),
getConstraintInfo: (callExp: CallExpression, code, pathToNode) => {
if (callExp.type !== 'CallExpression') return []
const firstArg = callExp.arguments?.[0]
@ -1860,7 +1861,7 @@ function isAngleLiteral(lineArugement: Expr): boolean {
type addTagFn = (a: AddTagInfo) => { modifiedAst: Program; tag: string } | Error
function addTag(tagIndex = 2): addTagFn {
function addTag(tagIndex = 3): addTagFn {
return ({ node, pathToNode }) => {
const _node = { ...node }
const callExpr = getNodeFromPath<CallExpression>(

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

@ -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::{
@ -1775,32 +1775,12 @@ 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;
let (to, relative, sketch_group, tag): ([f64; 2], bool, 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, relative, sketch_group, tag, args).await?;
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
}
@ -1815,7 +1795,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
/// angle: 60,
/// length: 10,
/// }, %)
/// |> tangentialArcTo([15, 15], %)
/// |> tangentialArcTo([15, 15], false, %)
/// |> line([10, -15], %)
/// |> close(%)
///
@ -1826,6 +1806,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
}]
async fn inner_tangential_arc_to(
to: [f64; 2],
relative: bool,
sketch_group: SketchGroup,
tag: Option<TagDeclarator>,
args: Args,
@ -1840,12 +1821,20 @@ async fn inner_tangential_arc_to(
let [to_x, to_y] = to;
let result = get_tangential_arc_to_info(TangentialArcInfoInput {
arc_start_point: [from.x, from.y],
arc_end_point: to,
arc_end_point: if relative {
[to_x + from.x, to_y + from.y]
} else {
[to_x, to_y]
},
tan_previous_point,
obtuse: true,
});
let delta = [to_x - from.x, to_y - from.y];
let delta = if relative {
[to_x, to_y]
} else {
[to_x - from.x, to_y - from.y]
};
let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?;

View File

@ -563,6 +563,7 @@ pub struct TangentialArcInfoInput {
}
/// Structure to hold the output data from calculating tangential arc information.
#[derive(Debug)]
pub struct TangentialArcInfoOutput {
/// The center point of the arc.
pub center: Coords2d,

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], %)
|> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(25.0 - corner_radius, %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> xLine(-(d_wrist_circumference[0] - (corner_radius * 2)), %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> yLine(length - 25.0 - 23.0 - (corner_radius * 2), %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcTo([corner_radius, corner_radius], true, %)
|> xLine(15.0 - (corner_radius * 2), %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(23.0 - corner_radius, %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> xLine(-(hand_thickness + 15.0 + 15.0 - (corner_radius * 2)), %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcTo([-corner_radius, -corner_radius], true, %)
|> yLine(-(23.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> xLine(15.0 - (corner_radius * 2), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> yLine(-(length - 25.0 - 23.0 - (corner_radius * 2)), %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcTo([-corner_radius, -corner_radius], true, %)
|> xLine(-(d_wrist_circumference[1] + d_wrist_circumference[2] + d_wrist_circumference[3] - hand_thickness - corner_radius), %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcTo([-corner_radius, -corner_radius], true, %)
|> yLine(-(25.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> close(%)
let inner = startSketchAt([0, 0])
|> xLine(1.0, %)
|> tangentialArc([corner_radius, corner_radius], %)
|> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(25.0 - (corner_radius * 2), %)
|> tangentialArc([-corner_radius, corner_radius], %)
|> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> xLine(-1.0, %)
|> tangentialArc([-corner_radius, -corner_radius], %)
|> tangentialArcTo([-corner_radius, -corner_radius], true, %)
|> yLine(-(25.0 - (corner_radius * 2)), %)
|> tangentialArc([corner_radius, -corner_radius], %)
|> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> 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], %)
|> tangentialArcTo([-5, 5], true, %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
@ -199,7 +199,7 @@ async fn kcl_test_basic_tangential_arc_with_point() {
async fn kcl_test_basic_tangential_arc_to() {
let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %)
|> tangentialArcTo([-5, 15], %)
|> tangentialArcTo([-5, 15], false, %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
@ -332,7 +332,7 @@ const thing = other_circle([2, 2], 20)
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_rounded_with_holes() {
let code = r#"fn tarc = (to, sketchGroup, tag?) => {
return tangentialArcTo(to, sketchGroup, tag)
return tangentialArcTo(to, false, sketchGroup, tag)
}
fn roundedRectangle = (pos, w, l, cornerRadius) => {
@ -1341,7 +1341,7 @@ async fn kcl_test_error_empty_start_sketch_on_string() {
|> line([190.03, -118.13], %)
|> line([-33.38, -202.86], %)
|> line([-315.86, -64.2], %)
|> tangentialArcTo([-147.66, 121.34], %)
|> tangentialArcTo([-147.66, 121.34], false, %)
|> close(%)
|> extrude(100, %)
@ -1354,7 +1354,7 @@ const secondSketch = startSketchOn(part001, '')
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([272, 298])], message: "Argument at index 1 was supposed to be type kcl_lib::std::sketch::FaceTag but found string (text)" }"#
r#"semantic: KclErrorDetails { source_ranges: [SourceRange([279, 305])], message: "Argument at index 1 was supposed to be type kcl_lib::std::sketch::FaceTag but found string (text)" }"#
);
}