Kernel rig: extend, extrude, loft, patch, revolve, stitch and sweep surfaces, a normal case and an edge case each, with their exact areas and surface kinds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-29 17:03:27 -04:00
committed by Irakli Kourtis
parent 3d080e96a3
commit 75353cb042
32 changed files with 1585 additions and 0 deletions
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a quarter-cylinder sheet r 10, 20 high, its top arc extended naturally by 5: the cylinder continued to 25 high",
"source": "analytic",
"method": "natural extension keeps a surface of revolution on itself: the top arc moves 5 along the rulings: A = (pi/2) 10 25 = 392.70, one cylinder face, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 392.6990816987241,
"surface_types": [
"cylinder"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
10,
10,
25
]
}
}
@@ -0,0 +1,73 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Arc"
}
},
{
"command": "sketch.arc.center_point",
"params": {
"center": [
0,
0
],
"start": [
10,
0
],
"end": [
0,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "Arc",
"curves": [
"a1"
],
"distance": 20,
"body_name": "Quarter"
}
},
{
"command": "surface.extend",
"params": {
"body": "Quarter",
"edges": [
[
9.84807753012208,
1.7364817766693033,
20
]
],
"distance": 5
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a 10 x 10 sheet's edge x = 10 extended naturally by 5: the plane continued to 15 x 10",
"source": "analytic",
"method": "a natural extension keeps a plane on itself: the face becomes x 0..15, y 0..10, area 150, one plane face, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 150.0,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
15,
10,
0
]
}
}
@@ -0,0 +1,65 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Sheet sketch"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
10,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.patch",
"params": {
"sketch": "Sheet sketch",
"body_name": "Sheet"
}
},
{
"command": "surface.extend",
"params": {
"body": "Sheet",
"edges": [
[
10,
5,
0
]
],
"distance": 5
}
}
]
}
@@ -0,0 +1,8 @@
{
"sources": [],
"what": "a tangent extension back to the surface's bounds: refused, only a natural one goes there",
"source": "invariants",
"method": "the bounds are the surface's own; a tangent continuation leaves the surface",
"outcome": "refused",
"refusal": "only a natural extension goes back to the surface's bounds"
}
@@ -0,0 +1,66 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Sheet sketch"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
10,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.patch",
"params": {
"sketch": "Sheet sketch",
"body_name": "Sheet"
}
},
{
"command": "surface.extend",
"params": {
"body": "Sheet",
"edges": [
[
10,
5,
0
]
],
"up_to": "bounds",
"mode": "tangent"
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a line extruded symmetric 10 as a surface with the total-distance convention: 5 each side of the sketch plane",
"source": "analytic",
"method": "total distance 10 split evenly: the plane y = 0, x 0..10, z -5..5, area 100, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 100.0,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
-5
],
"max": [
10,
0,
5
]
}
}
@@ -0,0 +1,60 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "S"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
10,
0
]
],
"infer": false
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "S",
"curves": [
"l1"
],
"distance": 10,
"direction": "symmetric",
"convention": "total_distance",
"body_name": "Wall"
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a line extruded symmetric 10 as a surface: surface.extrude's distance is per side (its legacy convention, kept by default), so 10 each way",
"source": "analytic",
"method": "surface.extrude without `convention` keeps legacy_per_side (crates/engine/src/cmd/features.rs, extrude_convention_tests): the plane y = 0, x 0..10, z -10..10, area 200, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 200.0,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
-10
],
"max": [
10,
0,
10
]
}
}
@@ -0,0 +1,59 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "S"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
10,
0
]
],
"infer": false
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "S",
"curves": [
"l1"
],
"distance": 10,
"direction": "symmetric",
"body_name": "Wall"
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a quarter arc r 10 extruded 20 as a surface: a quarter cylinder",
"source": "analytic",
"method": "A = (pi/2) 10 20 = 314.16; one cylinder face; its 4 edges free",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 314.1592653589793,
"surface_types": [
"cylinder"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
10,
10,
20
]
}
}
@@ -0,0 +1,59 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Arc"
}
},
{
"command": "sketch.arc.center_point",
"params": {
"center": [
0,
0
],
"start": [
10,
0
],
"end": [
0,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "Arc",
"curves": [
"a1"
],
"distance": 20,
"body_name": "Quarter"
}
}
]
}
@@ -0,0 +1,23 @@
{
"sources": [],
"what": "a smooth surface loft through three equal coaxial circles r 10 at z 0, 10, 20: the cylinder",
"source": "analytic",
"method": "every section is the same circle moved along z, so the interpolation through them is that circle swept straight: A = 2 pi 10 20 = 1256.64, bbox r 10, z 0..20",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 2,
"area_mm2": 1256.6370614359173,
"bbox": {
"min": [
-10,
-10,
0
],
"max": [
10,
10,
20
]
}
}
@@ -0,0 +1,141 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "C0"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 10
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
10
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "C1"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 10
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
20
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "C2"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 10
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.loft",
"params": {
"sections": [
{
"sketch": "C0",
"curves": [
"c1"
]
},
{
"sketch": "C1",
"curves": [
"c1"
]
},
{
"sketch": "C2",
"curves": [
"c1"
]
}
],
"body_name": "Tube"
}
}
]
}
@@ -0,0 +1,23 @@
{
"sources": [],
"what": "a surface loft between a circle r 10 at z 0 and a circle r 5 at z 10: ruled between two sections, a cone frustum",
"source": "analytic",
"method": "two sections loft ruled: corresponding points joined by lines, which for coaxial circles is the frustum; A = pi (10 + 5) sqrt(5^2 + 10^2) = 526.861; one face, 2 free circles",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 2,
"area_mm2": 526.8611048280544,
"bbox": {
"min": [
-10,
-10,
0
],
"max": [
10,
10,
10
]
}
}
@@ -0,0 +1,98 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Low"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 10
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
10
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "High"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 5
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.loft",
"params": {
"sections": [
{
"sketch": "Low",
"curves": [
"c1"
]
},
{
"sketch": "High",
"curves": [
"c1"
]
}
],
"body_name": "Funnel"
}
}
]
}
@@ -0,0 +1,25 @@
{
"sources": [],
"what": "a box with its top taken away, the rim patched (g0) and stitched in: the box again",
"source": "analytic",
"method": "the rim is a planar loop and the patch g0, so it is the exact plane z = 10, 20 x 10; stitched, the closed box 20 x 10 x 10: V = 2000, A = 1000, 6 faces",
"body_count": 1,
"faces": 6,
"volume_mm3": 2000.0,
"area_mm2": 1000.0,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
20,
10,
10
]
}
}
@@ -0,0 +1,73 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 20,
"width": 10,
"height": 10,
"body_name": "Box"
}
},
{
"command": "surface.unstitch",
"params": {
"body": "Box",
"faces": [
[
10,
5,
10
]
],
"body_name": "Top"
}
},
{
"command": "solid.remove",
"params": {
"bodies": [
"Top"
]
}
},
{
"command": "surface.patch",
"params": {
"body": "Box",
"edges": [
[
10,
0,
10
],
[
20,
5,
10
],
[
10,
10,
10
],
[
0,
5,
10
]
],
"body_name": "Lid"
}
},
{
"command": "surface.stitch",
"params": {
"bodies": [
"Box",
"Lid"
]
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a planar patch of the region between a 20 x 20 square and a circle r 4 inside it (picked by a point in the ring): a square with a hole",
"source": "analytic",
"method": "A = 400 - 16 pi = 349.73, one plane face, free edges 4 sides + the circle",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 5,
"area_mm2": 349.7345175425633,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
20,
20,
0
]
}
}
@@ -0,0 +1,69 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Holed sketch"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
20,
20
]
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
10,
10
],
"radius": 4
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.patch",
"params": {
"sketch": "Holed sketch",
"profiles": [
{
"point": [
2,
2
]
}
],
"body_name": "Holed"
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a line parallel to the axis at r 10 revolved a full turn as a surface: the cylinder wall",
"source": "analytic",
"method": "A = 2 pi 10 20 = 1256.64, one cylinder face, the 2 end circles free",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 2,
"area_mm2": 1256.6370614359173,
"surface_types": [
"cylinder"
],
"bbox": {
"min": [
-10,
-10,
0
],
"max": [
10,
10,
20
]
}
}
@@ -0,0 +1,61 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "P"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
10,
0
],
[
10,
20
]
],
"infer": false,
"ids": [
"l1"
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.revolve",
"params": {
"sketch": "P",
"curves": [
"l1"
],
"axis": "y",
"body_name": "Tube"
}
}
]
}
@@ -0,0 +1,17 @@
{
"sources": [],
"what": "a quarter arc r 10 about the axis revolved half a turn: half a hemisphere, on the sphere",
"source": "analytic",
"method": "a hemisphere is 2 pi r^2; half a turn of it pi r^2 = 314.16; one sphere face; free edges: the equator half-circle and the two meridian arcs (the pole a point, [3, 4])",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": [
3,
4
],
"area_mm2": 314.1592653589793,
"surface_types": [
"sphere"
]
}
@@ -0,0 +1,60 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "P"
}
},
{
"command": "sketch.arc.center_point",
"params": {
"center": [
0,
0
],
"start": [
10,
0
],
"end": [
0,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.revolve",
"params": {
"sketch": "P",
"curves": [
"a1"
],
"axis": "y",
"angle": "180 deg",
"body_name": "Dome"
}
}
]
}
@@ -0,0 +1,17 @@
{
"sources": [],
"what": "two 10 x 10 sheets sharing the edge x = 10, stitched: one surface body of two faces",
"source": "analytic",
"method": "area 200; the shared edge used by both faces, the outline's 6 edges free; B goes into A",
"valid": false,
"body_count": 1,
"faces": [
1,
2
],
"boundary_edges": 6,
"area_mm2": 200.0,
"surface_types": [
"plane"
]
}
@@ -0,0 +1,107 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "A sketch"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
10,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.patch",
"params": {
"sketch": "A sketch",
"body_name": "A"
}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "B sketch"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
10,
0
],
"p1": [
20,
10
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.patch",
"params": {
"sketch": "B sketch",
"body_name": "B"
}
},
{
"command": "surface.stitch",
"params": {
"bodies": [
"A",
"B"
]
}
}
]
}
@@ -0,0 +1,11 @@
{
"sources": [],
"what": "a box's top unstitched and stitched back: the closed box again",
"source": "analytic",
"method": "the six faces close: the solid 20 x 10 x 10, V = 2000, A = 1000, 6 faces, no free edge",
"body_count": 1,
"faces": 6,
"volume_mm3": 2000.0,
"area_mm2": 1000.0,
"boundary_edges": 0
}
@@ -0,0 +1,36 @@
{
"commands": [
{
"command": "solid.box",
"params": {
"length": 20,
"width": 10,
"height": 10,
"body_name": "Box"
}
},
{
"command": "surface.unstitch",
"params": {
"body": "Box",
"faces": [
[
10,
5,
10
]
],
"body_name": "Top"
}
},
{
"command": "surface.stitch",
"params": {
"bodies": [
"Box",
"Top"
]
}
}
]
}
@@ -0,0 +1,23 @@
{
"sources": [],
"what": "a circle r 10 swept 20 up a straight path, scaled to half at the end: a cone frustum wall",
"source": "analytic",
"method": "the scale runs linearly along the path: r 10 at z 0 to r 5 at z 20, a frustum: A = pi (10 + 5) sqrt(5^2 + 20^2) = 971.484; one face, 2 free circles",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 2,
"area_mm2": 971.4838757561392,
"bbox": {
"min": [
-10,
-10,
0
],
"max": [
10,
10,
20
]
}
}
@@ -0,0 +1,99 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "C"
}
},
{
"command": "sketch.circle.center",
"params": {
"center": [
0,
0
],
"radius": 10
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "P"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
0,
20
]
],
"infer": false
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.sweep",
"params": {
"sketch": "C",
"curves": [
"c1"
],
"path_sketch": "P",
"path": [
"l1"
],
"scale": "1/2",
"body_name": "Cone"
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "a line swept along a straight path square to it: a plane strip",
"source": "analytic",
"method": "the line x 0..10 swept 20 along +z: the plane y = 0, x 0..10, z 0..20, area 200, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 200.0,
"surface_types": [
"plane"
],
"bbox": {
"min": [
0,
0,
0
],
"max": [
10,
0,
20
]
}
}
@@ -0,0 +1,104 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
1,
0
]
},
"name": "Prof"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
10,
0
]
],
"infer": false
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "Path"
}
},
{
"command": "sketch.line",
"params": {
"points": [
[
0,
0
],
[
0,
20
]
],
"infer": false
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.sweep",
"params": {
"sketch": "Prof",
"curves": [
"l1"
],
"path_sketch": "Path",
"path": [
"l1"
],
"body_name": "Wall"
}
}
]
}