The oracle no longer uses Fusion measurements. tests/oracle/<case>/ now holds the 76 recipes (our own format, with recorded measurements and tool-specific fields removed) and an expected.json per case: - 55 analytic cases: closed-form values from tools/oracle-analytic/ (stdlib Python, formulas in each case's "method"). - 21 FreeCAD cases: the same recipe built with FreeCAD's public scripting API by tools/freecad-oracle/ (an external program, not a dependency), with a reference.stl for 20. solvecraft-cli oracle compares body count, volume, area, centre of mass, bbox, face counts where the geometry fixes them, and, against reference.stl, the sampled Hausdorff distance and the principal moments (spatial.rs from #301). cargo xtask oracle reads tests/oracle, writes docs/oracle.md with the source of each value, and supports known_failure marks for tracked bugs. CI runs it on every PR; a manual workflow regenerates the FreeCAD values. step-corpus, seam normalisation and the through-all emulation, which only existed to compare with Fusion, are removed. 75/76 pass; 75-sm-bracket-holes is a known failure (#296). Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT Co-authored-by: bherbruck <bherbruck@herbrucks.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
578 lines
7.8 KiB
JSON
578 lines
7.8 KiB
JSON
{
|
|
"id": "28-blind-pocket-fillets",
|
|
"name": "Blind pocket with filleted corners",
|
|
"description": "80x60x20 block; 50x30 rectangle on top face cut 8 mm deep (blind); 4 vertical pocket corner edges filleted R5, then pocket floor edges R2.",
|
|
"exercises": [
|
|
"extrude_cut",
|
|
"blind",
|
|
"fillet",
|
|
"concave_fillet"
|
|
],
|
|
"units": {
|
|
"length": "mm",
|
|
"angle": "deg",
|
|
"area": "mm2",
|
|
"volume": "mm3"
|
|
},
|
|
"conventions": {
|
|
"world": "right-handed; Z up. XY/XZ/YZ are the origin planes.",
|
|
"sketch_frame": "sketch-local 2D coords; world = plane.origin + x*plane.x_dir + y*plane.y_dir (origin in mm). Profile 'loops' list sketch entity ids.",
|
|
"point_refs": "'<id>.start' / '<id>.end' / '<id>.center' reuse (share) that existing sketch point; 'at' is its position when referenced.",
|
|
"extrude_direction": "positive = along sketch plane normal unless stated",
|
|
"selections": "selected faces/edges carry 'point': a world-space point on the face / the edge's parametric midpoint; pick the nearest face/edge to it."
|
|
},
|
|
"parameters": [],
|
|
"features": [
|
|
{
|
|
"op": "sketch",
|
|
"name": "Block_sketch",
|
|
"plane": {
|
|
"ref": "XY",
|
|
"origin": [
|
|
0.0,
|
|
0.0,
|
|
0.0
|
|
],
|
|
"x_dir": [
|
|
1.0,
|
|
0.0,
|
|
0.0
|
|
],
|
|
"y_dir": [
|
|
0.0,
|
|
1.0,
|
|
0.0
|
|
],
|
|
"normal": [
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
]
|
|
},
|
|
"entities": [
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"at": [
|
|
0,
|
|
0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
80,
|
|
0
|
|
]
|
|
},
|
|
"id": "l1"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l1.end",
|
|
"at": [
|
|
80.0,
|
|
0.0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
80,
|
|
60
|
|
]
|
|
},
|
|
"id": "l2"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l2.end",
|
|
"at": [
|
|
80.0,
|
|
60.0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
0,
|
|
60
|
|
]
|
|
},
|
|
"id": "l3"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l3.end",
|
|
"at": [
|
|
0.0,
|
|
60.0
|
|
]
|
|
},
|
|
"end": {
|
|
"ref": "l1.start",
|
|
"at": [
|
|
0.0,
|
|
0.0
|
|
]
|
|
},
|
|
"id": "l4"
|
|
}
|
|
],
|
|
"constraints": [],
|
|
"dimensions": []
|
|
},
|
|
{
|
|
"op": "extrude",
|
|
"name": "Block",
|
|
"operation": "new",
|
|
"profiles": [
|
|
{
|
|
"sketch": "Block_sketch",
|
|
"loops": [
|
|
{
|
|
"outer": true,
|
|
"curves": [
|
|
"l1",
|
|
"l2",
|
|
"l3",
|
|
"l4"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"extent": {
|
|
"type": "distance",
|
|
"distance": 20,
|
|
"direction": "positive"
|
|
},
|
|
"result_bodies": [
|
|
"Block"
|
|
]
|
|
},
|
|
{
|
|
"op": "sketch",
|
|
"name": "PocketSketch",
|
|
"plane": {
|
|
"ref": "face: top of Block (z=20)",
|
|
"origin": [
|
|
0.0,
|
|
0.0,
|
|
20.0
|
|
],
|
|
"x_dir": [
|
|
1.0,
|
|
0.0,
|
|
0.0
|
|
],
|
|
"y_dir": [
|
|
0.0,
|
|
1.0,
|
|
0.0
|
|
],
|
|
"normal": [
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
],
|
|
"face": {
|
|
"type": "plane",
|
|
"normal_at_point_on_face": [
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
],
|
|
"plane_normal_outward": [
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
],
|
|
"point": [
|
|
40.0,
|
|
30.0,
|
|
20.0
|
|
]
|
|
}
|
|
},
|
|
"entities": [
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"at": [
|
|
15.0,
|
|
15.0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
65.0,
|
|
15.0
|
|
]
|
|
},
|
|
"id": "l1"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l1.end",
|
|
"at": [
|
|
65.0,
|
|
15.0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
65.0,
|
|
45.0
|
|
]
|
|
},
|
|
"id": "l2"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l2.end",
|
|
"at": [
|
|
65.0,
|
|
45.0
|
|
]
|
|
},
|
|
"end": {
|
|
"at": [
|
|
15.0,
|
|
45.0
|
|
]
|
|
},
|
|
"id": "l3"
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": {
|
|
"ref": "l3.end",
|
|
"at": [
|
|
15.0,
|
|
45.0
|
|
]
|
|
},
|
|
"end": {
|
|
"ref": "l1.start",
|
|
"at": [
|
|
15.0,
|
|
15.0
|
|
]
|
|
},
|
|
"id": "l4"
|
|
}
|
|
],
|
|
"constraints": [],
|
|
"dimensions": []
|
|
},
|
|
{
|
|
"op": "extrude",
|
|
"name": "Pocket",
|
|
"operation": "cut",
|
|
"profiles": [
|
|
{
|
|
"sketch": "PocketSketch",
|
|
"loops": [
|
|
{
|
|
"outer": true,
|
|
"curves": [
|
|
"l1",
|
|
"l2",
|
|
"l3",
|
|
"l4"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"extent": {
|
|
"type": "distance",
|
|
"distance": 8,
|
|
"direction": "negative"
|
|
},
|
|
"result_bodies": [
|
|
"Block"
|
|
]
|
|
},
|
|
{
|
|
"op": "fillet",
|
|
"name": "CornerFillet",
|
|
"type": "constant_radius",
|
|
"radius": 5,
|
|
"tangent_chain": false,
|
|
"edge_selection": "the 4 vertical pocket corner edges (z 12..20)",
|
|
"edges": [
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
65.0,
|
|
15.0,
|
|
20.0
|
|
],
|
|
"end": [
|
|
65.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
65.0,
|
|
15.0,
|
|
16.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
15.0,
|
|
15.0,
|
|
20.0
|
|
],
|
|
"end": [
|
|
15.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
15.0,
|
|
15.0,
|
|
16.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
65.0,
|
|
45.0,
|
|
20.0
|
|
],
|
|
"end": [
|
|
65.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
65.0,
|
|
45.0,
|
|
16.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
15.0,
|
|
45.0,
|
|
20.0
|
|
],
|
|
"end": [
|
|
15.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
15.0,
|
|
45.0,
|
|
16.0
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"op": "fillet",
|
|
"name": "FloorFillet",
|
|
"type": "constant_radius",
|
|
"radius": 2,
|
|
"tangent_chain": false,
|
|
"edge_selection": "all edges of the pocket floor (z=12) - 4 lines + 4 arcs",
|
|
"edges": [
|
|
{
|
|
"type": "arc",
|
|
"start": [
|
|
20.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
15.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"center": [
|
|
20.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"axis": [
|
|
0.0,
|
|
-0.0,
|
|
1.0
|
|
],
|
|
"point": [
|
|
16.464466094,
|
|
43.535533906,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
15.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
15.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
15.0,
|
|
30.0,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "arc",
|
|
"start": [
|
|
15.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
20.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"center": [
|
|
20.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"axis": [
|
|
0.0,
|
|
-0.0,
|
|
1.0
|
|
],
|
|
"point": [
|
|
16.464466094,
|
|
16.464466094,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
60.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
20.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
40.0,
|
|
15.0,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "arc",
|
|
"start": [
|
|
60.0,
|
|
15.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
65.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"center": [
|
|
60.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"axis": [
|
|
-0.0,
|
|
0.0,
|
|
1.0
|
|
],
|
|
"point": [
|
|
63.535533906,
|
|
16.464466094,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
65.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
65.0,
|
|
20.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
65.0,
|
|
30.0,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "arc",
|
|
"start": [
|
|
65.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
60.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"center": [
|
|
60.0,
|
|
40.0,
|
|
12.0
|
|
],
|
|
"axis": [
|
|
0.0,
|
|
-0.0,
|
|
1.0
|
|
],
|
|
"point": [
|
|
63.535533906,
|
|
43.535533906,
|
|
12.0
|
|
]
|
|
},
|
|
{
|
|
"type": "line",
|
|
"start": [
|
|
20.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"end": [
|
|
60.0,
|
|
45.0,
|
|
12.0
|
|
],
|
|
"point": [
|
|
40.0,
|
|
45.0,
|
|
12.0
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|