Compare commits

...

20 Commits

Author SHA1 Message Date
ccaff0b3c6 Rust: migrate arc/arcTo to kwargs 2025-04-14 17:03:47 -05:00
45e906f8c7 Fix order of constraints in unit test 2025-04-14 16:50:27 -04:00
25ec74fc46 Fix e2e test expectation
App was working as expected, but the e2e test was
expecting the old code, not the new code.
2025-04-14 15:36:36 -05:00
05432b2ba4 Fix selections e2e test 2025-04-14 16:21:40 -04:00
699ce799b9 Fix to use labeledArg constraints and use the correct order of args 2025-04-14 16:17:24 -04:00
bb0ba6ed0b Fix adding constraint from UI to work 2025-04-14 15:33:50 -04:00
c1d0d8a762 tiny lint 2025-04-14 14:02:48 -05:00
639f2a583f Fix e2e tests to use new kw args 2025-04-14 14:48:19 -04:00
153da3312b Fix bench test 2025-04-14 14:42:44 -04:00
a91261be3e Fix more unit tests 2025-04-14 14:31:45 -04:00
d40f70ccb9 Fix to not have extra docs 2025-04-14 14:12:55 -04:00
255b88de4f Fix std unit tests 2025-04-14 14:02:26 -04:00
73d7d93a3d Fix sketch unit tests 2025-04-14 14:00:21 -04:00
d135cc7c55 Fix modifyAst unit tests 2025-04-14 13:57:21 -04:00
9cda90144c Fix missing cases 2025-04-14 13:49:51 -04:00
e8c391ea18 Fix tsc and lint errors 2025-04-14 13:38:24 -04:00
10e389bc38 Merge branch 'main' into achalmers/angle-line-intersects 2025-04-14 11:40:08 -05:00
a4f090e49d WIP 2025-04-11 16:16:00 -05:00
5e226b5573 Update KCL tests and samples 2025-04-11 16:15:53 -05:00
5cfeca0f69 KCL: Convert angledLineThatIntersects to use kwargs 2025-04-11 16:13:49 -05:00
26 changed files with 549 additions and 745 deletions

View File

@ -77,11 +77,7 @@ part001 = startSketchOn(-XZ)
)
|> xLine(endAbsolute = totalLen, tag = $seg03)
|> yLine(length = -armThick, tag = $seg01)
|> angledLineThatIntersects({
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg04
}, %)
|> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg04)
|> angledLine(angle = segAng(seg04, %) + 180, endAbsoluteY = turns::ZERO)
|> angledLine(
angle = -bottomAng,
@ -90,11 +86,7 @@ part001 = startSketchOn(-XZ)
)
|> xLine(length = endAbsolute = segEndX(seg03) + 0)
|> yLine(length = -segLen(seg01, %))
|> angledLineThatIntersects({
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg02
}, %)
|> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg02)
|> angledLine(angle = segAng(seg02, %) + 180, endAbsoluteY = -baseHeight)
|> xLine(endAbsolute = turns::ZERO)
|> close()

View File

@ -93,11 +93,7 @@ part001 = startSketchOn(XZ)
|> angledLine(angle = 30, lengthY = 3 + 0 )
|> angledLine(angle = 22.14 + 0, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 11.14)
|> angledLineThatIntersects({
angle: 3.14,
intersectTag: a,
offset: 0
}, %)
|> angledLineThatIntersects(angle = 3.14, intersectTag = a, offset = 0)
|> tangentialArc(endAbsolute = [13.14 + 0, 13.14])
|> close()
|> extrude(length = 5 + 7)

View File

@ -219,7 +219,9 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await expect(activeLinesContent[0]).toHaveText(
`|> line(end = [74.36, 130.4], tag = $seg01)`
)
await expect(activeLinesContent[1]).toHaveText(`}, %)`)
await expect(activeLinesContent[1]).toHaveText(
` |> angledLineThatIntersects(angle = -57, offset = ${offset}, intersectTag = seg01)`
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)

View File

@ -224,11 +224,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 5 + 26)
|> angledLine(angle = 89, endAbsoluteY = 20 + 9.14 + 0)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)
|> angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)
|> tangentialArc(endAbsolute = [5 + 3.14 + 13, 20 + 3.14])
`
)
@ -472,11 +468,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.14 + 0)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)
|> angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)
|> tangentialArc(endAbsolute = [3.14 + 13, 3.14])
`
)
@ -597,11 +589,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.14 + 0)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)
|> angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)
|> tangentialArc(endAbsolute = [3.14 + 13, 1.14])
`
)
@ -691,21 +679,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
y: angledLineThatIntersects.y,
},
constraintType: 'angle',
expectBeforeUnconstrained: `angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)`,
expectAfterUnconstrained: `angledLineThatIntersects({
angle = angle003,
intersectTag = a,
offset = 9
}, %)`,
expectFinal: `angledLineThatIntersects({
angle = -176,
offset = 9,
intersectTag = a
}, %)`,
expectBeforeUnconstrained: `angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)`,
expectAfterUnconstrained: `angledLineThatIntersects(angle = angle003, intersectTag = a,offset = 9)`,
expectFinal: `angledLineThatIntersects(angle = -176, offset = 9, intersectTag = a)`,
ang: ang + 180,
locator: '[data-overlay-toolbar-index="11"]',
})
@ -716,21 +692,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
y: angledLineThatIntersects.y,
},
constraintType: 'intersectionOffset',
expectBeforeUnconstrained: `angledLineThatIntersects({
angle = -176,
offset = 9,
intersectTag = a
}, %)`,
expectAfterUnconstrained: `angledLineThatIntersects({
angle = -176,
offset = perpDist001,
intersectTag = a
}, %)`,
expectFinal: `angledLineThatIntersects({
angle = -176,
offset = 9,
intersectTag = a
}, %)`,
expectBeforeUnconstrained: `angledLineThatIntersects(angle = -176, offset = 9, intersectTag = a)`,
expectAfterUnconstrained: `angledLineThatIntersects(angle = -176, offset = perpDist001, intersectTag = a)`,
expectFinal: `angledLineThatIntersects(angle = -176, offset = 9, intersectTag = a)`,
ang: ang + 180,
locator: '[data-overlay-toolbar-index="11"]',
})
@ -753,11 +717,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.14 + 0)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)
|> angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)
|> tangentialArc(endAbsolute = [3.14 + 13, -3.14])
`
)
@ -1083,11 +1043,7 @@ part001 = startSketchOn(XZ)
|> angledLine(angle = -91, lengthY = 19 + 0)
|> angledLine(angle = 3 + 0, endAbsoluteX = 26)
|> angledLine(angle = 89, endAbsoluteY = 9.14 + 0)
|> angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)
|> angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)
|> tangentialArc(endAbsolute = [3.14 + 13, 1.14])
|> arcTo({
interior = [16.25, 5.12],
@ -1169,11 +1125,7 @@ part001 = startSketchOn(XZ)
ang = await u.getAngle('[data-overlay-index="11"]')
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: `angledLineThatIntersects({
angle = 4.14,
intersectTag = a,
offset = 9
}, %)`,
codeToBeDeleted: `angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)`,
stdLibFnName: 'angledLineThatIntersects',
ang: ang + 180,
steps: 7,

View File

@ -524,11 +524,7 @@ part001 = startSketchOn(XZ)
|> angledLine(angle = 30, lengthY = 3 + 0)
|> angledLine(angle = 22.14 + 0, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 11.14)
|> angledLineThatIntersects({
angle = 3.14,
intersectTag = a,
offset = 0
}, %)
|> angledLineThatIntersects(angle = 3.14, intersectTag = a, offset = 0)
|> tangentialArc(endAbsolute = [13.14 + 0, 13.14])
|> close()
|> extrude(length = 5 + 7)
@ -660,8 +656,8 @@ part001 = startSketchOn(XZ)
await checkCodeAtHoverPosition(
'flatExtrusionFace',
flatExtrusionFace,
`angledLineThatIntersects({angle=3.14,intersectTag=a,offset=0},%)extrude(length=5+7)`,
'}, %)'
`angledLineThatIntersects(angle=3.14,intersectTag=a,offset=0)extrude(length=5+7)`,
'angledLineThatIntersects(angle = 3.14, intersectTag = a, offset = 0)'
)
await checkCodeAtHoverPosition(
@ -724,8 +720,8 @@ part001 = startSketchOn(XZ)
await checkCodeAtHoverPosition(
'straightSegmentAdjacentEdge',
straightSegmentAdjacentEdge,
`angledLineThatIntersects({angle=3.14,intersectTag=a,offset=0},%)`,
'}, %)'
`angledLineThatIntersects(angle=3.14,intersectTag=a,offset=0)`,
'angledLineThatIntersects(angle = 3.14, intersectTag = a, offset = 0)'
)
await page.waitForTimeout(200)

View File

@ -66,11 +66,7 @@ part001 = startSketchOn(-XZ)
)
|> xLine(endAbsolute = totalLen, tag = $seg03)
|> yLine(length = -armThick, tag = $seg01)
|> angledLineThatIntersects({
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg04
}, %)
|> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg04)
|> angledLine(angle = segAng(seg04) + 180, endAbsoluteY = turns::ZERO)
|> angledLine(
angle = -bottomAng,
@ -79,11 +75,7 @@ part001 = startSketchOn(-XZ)
)
|> xLine(endAbsolute = segEndX(seg03) + 0)
|> yLine(length = -segLen(seg01))
|> angledLineThatIntersects({
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg02
}, %)
|> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg02)
|> angledLine(angle = segAng(seg02) + 180, endAbsoluteY = -baseHeight)
|> xLine(endAbsolute = turns::ZERO)
|> close()

