Add 'relative: bool' to tanArcTo, remove 'to' mode from tanArc

This commit is contained in:
Adam Chalmers
2024-08-07 19:33:33 -05:00
parent 36a6b8c0ea
commit 06c0d411f9
12 changed files with 73 additions and 81 deletions

View File

@ -217149,8 +217149,8 @@
}, },
{ {
"name": "tangentialArc", "name": "tangentialArc",
"summary": "Starting at the current sketch's origin, draw a curved line segment along", "summary": "Draw a curved line segment along some part of an imaginary circle of the specified radius.",
"description": "some part of an imaginary circle of the specified radius.\nThe arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'offset' degrees along the imaginary circle.", "description": "If `relative` is true, the curve starts at the end of the previous path segment (i.e. the location of the \"pen\" which draws these lines). If `relative` is false, starts from the current sketch's origin.\nThe arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'offset' degrees along the imaginary circle.",
"tags": [], "tags": [],
"args": [ "args": [
{ {
@ -217177,16 +217177,6 @@
"format": "double" "format": "double"
} }
} }
},
{
"description": "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.",
"type": "array",
"items": {
"type": "number",
"format": "double"
},
"maxItems": 2,
"minItems": 2
} }
] ]
}, },
@ -223895,6 +223885,14 @@
}, },
"required": true "required": true
}, },
{
"name": "relative",
"type": "bool",
"schema": {
"type": "boolean"
},
"required": true
},
{ {
"name": "sketch_group", "name": "sketch_group",
"type": "SketchGroup", "type": "SketchGroup",
@ -230575,7 +230573,7 @@
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": false,
"examples": [ "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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -812,6 +812,7 @@ export const tangentialArcTo: SketchLineHelper = {
} }
const newLine = createCallExpression('tangentialArcTo', [ const newLine = createCallExpression('tangentialArcTo', [
createArrayExpression([toX, toY]), createArrayExpression([toX, toY]),
createLiteral(false),
createPipeSubstitution(), createPipeSubstitution(),
]) ])
if (pipe.type === 'PipeExpression') { if (pipe.type === 'PipeExpression') {

View File

@ -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::{
@ -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. /// 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, relative, sketch_group, tag): ([f64; 2], bool, SketchGroup, Option<TagDeclarator>) =
super::args::FromArgs::from_args(&args, 0)?;
// Get arguments to function call let new_sketch_group = inner_tangential_arc_to(to, relative, sketch_group, tag, args).await?;
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?;
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))
} }
@ -1826,6 +1806,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
}] }]
async fn inner_tangential_arc_to( async fn inner_tangential_arc_to(
to: [f64; 2], to: [f64; 2],
relative: bool,
sketch_group: SketchGroup, sketch_group: SketchGroup,
tag: Option<TagDeclarator>, tag: Option<TagDeclarator>,
args: Args, args: Args,
@ -1840,12 +1821,20 @@ async fn inner_tangential_arc_to(
let [to_x, to_y] = to; let [to_x, to_y] = to;
let result = get_tangential_arc_to_info(TangentialArcInfoInput { let result = get_tangential_arc_to_info(TangentialArcInfoInput {
arc_start_point: [from.x, from.y], 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, tan_previous_point,
obtuse: true, 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(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?; 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. /// Structure to hold the output data from calculating tangential arc information.
#[derive(Debug)]
pub struct TangentialArcInfoOutput { pub struct TangentialArcInfoOutput {
/// The center point of the arc. /// The center point of the arc.
pub center: Coords2d, pub center: Coords2d,

View File

@ -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], %) |> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(25.0 - corner_radius, %) |> yLine(25.0 - corner_radius, %)
|> tangentialArc([-corner_radius, corner_radius], %) |> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> xLine(-(d_wrist_circumference[0] - (corner_radius * 2)), %) |> 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), %) |> 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), %) |> xLine(15.0 - (corner_radius * 2), %)
|> tangentialArc([corner_radius, corner_radius], %) |> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(23.0 - corner_radius, %) |> 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)), %) |> 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), %) |> yLine(-(23.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %) |> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> xLine(15.0 - (corner_radius * 2), %) |> 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)), %) |> 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), %) |> 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), %) |> yLine(-(25.0 - corner_radius), %)
|> tangentialArc([corner_radius, -corner_radius], %) |> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> close(%) |> close(%)
let inner = startSketchAt([0, 0]) let inner = startSketchAt([0, 0])
|> xLine(1.0, %) |> xLine(1.0, %)
|> tangentialArc([corner_radius, corner_radius], %) |> tangentialArcTo([corner_radius, corner_radius], true, %)
|> yLine(25.0 - (corner_radius * 2), %) |> yLine(25.0 - (corner_radius * 2), %)
|> tangentialArc([-corner_radius, corner_radius], %) |> tangentialArcTo([-corner_radius, corner_radius], true, %)
|> xLine(-1.0, %) |> xLine(-1.0, %)
|> tangentialArc([-corner_radius, -corner_radius], %) |> tangentialArcTo([-corner_radius, -corner_radius], true, %)
|> yLine(-(25.0 - (corner_radius * 2)), %) |> yLine(-(25.0 - (corner_radius * 2)), %)
|> tangentialArc([corner_radius, -corner_radius], %) |> tangentialArcTo([corner_radius, -corner_radius], true, %)
|> close(%) |> close(%)
let final = brace_base 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() { 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], %) |> tangentialArcTo([-5, 5], true, %)
|> line([5, -15], %) |> line([5, -15], %)
|> extrude(10, %) |> extrude(10, %)
"#; "#;
@ -199,7 +199,7 @@ async fn kcl_test_basic_tangential_arc_with_point() {
async fn kcl_test_basic_tangential_arc_to() { async fn kcl_test_basic_tangential_arc_to() {
let code = r#"const boxSketch = startSketchAt([0, 0]) let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %) |> line([0, 10], %)
|> tangentialArcTo([-5, 15], %) |> tangentialArcTo([-5, 15], false, %)
|> line([5, -15], %) |> line([5, -15], %)
|> extrude(10, %) |> extrude(10, %)
"#; "#;
@ -332,7 +332,7 @@ const thing = other_circle([2, 2], 20)
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn kcl_test_rounded_with_holes() { async fn kcl_test_rounded_with_holes() {
let code = r#"fn tarc = (to, sketchGroup, tag?) => { 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) => { 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([190.03, -118.13], %)
|> line([-33.38, -202.86], %) |> line([-33.38, -202.86], %)
|> line([-315.86, -64.2], %) |> line([-315.86, -64.2], %)
|> tangentialArcTo([-147.66, 121.34], %) |> tangentialArcTo([-147.66, 121.34], false, %)
|> close(%) |> close(%)
|> extrude(100, %) |> extrude(100, %)