Kernel rig: fairing leaves a flat patch flat and a face with no free control rows as it was; zero strength is refused

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 f861f44e1d
commit 3d080e96a3
7 changed files with 267 additions and 0 deletions
@@ -3,3 +3,4 @@
# that fails and is not listed fails it, and so does a listed case that passes: a fix removes its
# line in the same pull request.
# Baseline: rig-cases-surfaces 45f69c0e5 with SMLib 60b1c6a, aarch64 Linux.
cov-fair-single-span-face-has-nothing-free-to-move surface.fair refuses a face of degree 1 one way ("a fairness term does not fit the net's degrees"): kernel/src/fair.rs checks its second-derivative terms against the net's degrees instead of fairing only the direction that has them
@@ -0,0 +1,23 @@
{
"sources": [],
"what": "fair on a flat boundary patch, with its edges free: a plane has no curvature to even out, so it stays the flat square",
"source": "analytic",
"method": "the Coons patch of the 20 x 20 square lies in z = 0; fairing moves control points to flatten curvature variation, of which a plane has none, and never past the tolerance: area 400, box z 0..0, 4 free edges",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 400.0,
"bbox": {
"min": [
0,
0,
0
],
"max": [
20,
20,
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": "Square"
}
},
{
"command": "sketch.rectangle.two_point",
"params": {
"p0": [
0,
0
],
"p1": [
20,
20
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.boundary",
"params": {
"sketch": "Square",
"curves": [
"l1",
"l2",
"l3",
"l4"
],
"body_name": "Patch"
}
},
{
"command": "surface.fair",
"params": {
"body": "Patch",
"iterations": 20,
"keep_edges": false
}
}
]
}
@@ -0,0 +1,26 @@
{
"sources": [],
"what": "fair on a single-span cubic extrusion holding its edges: every control row is a boundary row or the one next to it, so nothing moves",
"source": "analytic",
"method": "the face: the Bezier (0,0), (13,8), (27,-8), (40,0) on XZ extruded 20 along -y or +y, B-spline degree (3, 1), one span each way. keep_edges holds the two boundary rows each side and the rows next to them: across the cubic that is all 4 rows, so the surface is unchanged: area = curve length 41.3983 (Gauss-Legendre 64) x 20 = 827.966",
"valid": false,
"body_count": 1,
"faces": 1,
"boundary_edges": 4,
"area_mm2": 827.9663653036151,
"surface_types": [
"bspline"
],
"splines": [
{
"degree": [
3,
1
],
"spans": [
1,
1
]
}
]
}
@@ -0,0 +1,72 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "Wave"
}
},
{
"command": "sketch.spline.control_point",
"params": {
"points": [
[
0,
0
],
[
13,
8
],
[
27,
-8
],
[
40,
0
]
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "Wave",
"curves": [
"s1"
],
"distance": 20,
"body_name": "Wave"
}
},
{
"command": "surface.fair",
"params": {
"body": "Wave",
"iterations": 10
}
}
]
}
@@ -0,0 +1,8 @@
{
"sources": [],
"what": "fair with strength 0: refused, a step of nothing",
"source": "invariants",
"method": "strength is the fraction of the fairing step, greater than 0 and at most 1",
"outcome": "refused",
"refusal": "`strength` must be greater than 0 and at most 1"
}
@@ -0,0 +1,72 @@
{
"commands": [
{
"command": "sketch.create",
"params": {
"plane": {
"origin": [
0,
0,
0
],
"x_dir": [
1,
0,
0
],
"y_dir": [
0,
0,
1
]
},
"name": "Wave"
}
},
{
"command": "sketch.spline.control_point",
"params": {
"points": [
[
0,
0
],
[
13,
8
],
[
27,
-8
],
[
40,
0
]
]
}
},
{
"command": "sketch.finish",
"params": {}
},
{
"command": "surface.extrude",
"params": {
"sketch": "Wave",
"curves": [
"s1"
],
"distance": 20,
"body_name": "Wave"
}
},
{
"command": "surface.fair",
"params": {
"body": "Wave",
"strength": 0
}
}
]
}