View File

@ -153,11 +153,7 @@ fn z(origin, scale, depth) {
|> yLine(length = segLen(seg3))
|> xLine(endAbsolute = 0 + origin[0])
|> yLine(length = -0.225 * scale)
|> angledLineThatIntersects({
angle = 0,
intersectTag = seg2,
offset = 0
}, %)
|> angledLineThatIntersects(angle = 0, intersectTag = seg2, offset = 0)
|> close()
|> extrude(length = -depth)
|> appearance(color = baseColor)

View File

@ -21,11 +21,11 @@ export fn zLogo(surface, origin, scale) {
|> yLine(length = segLen(seg3))
|> xLine(endAbsolute = 0 + origin[0])
|> yLine(length = -0.225 * scale)
|> angledLineThatIntersects({
|> angledLineThatIntersects(
angle = 0,
intersectTag = seg2,
offset = 0
}, %)
offset = 0,
)
|> close()
return zSketch
}

View File

@ -152,11 +152,11 @@ const extrude005l = extrude(sketch005l, length = 1)
const sketch006l = startSketchOn(plane001)
|> startProfileAt([1, 1], %)
|> angledLineThatIntersects({
angle: 70,
intersectTag: lineToIntersect4,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = 70,
intersectTag = lineToIntersect4,
offset = 0,
)
|> angledLine(angle = -70, length = 1.414 )
|> angledLine(angle = 70 + 180, endAbsoluteY = 2 - 1)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
@ -168,11 +168,11 @@ const sketch007l = startSketchOn(plane001)
serverDepth - 1.2,
railHeight * 1.75 + 1
], %)
|> angledLineThatIntersects({
angle: 70,
intersectTag: lineToIntersect5,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = 70,
intersectTag = lineToIntersect5,
offset = 0,
)
|> angledLine(angle = -70, length = 1.414 )
|> angledLine(angle = 70 + 180, endAbsoluteY = railHeight * 1.75 + 1)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
@ -243,11 +243,12 @@ const sketch006w = startSketchOn(plane002)
], %)
|> angledLine(angle = -23 + 90, endAbsoluteX = depth - 1)
|> yLine(length = 2.56)
|> angledLineThatIntersects({
angle: -23 + 90 + 180,
intersectTag: lineToIntersect,
offset: 0
}, %, $lineToIntersect2)
|> angledLineThatIntersects(
angle = -23 + 90 + 180,
intersectTag = lineToIntersect,
offset = 0,
tag = $lineToIntersect2,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude006w = extrude(sketch006w, length = 1)
@ -256,28 +257,28 @@ const sketch007w = startSketchOn(plane002)
|> startProfileAt([depth - 1, 60.65 + 1.75 / 2], %)
|> angledLine(angle = -23 + 180, length = 34.93 , tag = $lineToIntersect3)
|> angledLine(angle = 23 - 90, length = 1.414 )
|> angledLineThatIntersects({
angle: -23 + 180,
intersectTag: lineToIntersect2,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 + 180,
intersectTag = lineToIntersect2,
offset = 0,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude007w = extrude(sketch007w, length = 1)
const sketch008w = startSketchOn(plane002)
|> startProfileAt([1, 41.7 + 1.75 / 2], %)
|> angledLineThatIntersects({
angle: -23 + 90,
intersectTag: lineToIntersect3,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 + 90,
intersectTag = lineToIntersect3,
offset = 0,
)
|> angledLine(angle = -23 - 45, length = 1.414 )
|> angledLineThatIntersects({
angle: -23 - 90,
intersectTag: lineToIntersect,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 - 90,
intersectTag = lineToIntersect,
offset = 0,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude008w = extrude(sketch008w, length = 1)

View File

@ -150,11 +150,7 @@ const extrude005l = extrude(sketch005l, length = 1)
const sketch006l = startSketchOn(plane001)
|> startProfileAt([1, 1], %)
|> angledLineThatIntersects({
angle: 70,
intersectTag: lineToIntersect4,
offset: 0
}, %)
|> angledLineThatIntersects(angle = 70, intersectTag = lineToIntersect4, offset = 0)
|> angledLine(angle = -70, length = 1.414 )
|> angledLine(angle = 70 + 180, endAbsoluteY = 2 - 1)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
@ -166,11 +162,7 @@ const sketch007l = startSketchOn(plane001)
serverDepth - 1.2,
railHeight * 1.75 + 1
], %)
|> angledLineThatIntersects({
angle: 70,
intersectTag: lineToIntersect5,
offset: 0
}, %)
|> angledLineThatIntersects(angle = 70, intersectTag = lineToIntersect5, offset = 0)
|> angledLine(angle = -70, length = 1.414 )
|> angledLine(angle = 70 + 180, endAbsoluteY = railHeight * 1.75 + 1)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
@ -241,11 +233,12 @@ const sketch006w = startSketchOn(plane002)
], %)
|> angledLine(angle = -23 + 90, endAbsoluteX = depth - 1)
|> yLine(length = 2.56)
|> angledLineThatIntersects({
angle: -23 + 90 + 180,
intersectTag: lineToIntersect,
offset: 0
}, %, $lineToIntersect2)
|> angledLineThatIntersects(
angle = -23 + 90 + 180,
intersectTag = lineToIntersect,
offset = 0,
tag = $lineToIntersect2,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude006w = extrude(sketch006w, length = 1)
@ -254,28 +247,28 @@ const sketch007w = startSketchOn(plane002)
|> startProfileAt([depth - 1, 60.65 + 1.75 / 2], %)
|> angledLine(angle = -23 + 180, length = 34.93 , tag = $lineToIntersect3)
|> angledLine(angle = 23 - 90, length = 1.414 )
|> angledLineThatIntersects({
angle: -23 + 180,
intersectTag: lineToIntersect2,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 + 180,
intersectTag = lineToIntersect2,
offset = 0,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude007w = extrude(sketch007w, length = 1)
const sketch008w = startSketchOn(plane002)
|> startProfileAt([1, 41.7 + 1.75 / 2], %)
|> angledLineThatIntersects({
angle: -23 + 90,
intersectTag: lineToIntersect3,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 + 90,
intersectTag = lineToIntersect3,
offset = 0,
)
|> angledLine(angle = -23 - 45, length = 1.414 )
|> angledLineThatIntersects({
angle: -23 - 90,
intersectTag: lineToIntersect,
offset: 0
}, %)
|> angledLineThatIntersects(
angle = -23 - 90,
intersectTag = lineToIntersect,
offset = 0,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
const extrude008w = extrude(sketch008w, length = 1)

View File

@ -991,20 +991,6 @@ macro_rules! let_field_of {
};
}
impl<'a> FromKclValue<'a> for super::sketch::AngledLineThatIntersectsData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let_field_of!(obj, angle);
let_field_of!(obj, intersect_tag "intersectTag");
let_field_of!(obj, offset?);
Some(Self {
angle,
intersect_tag,
offset,
})
}
}
impl<'a> FromKclValue<'a> for super::shapes::PolygonData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
@ -1128,39 +1114,6 @@ impl<'a> FromKclValue<'a> for FaceTag {
}
}
impl<'a> FromKclValue<'a> for super::sketch::ArcData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let case1 = || {
let angle_start = obj.get("angleStart")?.as_ty_f64()?;
let angle_end = obj.get("angleEnd")?.as_ty_f64()?;
let_field_of!(obj, radius, TyF64);
Some(Self::AnglesAndRadius {
angle_start,
angle_end,
radius,
})
};
let case2 = || {
let obj = arg.as_object()?;
let_field_of!(obj, to);
let_field_of!(obj, center);
let_field_of!(obj, radius, TyF64);
Some(Self::CenterToRadius { center, to, radius })
};
case1().or_else(case2)
}
}
impl<'a> FromKclValue<'a> for super::sketch::ArcToData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let_field_of!(obj, end);
let_field_of!(obj, interior);
Some(Self { end, interior })
}
}
impl<'a> FromKclValue<'a> for super::sketch::TangentialArcData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;

