From 3d080e96a39883685e516411ca03daeedbd07eb4 Mon Sep 17 00:00:00 2001 From: jyviko <2501648+jyviko@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:03:27 -0400 Subject: [PATCH] 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 --- tests/kernel-cases/surfaces/KNOWN_FAILING | 1 + .../expected.json | 23 ++++++ .../recipe.json | 65 +++++++++++++++++ .../expected.json | 26 +++++++ .../recipe.json | 72 +++++++++++++++++++ .../expected.json | 8 +++ .../recipe.json | 72 +++++++++++++++++++ 7 files changed, 267 insertions(+) create mode 100644 tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/expected.json create mode 100644 tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/recipe.json create mode 100644 tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/expected.json create mode 100644 tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/recipe.json create mode 100644 tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/expected.json create mode 100644 tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/recipe.json diff --git a/tests/kernel-cases/surfaces/KNOWN_FAILING b/tests/kernel-cases/surfaces/KNOWN_FAILING index fe07e824ce..a514c68f37 100644 --- a/tests/kernel-cases/surfaces/KNOWN_FAILING +++ b/tests/kernel-cases/surfaces/KNOWN_FAILING @@ -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 diff --git a/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/expected.json b/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/expected.json new file mode 100644 index 0000000000..ec976528f1 --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/expected.json @@ -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 + ] + } +} diff --git a/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/recipe.json b/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/recipe.json new file mode 100644 index 0000000000..f658463293 --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-flat-patch-stays-flat/recipe.json @@ -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 + } + } + ] +} diff --git a/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/expected.json b/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/expected.json new file mode 100644 index 0000000000..212c473639 --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/expected.json @@ -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 + ] + } + ] +} diff --git a/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/recipe.json b/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/recipe.json new file mode 100644 index 0000000000..24099e120c --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-single-span-face-has-nothing-free-to-move/recipe.json @@ -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 + } + } + ] +} diff --git a/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/expected.json b/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/expected.json new file mode 100644 index 0000000000..7d910395c1 --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/expected.json @@ -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" +} diff --git a/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/recipe.json b/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/recipe.json new file mode 100644 index 0000000000..cb966d29db --- /dev/null +++ b/tests/kernel-cases/surfaces/cov-fair-zero-strength-refused/recipe.json @@ -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 + } + } + ] +}