#5339 Add tangent snapping to straight segment tool (#5995)

* first draft of making segment snap to previous arc's last tangent

* ability to force/disable line snap, threshold in screen space

* mouseEvent refactor tsc errors fixed

* cleanups, extract getTanPreviousPoint function

* add snap line support when previous segment is ARC

* small cleanups

* remove unused planeNodePath param from onDragSegment

* renaming

* Enable snapping when placing the segment point in onClick

* refactor getSnappedDragPoint to include axis intersection

* handle snapping to both axis and tangent direction

* snap refinements

* small cleanups

* lint

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* generate tag for previous arc when snapping current straight segment

* using previous arc's tag in snapped angledLine

* angledLine uses object instead of array now

* use more general snap object instead

* snap tangent line visualized when snapping occurs

* remove unused scale param from createLine

* prettier

* fix bug where segment body is not drawn

* fix generated kcl error introduced in merge from main - modifiedAst needs to be passed to addNewSketchLn

* add support for snapping to negative tangent direction

* fix findTangentDirection for THREE_POINT_ARC_SEGMENT

* fix tsc error by introducing overrideExpr

* fix missing ccw for 3 point arc, fix tan_previous_point calculation for 3 point arcs

* resolve clippy until confirmation for circle radius

* fix runtime error when drawing a 3 point arc

* add unit tests to closestPointoOnRay

* unrelated react warning fixed

* add playwright test for tangent snapping

* better fix for tan_previous_point

* fix lint

* add simulation test for tangent_to_3_point_arc

* Fix simulation test output

* Add missing simulation test output files

* fix tangent snapping bug: use current group instead of last group in activeSegments

* make testcombos.test happy

* cleanup merge

* fix merge mistake, tsc error

* update tangent_to_3_point_arc simulation test

* fix angledLine related breaking tests

* minimum distance added before snapping to tangent

* circle is always ccw regardless of the order of points for tangential info calculation

* fix snapping when different unit is used other than mm

* update test: Straight line snapping to previous tangent

* update rust snapshot test

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
This commit is contained in:
Andrew Varga
2025-04-14 23:51:14 +02:00
committed by GitHub
parent add1b21503
commit d0e9b111af
26 changed files with 1556 additions and 129 deletions

View File

@ -0,0 +1,156 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands tangent_to_3_point_arc.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": -1.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 100.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 0.0,
"y": 120.0,
"z": 0.0
},
"relative": true
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "arc_to",
"interior": {
"x": 300.0,
"y": 100.0,
"z": 0.0
},
"end": {
"x": 200.0,
"y": -100.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -99.8038,
"y": -6.2608,
"z": 0.0
},
"relative": true
}
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart tangent_to_3_point_arc.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,14 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[43, 82, 0]"]
3["Segment<br>[88, 112, 0]"]
4["Segment<br>[118, 209, 0]"]
5["Segment<br>[215, 292, 0]"]
end
1["Plane<br>[12, 29, 0]"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
```

View File

@ -0,0 +1,490 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of parsing tangent_to_3_point_arc.kcl
---
{
"Ok": {
"body": [
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 0,
"id": {
"commentStart": 0,
"end": 0,
"name": "sketch001",
"start": 0,
"type": "Identifier"
},
"init": {
"arguments": [
{
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "XZ",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startSketchOn",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 0,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
"type": "VariableDeclaration"
},
{
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 0,
"id": {
"commentStart": 0,
"end": 0,
"name": "profile001",
"start": 0,
"type": "Identifier"
},
"init": {
"body": [
{
"arguments": [
{
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "100.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 100.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "0.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "sketch001",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "startProfileAt",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "end",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "0.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "120.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 120.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "line",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"commentStart": 0,
"end": 0,
"properties": [
{
"commentStart": 0,
"end": 0,
"key": {
"commentStart": 0,
"end": 0,
"name": "interior",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "300.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 300.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "100.0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 100.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
},
{
"commentStart": 0,
"end": 0,
"key": {
"commentStart": 0,
"end": 0,
"name": "end",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 0,
"elements": [
{
"commentStart": 0,
"end": 0,
"raw": "200.00",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 200.0,
"suffix": "None"
}
},
{
"argument": {
"commentStart": 0,
"end": 0,
"raw": "100.00",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 100.0,
"suffix": "None"
}
},
"commentStart": 0,
"end": 0,
"operator": "-",
"start": 0,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"start": 0,
"type": "ObjectExpression",
"type": "ObjectExpression"
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
},
{
"commentStart": 0,
"end": 0,
"start": 0,
"type": "TagDeclarator",
"type": "TagDeclarator",
"value": "seg01"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "arcTo",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "angle",
"start": 0,
"type": "Identifier"
},
"arg": {
"arguments": [
{
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "seg01",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name",
"type": "Name"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "tangentToEnd",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 0,
"end": 0,
"name": "length",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 0,
"end": 0,
"raw": "100.00",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 100.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"commentStart": 0,
"end": 0,
"name": "angledLine",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Name"
},
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 0,
"end": 0,
"start": 0,
"type": "PipeExpression",
"type": "PipeExpression"
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 0,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
"type": "VariableDeclaration"
}
],
"commentStart": 0,
"end": 0,
"start": 0
}
}

View File

@ -0,0 +1,11 @@
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([100.0, 0.0], sketch001)
|> line(end = [0.0, 120.0])
|> arcTo({
interior = [300.0, 100.0],
end = [200.00, -100.00]
}, %, $seg01)
|> angledLine(
angle = tangentToEnd(seg01),
length = 100.00
)

View File

@ -0,0 +1,21 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed tangent_to_3_point_arc.kcl
---
[
{
"labeledArgs": {
"planeOrSolid": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
}
]

View File

@ -0,0 +1,208 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing tangent_to_3_point_arc.kcl
---
{
"profile001": {
"type": "Sketch",
"value": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
100.0,
0.0
],
"tag": null,
"to": [
100.0,
120.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
100.0,
120.0
],
"p1": [
100.0,
120.0
],
"p2": [
300.0,
100.0
],
"p3": [
200.0,
-100.0
],
"tag": {
"commentStart": 202,
"end": 208,
"start": 202,
"type": "TagDeclarator",
"value": "seg01"
},
"to": [
200.0,
-100.0
],
"type": "ArcThreePoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
200.0,
-100.0
],
"tag": null,
"to": [
100.1962,
-106.2608
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XZ",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"yAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
100.0,
0.0
],
"to": [
100.0,
0.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"tags": {
"seg01": {
"type": "TagIdentifier",
"value": "seg01"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"seg01": {
"type": "TagIdentifier",
"type": "TagIdentifier",
"value": "seg01"
},
"sketch001": {
"type": "Plane",
"value": {
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XZ",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"yAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0,
"units": {
"type": "Mm"
}
},
"zAxis": {
"x": 0.0,
"y": -1.0,
"z": 0.0,
"units": {
"type": "Mm"
}
},
"units": {
"type": "Mm"
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,12 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing tangent_to_3_point_arc.kcl
---
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([100.0, 0.0], sketch001)
|> line(end = [0.0, 120.0])
|> arcTo({
interior = [300.0, 100.0],
end = [200.0, -100.0]
}, %, $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = 100.0)