View File

@ -84,7 +84,6 @@ lazy_static! {
Box::new(crate::std::sketch::ProfileStart),
Box::new(crate::std::sketch::Close),
Box::new(crate::std::sketch::Arc),
Box::new(crate::std::sketch::ArcTo),
Box::new(crate::std::sketch::TangentialArc),
Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::sketch::Hole),

View File

@ -24,7 +24,7 @@ use crate::{
std::{
args::{Args, TyF64},
utils::{
arc_angles, arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
intersection_with_parallel_line, TangentialArcInfoInput,
},
},
@ -104,7 +104,7 @@ pub async fn involute_circular(exec_state: &mut ExecState, args: Args) -> Result
let end_radius: TyF64 = args.get_kw_arg_typed("endRadius", &RuntimeType::length(), exec_state)?;
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
let reverse = args.get_kw_arg_opt("reverse")?;
let tag = args.get_kw_arg_opt("tag")?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
let new_sketch = inner_involute_circular(
sketch,
start_radius.n,
@ -617,12 +617,12 @@ pub async fn angled_line(exec_state: &mut ExecState, args: Args) -> Result<KclVa
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
angle = { docs = "Which angle should the line be drawn at?" },
length = { docs = "Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_x = { docs = "Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_y = { docs = "Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_x = { docs = "Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_y = { docs = "Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
angle = { docs = "Which angle should the line be drawn at?" },
length = { docs = "Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_x = { docs = "Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
length_y = { docs = "Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_x = { docs = "Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
end_absolute_y = { docs = "Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given."},
tag = { docs = "Create a new tag which refers to this line"},
}
}]
@ -871,25 +871,16 @@ async fn inner_angled_line_to_y(
Ok(new_sketch)
}
/// Data for drawing an angled line that intersects with a given line.
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
// TODO: make sure the docs on the args below are correct.
pub struct AngledLineThatIntersectsData {
/// The angle of the line.
pub angle: TyF64,
/// The tag of the line to intersect with.
pub intersect_tag: TagIdentifier,
/// The offset from the intersecting line.
pub offset: Option<TyF64>,
}
/// Draw an angled line that intersects with a given line.
pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, sketch, tag): (AngledLineThatIntersectsData, Sketch, Option<TagNode>) =
args.get_data_and_sketch_and_tag(exec_state)?;
let new_sketch = inner_angled_line_that_intersects(data, sketch, tag, exec_state, args).await?;
let sketch =
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
let angle: TyF64 = args.get_kw_arg("angle")?;
let intersect_tag: TagIdentifier = args.get_kw_arg("intersectTag")?;
let offset: Option<TyF64> = args.get_kw_arg_opt("offset")?;
let tag: Option<TagNode> = args.get_kw_arg_opt("tag")?;
let new_sketch =
inner_angled_line_that_intersects(sketch, angle, intersect_tag, offset, tag, exec_state, args).await?;
Ok(KclValue::Sketch {
value: Box::new(new_sketch),
})
@ -905,26 +896,37 @@ pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args)
/// |> line(endAbsolute = [5, 10])
/// |> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
/// |> line(endAbsolute = [0, 20])
/// |> angledLineThatIntersects({
/// |> angledLineThatIntersects(
/// angle = 80,
/// intersectTag = lineToIntersect,
/// offset = 10
/// }, %)
/// offset = 10,
/// )
/// |> close()
///
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "angledLineThatIntersects",
keywords = true,
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?"},
angle = { docs = "Which angle should the line be drawn at?" },
intersect_tag = { docs = "The tag of the line to intersect with" },
offset = { docs = "The offset from the intersecting line. Defaults to 0." },
tag = { docs = "Create a new tag which refers to this line"},
}
}]
pub async fn inner_angled_line_that_intersects(
data: AngledLineThatIntersectsData,
sketch: Sketch,
angle: TyF64,
intersect_tag: TagIdentifier,
offset: Option<TyF64>,
tag: Option<TagNode>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Sketch, KclError> {
let intersect_path = args.get_tag_engine_info(exec_state, &data.intersect_tag)?;
let intersect_path = args.get_tag_engine_info(exec_state, &intersect_tag)?;
let path = intersect_path.path.clone().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected an intersect path with a path, found `{:?}`", intersect_path),
@ -935,13 +937,12 @@ pub async fn inner_angled_line_that_intersects(
let from = sketch.current_pen_position()?;
let to = intersection_with_parallel_line(
&[untype_point(path.get_from()).0, untype_point(path.get_to()).0],
data.offset.map(|t| t.n).unwrap_or_default(),
data.angle.n,
offset.map(|t| t.n).unwrap_or_default(),
angle.n,
from.into(),
);
let new_sketch = straight_line(StraightLineParams::absolute(to, sketch, tag), exec_state, args).await?;
Ok(new_sketch)
straight_line(StraightLineParams::absolute(to, sketch, tag), exec_state, args).await
}
/// Data for start sketch on.
@ -1635,51 +1636,30 @@ pub(crate) async fn inner_close(
Ok(new_sketch)
}
/// Data to draw an arc.
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase", untagged)]
pub enum ArcData {
/// Angles and radius with an optional tag.
AnglesAndRadius {
/// The start angle.
#[serde(rename = "angleStart")]
#[schemars(range(min = -360.0, max = 360.0))]
angle_start: TyF64,
/// The end angle.
#[serde(rename = "angleEnd")]
#[schemars(range(min = -360.0, max = 360.0))]
angle_end: TyF64,
/// The radius.
radius: TyF64,
},
/// Center, to and radius with an optional tag.
CenterToRadius {
/// The center.
center: [TyF64; 2],
/// The to point.
to: [TyF64; 2],
/// The radius.
radius: TyF64,
},
}
/// Data to draw a three point arc (arcTo).
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ArcToData {
/// End point of the arc. A point in 3D space
pub end: [TyF64; 2],
/// Interior point of the arc. A point in 3D space
pub interior: [TyF64; 2],
}
/// Draw an arc.
pub async fn arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, sketch, tag): (ArcData, Sketch, Option<TagNode>) = args.get_data_and_sketch_and_tag(exec_state)?;
let sketch =
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
let new_sketch = inner_arc(data, sketch, tag, exec_state, args).await?;
let angle_start: Option<TyF64> = args.get_kw_arg_opt_typed("angleStart", &RuntimeType::degrees(), exec_state)?;
let angle_end: Option<TyF64> = args.get_kw_arg_opt_typed("angleEnd", &RuntimeType::degrees(), exec_state)?;
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
let end_absolute: Option<[TyF64; 2]> =
args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::point2d(), exec_state)?;
let interior: Option<[TyF64; 2]> = args.get_kw_arg_opt_typed("interior", &RuntimeType::point2d(), exec_state)?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
let new_sketch = inner_arc(
sketch,
angle_start,
angle_end,
radius,
end_absolute,
interior,
tag,
exec_state,
args,
)
.await?;
Ok(KclValue::Sketch {
value: Box::new(new_sketch),
})
@ -1700,74 +1680,181 @@ pub async fn arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> line(end = [10, 0])
/// |> arc({
/// |> arc(
/// angleStart = 0,
/// angleEnd = 280,
/// radius = 16
/// }, %)
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> arc(
/// end = [10,0],
/// interior = [5,5]
/// )
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "arc",
keywords = true,
unlabeled_first = true,
args = {
sketch = { docs = "Which sketch should this path be added to?" },
angle_start = { docs = "Where along the circle should this arc start?" },
angle_end = { docs = "Where along the circle should this arc end?" },
radius = { docs = "How large should the circle be?" },
end_absolute = { docs = "Where should this arc end? Requires `interior`. Incompatible with `angleStart` or `angleEnd`" },
interior = { docs = "Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`" },
tag = { docs = "Create a new tag which refers to this line"},
}
}]
#[allow(clippy::too_many_arguments)]
pub(crate) async fn inner_arc(
data: ArcData,
sketch: Sketch,
angle_start: Option<TyF64>,
angle_end: Option<TyF64>,
radius: Option<TyF64>,
end_absolute: Option<[TyF64; 2]>,
interior: Option<[TyF64; 2]>,
tag: Option<TagNode>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Sketch, KclError> {
let from: Point2d = sketch.current_pen_position()?;
let id = exec_state.next_uuid();
let (center, angle_start, angle_end, radius, end) = match &data {
ArcData::AnglesAndRadius {
angle_start,
angle_end,
radius,
} => {
let a_start = Angle::from_degrees(angle_start.n);
let a_end = Angle::from_degrees(angle_end.n);
let (center, end) = arc_center_and_end(from.into(), a_start, a_end, radius.n);
(center, a_start, a_end, radius.n, end)
// Relative case
match (angle_start, angle_end, radius, end_absolute, interior) {
(Some(angle_start), Some(angle_end), Some(radius), None, None) => {
relative_arc(&args, id, exec_state, sketch, from, angle_start, angle_end, radius, tag).await
}
ArcData::CenterToRadius { center, to, radius } => {
let (angle_start, angle_end) = arc_angles(
from.into(),
untype_point(to.clone()).0,
untype_point(center.clone()).0,
radius.n,
args.source_range,
)?;
(
untype_point(center.clone()).0,
angle_start,
angle_end,
radius.n,
untype_point(to.clone()).0,
)
(None, None, None, Some(interior), Some(end_absolute)) => {
absolute_arc(&args, id, exec_state, sketch, from, interior, end_absolute,tag).await
}
_ => {
Err(KclError::Type(KclErrorDetails {
message:
"Invalid combination of arguments. Either provide (angleStart, angleEnd, radius) or (endAbsolute, interior)"
.to_string(),
source_ranges: vec![args.source_range],
}))
}
}
}
#[allow(clippy::too_many_arguments)]
pub async fn absolute_arc(
args: &Args,
id: uuid::Uuid,
exec_state: &mut ExecState,
sketch: Sketch,
from: Point2d,
interior: [TyF64; 2],
end_absolute: [TyF64; 2],
tag: Option<TagNode>,
) -> Result<Sketch, KclError> {
// The start point is taken from the path you are extending.
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::ArcTo {
end: kcmc::shared::Point3d {
x: LengthUnit(end_absolute[0].n),
y: LengthUnit(end_absolute[1].n),
z: LengthUnit(0.0),
},
interior: kcmc::shared::Point3d {
x: LengthUnit(interior[0].n),
y: LengthUnit(interior[1].n),
z: LengthUnit(0.0),
},
relative: false,
},
}),
)
.await?;
let start = [from.x, from.y];
let end = end_absolute.clone();
let untyped_end = untype_point(end);
let current_path = Path::ArcThreePoint {
base: BasePath {
from: from.into(),
to: untyped_end.0,
tag: tag.clone(),
units: sketch.units,
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
p1: start,
p2: untype_point(interior).0,
p3: untyped_end.0,
};
let mut new_sketch = sketch.clone();
if let Some(tag) = &tag {
new_sketch.add_tag(tag, &current_path, exec_state);
}
new_sketch.paths.push(current_path);
Ok(new_sketch)
}
#[allow(clippy::too_many_arguments)]
pub async fn relative_arc(
args: &Args,
id: uuid::Uuid,
exec_state: &mut ExecState,
sketch: Sketch,
from: Point2d,
angle_start: TyF64,
angle_end: TyF64,
radius: TyF64,
tag: Option<TagNode>,
) -> Result<Sketch, KclError> {
let a_start = Angle::from_degrees(angle_start.n);
let a_end = Angle::from_degrees(angle_end.n);
let (center, end) = arc_center_and_end(from.into(), a_start, a_end, radius.n);
if angle_start == angle_end {
return Err(KclError::Type(KclErrorDetails {
message: "Arc start and end angles must be different".to_string(),
source_ranges: vec![args.source_range],
}));
}
let ccw = angle_start < angle_end;
let id = exec_state.next_uuid();
if a_start.to_degrees() > 360.0 || a_start.to_degrees() < -360.0 {
return Err(KclError::Type(KclErrorDetails {
message: "Start angle must be between ±360 degrees.".to_string(),
// TODO: This source range should be specifically on the `angleStart` arg, not the entire arg list.
source_ranges: vec![args.source_range],
}));
}
if a_end.to_degrees() > 360.0 || a_end.to_degrees() < -360.0 {
return Err(KclError::Type(KclErrorDetails {
message: "End angle must be between ±360 degrees.".to_string(),
// TODO: This source range should be specifically on the `angleEnd` arg, not the entire arg list.
source_ranges: vec![args.source_range],
}));
}
let ccw = angle_start.n < angle_end.n;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Arc {
start: angle_start,
end: angle_end,
start: a_start,
end: a_end,
center: KPoint2d::from(center).map(LengthUnit),
radius: LengthUnit(radius),
radius: LengthUnit(radius.n),
relative: false,
},
}),
@ -1786,7 +1873,7 @@ pub(crate) async fn inner_arc(
},
},
center,
radius,
radius: radius.n,
ccw,
};
@ -1799,98 +1886,6 @@ pub(crate) async fn inner_arc(
Ok(new_sketch)
}
/// Draw a three point arc.
pub async fn arc_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, sketch, tag): (ArcToData, Sketch, Option<TagNode>) = args.get_data_and_sketch_and_tag(exec_state)?;
let new_sketch = inner_arc_to(data, sketch, tag, exec_state, args).await?;
Ok(KclValue::Sketch {
value: Box::new(new_sketch),
})
}
/// Draw a three point arc.
///
/// The arc is constructed such that the start point is the current position of the sketch and two more points defined as the end and interior point.
/// The interior point is placed between the start point and end point. The radius of the arc will be controlled by how far the interior point is placed from
/// the start and end.
///
/// ```no_run
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> arcTo({
/// end = [10,0],
/// interior = [5,5]
/// }, %)
/// |> close()
/// example = extrude(exampleSketch, length = 10)
/// ```
#[stdlib {
name = "arcTo",
}]
pub(crate) async fn inner_arc_to(
data: ArcToData,
sketch: Sketch,
tag: Option<TagNode>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Sketch, KclError> {
let from: Point2d = sketch.current_pen_position()?;
let id = exec_state.next_uuid();
// The start point is taken from the path you are extending.
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::ArcTo {
end: kcmc::shared::Point3d {
x: LengthUnit(data.end[0].n),
y: LengthUnit(data.end[1].n),
z: LengthUnit(0.0),
},
interior: kcmc::shared::Point3d {
x: LengthUnit(data.interior[0].n),
y: LengthUnit(data.interior[1].n),
z: LengthUnit(0.0),
},
relative: false,
},
}),
)
.await?;
let start = [from.x, from.y];
let interior = data.interior;
let end = data.end.clone();
let current_path = Path::ArcThreePoint {
base: BasePath {
from: from.into(),
to: untype_point(data.end).0,
tag: tag.clone(),
units: sketch.units,
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
p1: start,
p2: untype_point(interior).0,
p3: untype_point(end).0,
};
let mut new_sketch = sketch.clone();
if let Some(tag) = &tag {
new_sketch.add_tag(tag, &current_path, exec_state);
}
new_sketch.paths.push(current_path);
Ok(new_sketch)
}
/// Draw a tangential arc to a specific point.
pub async fn tangential_arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch =

View File

@ -2141,11 +2141,11 @@ mySk1 = startSketchOn(XY)
|> startProfileAt([-0.01, -0.08], %)
|> line([0.62, 4.15], %, $seg01)
|> line([2.77, -1.24], %)
|> angledLineThatIntersects({
|> angledLineThatIntersects(
angle = 201,
offset = -1.35,
intersectTag = seg01
}, %)
)
|> line([-0.42, -1.72], %)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();

View File

@ -318,40 +318,40 @@ flowchart LR
892["Segment<br>[5591, 5619, 0]"]
893["Segment<br>[5627, 5661, 0]"]
894["Segment<br>[5669, 5699, 0]"]
895["Segment<br>[5707, 5816, 0]"]
896["Segment<br>[5824, 5831, 0]"]
895["Segment<br>[5707, 5812, 0]"]
896["Segment<br>[5820, 5827, 0]"]
897[Solid2d]
end
subgraph path950 [Path]
950["Path<br>[6031, 6129, 0]"]
951["Segment<br>[6137, 6256, 0]"]
952["Segment<br>[6264, 6311, 0]"]
953["Segment<br>[6319, 6440, 0]"]
954["Segment<br>[6448, 6455, 0]"]
950["Path<br>[6027, 6125, 0]"]
951["Segment<br>[6133, 6252, 0]"]
952["Segment<br>[6260, 6307, 0]"]
953["Segment<br>[6315, 6436, 0]"]
954["Segment<br>[6444, 6451, 0]"]
955[Solid2d]
end
subgraph path972 [Path]
972["Path<br>[6563, 6660, 0]"]
973["Segment<br>[6668, 6787, 0]"]
974["Segment<br>[6795, 6843, 0]"]
975["Segment<br>[6851, 6972, 0]"]
976["Segment<br>[6980, 6987, 0]"]
972["Path<br>[6559, 6656, 0]"]
973["Segment<br>[6664, 6783, 0]"]
974["Segment<br>[6791, 6839, 0]"]
975["Segment<br>[6847, 6968, 0]"]
976["Segment<br>[6976, 6983, 0]"]
977[Solid2d]
end
subgraph path994 [Path]
994["Path<br>[6031, 6129, 0]"]
995["Segment<br>[6137, 6256, 0]"]
996["Segment<br>[6264, 6311, 0]"]
997["Segment<br>[6319, 6440, 0]"]
998["Segment<br>[6448, 6455, 0]"]
994["Path<br>[6027, 6125, 0]"]
995["Segment<br>[6133, 6252, 0]"]
996["Segment<br>[6260, 6307, 0]"]
997["Segment<br>[6315, 6436, 0]"]
998["Segment<br>[6444, 6451, 0]"]
999[Solid2d]
end
subgraph path1016 [Path]
1016["Path<br>[6563, 6660, 0]"]
1017["Segment<br>[6668, 6787, 0]"]
1018["Segment<br>[6795, 6843, 0]"]
1019["Segment<br>[6851, 6972, 0]"]
1020["Segment<br>[6980, 6987, 0]"]
1016["Path<br>[6559, 6656, 0]"]
1017["Segment<br>[6664, 6783, 0]"]
1018["Segment<br>[6791, 6839, 0]"]
1019["Segment<br>[6847, 6968, 0]"]
1020["Segment<br>[6976, 6983, 0]"]
1021[Solid2d]
end
1["Plane<br>[532, 549, 0]"]
@ -983,7 +983,7 @@ flowchart LR
877["SweepEdge Opposite"]
878["SweepEdge Adjacent"]
879["Plane<br>[4924, 4947, 0]"]
898["Sweep Extrusion<br>[5839, 5863, 0]"]
898["Sweep Extrusion<br>[5835, 5859, 0]"]
899[Wall]
900[Wall]
901[Wall]
@ -1034,8 +1034,8 @@ flowchart LR
946["SweepEdge Adjacent"]
947["SweepEdge Opposite"]
948["SweepEdge Adjacent"]
949["Plane<br>[6000, 6023, 0]"]
956["Sweep Extrusion<br>[6463, 6487, 0]"]
949["Plane<br>[5996, 6019, 0]"]
956["Sweep Extrusion<br>[6459, 6483, 0]"]
957[Wall]
958[Wall]
959[Wall]
@ -1050,8 +1050,8 @@ flowchart LR
968["SweepEdge Adjacent"]
969["SweepEdge Opposite"]
970["SweepEdge Adjacent"]
971["Plane<br>[6532, 6555, 0]"]
978["Sweep Extrusion<br>[6995, 7019, 0]"]
971["Plane<br>[6528, 6551, 0]"]
978["Sweep Extrusion<br>[6991, 7015, 0]"]
979[Wall]
980[Wall]
981[Wall]
@ -1066,8 +1066,8 @@ flowchart LR
990["SweepEdge Adjacent"]
991["SweepEdge Opposite"]
992["SweepEdge Adjacent"]
993["Plane<br>[6000, 6023, 0]"]
1000["Sweep Extrusion<br>[6463, 6487, 0]"]
993["Plane<br>[5996, 6019, 0]"]
1000["Sweep Extrusion<br>[6459, 6483, 0]"]
1001[Wall]
1002[Wall]
1003[Wall]
@ -1082,8 +1082,8 @@ flowchart LR
1012["SweepEdge Adjacent"]
1013["SweepEdge Opposite"]
1014["SweepEdge Adjacent"]
1015["Plane<br>[6532, 6555, 0]"]
1022["Sweep Extrusion<br>[6995, 7019, 0]"]
1015["Plane<br>[6528, 6551, 0]"]
1022["Sweep Extrusion<br>[6991, 7015, 0]"]
1023[Wall]
1024[Wall]
1025[Wall]

View File

@ -9548,99 +9548,74 @@ description: Result of parsing keyboard.kcl
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"properties": [
{
"commentStart": 0,
"end": 0,
"key": {
"commentStart": 0,
"end": 0,
"name": "angle",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 0,
"end": 0,
"key": {
"commentStart": 0,
"end": 0,
"name": "intersectTag",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "seg2",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
}
},
{
"commentStart": 0,
"end": 0,
"key": {
"commentStart": 0,
"end": 0,
"name": "offset",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "angle",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
],
"start": 0,
"type": "ObjectExpression",
"type": "ObjectExpression"
}
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "intersectTag",
"start": 0,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "seg2",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "offset",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
}
],
"callee": {
@ -9661,8 +9636,9 @@ description: Result of parsing keyboard.kcl
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [],

View File

@ -7202,7 +7202,7 @@ description: Operations executed keyboard.kcl
"name": "z",
"functionSourceRange": [
4893,
5913,
5909,
0
],
"unlabeledArg": null,
@ -7438,8 +7438,8 @@ description: Operations executed keyboard.kcl
"type": "FunctionCall",
"name": "o",
"functionSourceRange": [
5960,
7069,
5956,
7065,
0
],
"unlabeledArg": null,
@ -7894,8 +7894,8 @@ description: Operations executed keyboard.kcl
"type": "FunctionCall",
"name": "o",
"functionSourceRange": [
5960,
7069,
5956,
7065,
0
],
"unlabeledArg": null,

View File

@ -94,40 +94,40 @@ flowchart LR
168["Segment<br>[759, 787, 12]"]
169["Segment<br>[795, 829, 12]"]
170["Segment<br>[837, 867, 12]"]
171["Segment<br>[875, 984, 12]"]
172["Segment<br>[992, 999, 12]"]
171["Segment<br>[875, 980, 12]"]
172["Segment<br>[988, 995, 12]"]
173[Solid2d]
end
subgraph path175 [Path]
175["Path<br>[1133, 1231, 12]"]
176["Segment<br>[1239, 1358, 12]"]
177["Segment<br>[1366, 1413, 12]"]
178["Segment<br>[1421, 1542, 12]"]
179["Segment<br>[1550, 1557, 12]"]
175["Path<br>[1129, 1227, 12]"]
176["Segment<br>[1235, 1354, 12]"]
177["Segment<br>[1362, 1409, 12]"]
178["Segment<br>[1417, 1538, 12]"]
179["Segment<br>[1546, 1553, 12]"]
180[Solid2d]
end
subgraph path182 [Path]
182["Path<br>[1654, 1751, 12]"]
183["Segment<br>[1759, 1878, 12]"]
184["Segment<br>[1886, 1934, 12]"]
185["Segment<br>[1942, 2063, 12]"]
186["Segment<br>[2071, 2078, 12]"]
182["Path<br>[1650, 1747, 12]"]
183["Segment<br>[1755, 1874, 12]"]
184["Segment<br>[1882, 1930, 12]"]
185["Segment<br>[1938, 2059, 12]"]
186["Segment<br>[2067, 2074, 12]"]
187[Solid2d]
end
subgraph path189 [Path]
189["Path<br>[1133, 1231, 12]"]
190["Segment<br>[1239, 1358, 12]"]
191["Segment<br>[1366, 1413, 12]"]
192["Segment<br>[1421, 1542, 12]"]
193["Segment<br>[1550, 1557, 12]"]
189["Path<br>[1129, 1227, 12]"]
190["Segment<br>[1235, 1354, 12]"]
191["Segment<br>[1362, 1409, 12]"]
192["Segment<br>[1417, 1538, 12]"]
193["Segment<br>[1546, 1553, 12]"]
194[Solid2d]
end
subgraph path196 [Path]
196["Path<br>[1654, 1751, 12]"]
197["Segment<br>[1759, 1878, 12]"]
198["Segment<br>[1886, 1934, 12]"]
199["Segment<br>[1942, 2063, 12]"]
200["Segment<br>[2071, 2078, 12]"]
196["Path<br>[1650, 1747, 12]"]
197["Segment<br>[1755, 1874, 12]"]
198["Segment<br>[1882, 1930, 12]"]
199["Segment<br>[1938, 2059, 12]"]
200["Segment<br>[2067, 2074, 12]"]
201[Solid2d]
end
subgraph path230 [Path]

View File

@ -1512,7 +1512,7 @@ description: Operations executed walkie-talkie.kcl
"name": "zLogo",
"functionSourceRange": [
69,
1018,
1014,
12
],
"unlabeledArg": null,
@ -1570,8 +1570,8 @@ description: Operations executed walkie-talkie.kcl
"type": "FunctionCall",
"name": "oLogo",
"functionSourceRange": [
1076,
1579,
1072,
1575,
12
],
"unlabeledArg": null,
@ -1629,8 +1629,8 @@ description: Operations executed walkie-talkie.kcl
"type": "FunctionCall",
"name": "oLogo2",
"functionSourceRange": [
1597,
2100,
1593,
2096,
12
],
"unlabeledArg": null,
@ -1688,8 +1688,8 @@ description: Operations executed walkie-talkie.kcl
"type": "FunctionCall",
"name": "oLogo",
"functionSourceRange": [
1076,
1579,
1072,
1575,
12
],
"unlabeledArg": null,
@ -1747,8 +1747,8 @@ description: Operations executed walkie-talkie.kcl
"type": "FunctionCall",
"name": "oLogo2",
"functionSourceRange": [
1597,
2100,
1593,
2096,
12
],
"unlabeledArg": null,

View File

@ -8,5 +8,7 @@ export const DETERMINING_ARGS = [ARG_LENGTH, ARG_END, ARG_END_ABSOLUTE]
export const ARG_LENGTH_X = 'lengthX'
export const ARG_LENGTH_Y = 'lengthY'
export const ARG_ANGLE = 'angle'
export const ARG_OFFSET = 'offset'
export const ARG_END_ABSOLUTE_X = 'endAbsoluteX'
export const ARG_END_ABSOLUTE_Y = 'endAbsoluteY'
export const ARG_INTERSECT_TAG = 'intersectTag'

View File

@ -642,7 +642,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine(angle = -65, length = ${
],
[
'angledLineThatIntersects',
`angledLineThatIntersects({ angle = 45.5, intersectTag = b, offset = 198.85 }, %, $a)`,
`angledLineThatIntersects(angle = 45.5, intersectTag = b, offset = 198.85, tag = $a)`,
['918.4', '45.5'],
],
])(`%s`, async (_, line, [replace1, replace2]) => {
@ -684,11 +684,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|> /*2*/ angledLine(angle = 30 + 0, lengthY = 3 + 0)
|> /*3*/ angledLine(angle = 12.14 + 0, endAbsoluteX = 12 + 0)
|> /*4*/ angledLine(angle = 30 + 0, endAbsoluteY = 10.14 + 0)
|> angledLineThatIntersects({
angle = 3.14 + 0,
intersectTag = a,
offset = 0 + 0
}, %)
|> angledLineThatIntersects(angle = 3.14 + 0, intersectTag = a, offset = 0 + 0)
|> tangentialArc(endAbsolute = [3.14 + 0, 13.14 + 0])`
test.each([
[' line(end = [3 + 0, 4])', 'arrayIndex', 1, ''],
@ -728,12 +724,8 @@ describe('Testing removeSingleConstraintInfo', () => {
'',
],
[
`angledLineThatIntersects({
angle = 3.14 + 0,
offset = 0,
intersectTag = a
}, %)`,
'objectProperty',
`angledLineThatIntersects(angle = 3.14 + 0, intersectTag = a, offset = 0)`,
'labeledArg',
'offset',
'',
],
@ -762,11 +754,6 @@ describe('Testing removeSingleConstraintInfo', () => {
type: 'arrayItem',
index: value === 0 ? 0 : 1,
}
} else if (key === 'objectProperty' && typeof value === 'string') {
argPosition = {
type: 'objectProperty',
key: value,
}
} else if (key === '') {
argPosition = {
type: 'singleValue',

View File

@ -337,11 +337,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|> startProfileAt([-0.01, -0.08], %)
|> line(end = [0.62, 4.15], tag = $seg01)
|> line(end = [2.77, -1.24])
|> angledLineThatIntersects({
angle = 201,
offset = -1.35,
intersectTag = $seg01
}, %)
|> angledLineThatIntersects(angle = 201, offset = -1.35, intersectTag = $seg01)
|> line(end = [-0.42, -1.72])
`
const { ast } = code2ast(code)
@ -350,11 +346,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
expect(recasted).toBe(code)
})
it('recasts wrapped object expressions NOT in pipe body correctly', () => {
const code = `angledLineThatIntersects({
angle = 201,
offset = -1.35,
intersectTag = $seg01
}, %)
const code = `angledLineThatIntersects(angle = 201, offset = -1.35, intersectTag = $seg01)
`
const { ast } = code2ast(code)
const recasted = recast(ast)

View File

@ -330,11 +330,11 @@ describe('testing getConstraintInfo', () => {
|> angledLine(angle = 30, lengthY = 3)
|> angledLine(angle = 12.14, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 10.14)
|> angledLineThatIntersects({
|> angledLineThatIntersects(
angle = 3.14,
intersectTag = a,
offset = 0
}, %)
offset = 0,
)
|> tangentialArc(endAbsolute = [3.14, 13.14])`
test.each([
[
@ -598,16 +598,7 @@ describe('testing getConstraintInfo', () => {
isConstrained: false,
value: '3.14',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'objectProperty', key: 'angle' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
{
type: 'intersectionOffset',
isConstrained: false,
value: '0',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'objectProperty', key: 'offset' },
argPosition: { type: 'labeledArg', key: 'angle' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
@ -618,11 +609,20 @@ describe('testing getConstraintInfo', () => {
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: {
key: 'intersectTag',
type: 'objectProperty',
type: 'labeledArg',
},
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
{
type: 'intersectionOffset',
isConstrained: false,
value: '0',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'labeledArg', key: 'offset' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
],
],
[
@ -696,11 +696,11 @@ describe('testing getConstraintInfo', () => {
|> angledLine(angle = 30, lengthY = 3)
|> angledLine(angle = 12, endAbsoluteX = 12)
|> angledLine(angle = 30, endAbsoluteY = 10)
|> angledLineThatIntersects({
|> angledLineThatIntersects(
angle = 3.14,
intersectTag = a,
offset = 0
}, %)
offset = 0,
)
|> tangentialArc(endAbsolute = [3.14, 13.14])`
test.each([
[
@ -857,11 +857,11 @@ describe('testing getConstraintInfo', () => {
|> angledLine(angle = 30 + 0, lengthY = 3 + 0)
|> angledLine(angle = 12.14 + 0, endAbsoluteX = 12 + 0)
|> angledLine(angle = 30 + 0, endAbsoluteY = 10.14 + 0)
|> angledLineThatIntersects({
|> angledLineThatIntersects(
angle = 3.14 + 0,
intersectTag = a,
offset = 0 + 0
}, %)
offset = 0 + 0,
)
|> tangentialArc(endAbsolute = [3.14 + 0, 13.14 + 0])`
test.each([
[
@ -1125,16 +1125,7 @@ describe('testing getConstraintInfo', () => {
isConstrained: true,
value: '3.14 + 0',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'objectProperty', key: 'angle' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
{
type: 'intersectionOffset',
isConstrained: true,
value: '0 + 0',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'objectProperty', key: 'offset' },
argPosition: { type: 'labeledArg', key: 'angle' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
@ -1143,7 +1134,16 @@ describe('testing getConstraintInfo', () => {
isConstrained: false,
value: 'a',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { key: 'intersectTag', type: 'objectProperty' },
argPosition: { key: 'intersectTag', type: 'labeledArg' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},
{
type: 'intersectionOffset',
isConstrained: true,
value: '0 + 0',
sourceRange: [expect.any(Number), expect.any(Number), 0],
argPosition: { type: 'labeledArg', key: 'offset' },
pathToNode: expect.any(Array),
stdLibFnName: 'angledLineThatIntersects',
},

View File

@ -1,6 +1,5 @@
import { perpendicularDistance } from 'sketch-helpers'
import type { Name } from '@rust/kcl-lib/bindings/Name'
import type { Node } from '@rust/kcl-lib/bindings/Node'
import type { TagDeclarator } from '@rust/kcl-lib/bindings/TagDeclarator'
@ -12,9 +11,11 @@ import {
ARG_END_ABSOLUTE,
ARG_END_ABSOLUTE_X,
ARG_END_ABSOLUTE_Y,
ARG_INTERSECT_TAG,
ARG_LENGTH,
ARG_LENGTH_X,
ARG_LENGTH_Y,
ARG_OFFSET,
ARG_TAG,
DETERMINING_ARGS,
} from '@src/lang/constants'
@ -128,15 +129,10 @@ export function createFirstArg(
'angledLineOfYLength',
'angledLineToX',
'angledLineToY',
'angledLineThatIntersects',
].includes(sketchFn)
)
return createArrayExpression(val)
if (['angledLineThatIntersects'].includes(sketchFn) && val[2])
return createObjectExpression({
angle: val[0],
offset: val[1],
intersectTag: val[2],
})
} else {
if (['xLine', 'xLineTo', 'yLine', 'yLineTo'].includes(sketchFn)) return val
}
@ -2819,7 +2815,7 @@ export const angledLineToY: SketchLineHelperKw = {
),
}
export const angledLineThatIntersects: SketchLineHelper = {
export const angledLineThatIntersects: SketchLineHelperKw = {
add: ({
node,
pathToNode,
@ -2858,13 +2854,13 @@ export const angledLineThatIntersects: SketchLineHelper = {
if (replaceExistingCallback) {
const result = replaceExistingCallback([
{
type: 'objectProperty',
type: 'labeledArg',
key: 'angle',
argType: 'angle',
expr: angle,
},
{
type: 'objectProperty',
type: 'labeledArg',
key: 'offset',
argType: 'intersectionOffset',
expr: offset,
@ -2886,18 +2882,18 @@ export const angledLineThatIntersects: SketchLineHelper = {
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR
const { to, from } = input
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const firstArg = callExpression.arguments?.[0]
const intersectTag =
firstArg.type === 'ObjectExpression'
? firstArg.properties.find((p) => p.key.name === 'intersectTag')
?.value || createLiteral('')
: createLiteral('')
const intersectTag = findKwArg(ARG_INTERSECT_TAG, callExpression)
if (intersectTag === undefined) {
return new Error(
`no ${ARG_INTERSECT_TAG} argument found in angledLineThatIntersect call, which requires it`
)
}
const intersectTagName =
intersectTag.type === 'Name' ? intersectTag.name.name : ''
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
@ -2922,94 +2918,79 @@ export const angledLineThatIntersects: SketchLineHelper = {
)
}
const angleLit = createLiteral(angle)
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, createLiteral(offset), 'offset')
mutateKwArg(ARG_ANGLE, callExpression, createLiteral(angle))
mutateKwArg(ARG_OFFSET, callExpression, createLiteral(offset))
return {
modifiedAst: _node,
pathToNode,
}
},
getTag: getTag(),
addTag: addTag(),
getConstraintInfo: (callExp: CallExpression, code, pathToNode) => {
if (callExp.type !== 'CallExpression') return []
const firstArg = callExp.arguments?.[0]
if (firstArg.type !== 'ObjectExpression') return []
const angleIndex = firstArg.properties.findIndex(
(p) => p.key.name === 'angle'
)
const offsetIndex = firstArg.properties.findIndex(
(p) => p.key.name === 'offset'
)
const intersectTag = firstArg.properties.findIndex(
(p) => p.key.name === 'intersectTag'
)
getTag: getTagKwArg(),
addTag: addTagKw(),
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
if (callExp.type !== 'CallExpressionKw') return []
const angle = findKwArgWithIndex(ARG_ANGLE, callExp)
const offset = findKwArgWithIndex(ARG_OFFSET, callExp)
const intersectTag = findKwArgWithIndex(ARG_INTERSECT_TAG, callExp)
const returnVal = []
const pathToObjectExp: PathToNode = [
const pathToBase: PathToNode = [
...pathToNode,
['arguments', 'CallExpression'],
[0, 'index'],
['properties', 'ObjectExpression'],
['arguments', 'CallExpressionKw'],
]
if (angleIndex !== -1) {
const angle = firstArg.properties[angleIndex]?.value
if (angle !== undefined) {
const pathToAngleProp: PathToNode = [
...pathToObjectExp,
[angleIndex, 'index'],
['value', 'Property'],
...pathToBase,
[angle.argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]
returnVal.push(
constrainInfo(
'angle',
isNotLiteralArrayOrStatic(angle),
code.slice(angle.start, angle.end),
isNotLiteralArrayOrStatic(angle.expr),
code.slice(angle.expr.start, angle.expr.end),
'angledLineThatIntersects',
'angle',
topLevelRange(angle.start, angle.end),
{ type: 'labeledArg', key: 'angle' },
topLevelRange(angle.expr.start, angle.expr.end),
pathToAngleProp
)
)
}
if (offsetIndex !== -1) {
const offset = firstArg.properties[offsetIndex]?.value
const pathToOffsetProp: PathToNode = [
...pathToObjectExp,
[offsetIndex, 'index'],
['value', 'Property'],
]
returnVal.push(
constrainInfo(
'intersectionOffset',
isNotLiteralArrayOrStatic(offset),
code.slice(offset.start, offset.end),
'angledLineThatIntersects',
'offset',
topLevelRange(offset.start, offset.end),
pathToOffsetProp
)
)
}
if (intersectTag !== -1) {
const tag = firstArg.properties[intersectTag]?.value as Node<Name>
if (intersectTag !== undefined) {
const pathToTagProp: PathToNode = [
...pathToObjectExp,
[intersectTag, 'index'],
['value', 'Property'],
...pathToBase,
[intersectTag.argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]
const info = constrainInfo(
'intersectionTag',
// This will always be a tag identifier.
false,
code.slice(tag.start, tag.end),
code.slice(intersectTag.expr.start, intersectTag.expr.end),
'angledLineThatIntersects',
'intersectTag',
topLevelRange(tag.start, tag.end),
{ type: 'labeledArg', key: 'intersectTag' },
topLevelRange(intersectTag.expr.start, intersectTag.expr.end),
pathToTagProp
)
returnVal.push(info)
}
if (offset !== undefined) {
const pathToOffsetProp: PathToNode = [
...pathToBase,
[offset.argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]
returnVal.push(
constrainInfo(
'intersectionOffset',
isNotLiteralArrayOrStatic(offset.expr),
code.slice(offset.expr.start, offset.expr.end),
'angledLineThatIntersects',
{ type: 'labeledArg', key: 'offset' },
topLevelRange(offset.expr.start, offset.expr.end),
pathToOffsetProp
)
)
}
return returnVal
},
}
@ -3064,7 +3045,6 @@ export const updateStartProfileAtArgs: SketchLineHelper['updateArgs'] = ({
}
export const sketchLineHelperMap: { [key: string]: SketchLineHelper } = {
angledLineThatIntersects,
arc,
arcTo,
} as const
@ -3081,6 +3061,7 @@ export const sketchLineHelperMapKw: { [key: string]: SketchLineHelperKw } = {
angledLine,
angledLineOfXLength,
angledLineOfYLength,
angledLineThatIntersects,
angledLineToX,
angledLineToY,
tangentialArc,
@ -3173,6 +3154,7 @@ export function fnNameToTooltip(
return isAbsolute ? 'xLineTo' : 'xLine'
case 'yLine':
return isAbsolute ? 'yLineTo' : 'yLine'
case 'angledLineThatIntersects':
case 'circleThreePoint':
case 'circle':
case 'tangentialArc':
@ -3191,7 +3173,7 @@ export function fnNameToTooltip(
return tooltip
}
}
const err = `Unknown angledline arguments, could not map to tooltip. Args were ${argLabels}`
const err = `Unknown angledLine arguments, could not map to tooltip. Args were ${argLabels}`
console.error(err)
return new Error(err)
}
@ -3893,29 +3875,24 @@ export const getCircle = (
return new Error('expected the arguments to be for a circle')
}
const getAngledLineThatIntersects = (
callExp: CallExpression
export const getAngledLineThatIntersects = (
callExp: CallExpressionKw
):
| {
val: [Expr, Expr, Expr]
tag?: Expr
}
| Error => {
const firstArg = callExp.arguments[0]
if (firstArg.type === 'ObjectExpression') {
const tag = firstArg.properties.find((p) => p.key.name === 'tag')?.value
const angle = firstArg.properties.find((p) => p.key.name === 'angle')?.value
const offset = firstArg.properties.find(
(p) => p.key.name === 'offset'
)?.value
const intersectTag = firstArg.properties.find(
(p) => p.key.name === 'intersectTag'
)?.value
if (angle && offset && intersectTag) {
return { val: [angle, offset, intersectTag], tag }
}
const angle = findKwArg(ARG_ANGLE, callExp)
const intersectTag = findKwArg(ARG_INTERSECT_TAG, callExp)
const offset = findKwArg(ARG_OFFSET, callExp)
if (!angle || !intersectTag || !offset) {
return new Error(
`angledLineThatIntersects call needs angle, intersectTag, and offset args`
)
}
return new Error('expected ArrayExpression or ObjectExpression')
const tag = findKwArg(ARG_TAG, callExp)
return { val: [angle, intersectTag, offset], tag }
}
/**
@ -3946,6 +3923,7 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
return new Error(
`${name} call has neither ${ARG_END} nor ${ARG_END_ABSOLUTE} params`
)
case 'angledLineThatIntersects':
case 'circle':
case 'circleThreePoint':
return false
@ -3980,6 +3958,8 @@ export function getArgForEnd(lineCall: CallExpressionKw):
}
return getValuesForXYFns(arg)
}
case 'angledLineThatIntersects':
return getAngledLineThatIntersects(lineCall)
case 'yLine':
case 'xLine': {
const arg = findKwArgAny(DETERMINING_ARGS, lineCall)
@ -4039,9 +4019,6 @@ export function getFirstArg(callExp: CallExpression):
if (['xLine', 'yLine', 'xLineTo', 'yLineTo'].includes(name)) {
return getFirstArgValuesForXYLineFns(callExp)
}
if (['angledLineThatIntersects'].includes(name)) {
return getAngledLineThatIntersects(callExp)
}
if (['tangentialArc'].includes(name)) {
// TODO probably needs it's own implementation
return getFirstArgValuesForXYFns(callExp)

View File

@ -7,9 +7,11 @@ import {
ARG_END_ABSOLUTE,
ARG_END_ABSOLUTE_X,
ARG_END_ABSOLUTE_Y,
ARG_INTERSECT_TAG,
ARG_LENGTH,
ARG_LENGTH_X,
ARG_LENGTH_Y,
ARG_OFFSET,
ARG_TAG,
DETERMINING_ARGS,
} from '@src/lang/constants'
@ -36,6 +38,7 @@ import {
createFirstArg,
fnNameToTooltip,
getAngledLine,
getAngledLineThatIntersects,
getArgForEnd,
getCircle,
getConstraintInfo,
@ -345,20 +348,16 @@ function intersectCallWrapper({
tag?: Expr
valueUsedInTransform?: number
}): CreatedSketchExprResult {
const firstArg: any = {
angle: angleVal,
offset: offsetVal,
intersectTag,
}
const args: Expr[] = [
createObjectExpression(firstArg),
createPipeSubstitution(),
const args: LabeledArg[] = [
createLabeledArg(ARG_ANGLE, angleVal),
createLabeledArg(ARG_OFFSET, offsetVal),
createLabeledArg(ARG_INTERSECT_TAG, intersectTag),
]
if (tag) {
args.push(tag)
args.push(createLabeledArg(ARG_TAG, tag))
}
return {
callExp: createCallExpression(fnName, args),
callExp: createCallExpressionStdLibKw(fnName, null, args),
valueUsedInTransform,
}
}
@ -2335,6 +2334,9 @@ export function getConstraintLevelFromSourceRange(
) {
return getAngledLine(nodeMeta.node)
}
if (name === 'angledLineThatIntersects') {
return getAngledLineThatIntersects(nodeMeta.node)
}
const arg = findKwArgAny(DETERMINING_ARGS, nodeMeta.node)
if (arg === undefined) {
const argStr = nodeMeta.node.arguments.map((a) => a.label.name)

View File

@ -12,11 +12,12 @@ describe('testing angledLineThatIntersects', () => {
|> startProfileAt([0, 0], %)
|> line(endAbsolute = [2, 2], tag = $yo)
|> line(endAbsolute = [3, 1])
|> angledLineThatIntersects({
angle: 180,
intersectTag: yo,
offset: ${offset},
}, %, $yo2)
|> angledLineThatIntersects(
angle = 180,
intersectTag = yo,
offset = ${offset},
tag = $yo2,
)
intersect = segEndX(yo2)`
const execState = await enginelessExecutor(assertParse(code('-1')))
expect(execState.variables['intersect']?.value).toBe(1 + Math.sqrt(2))