Commit graph CultLib/tests/GameCult.Geometry.Tests/SurfaceNetsTests.cs
Author SHA1 Message Date
Meta Vens
20ac3b0b6c Collapse CultVec2, CultVec3 and CultRect into CultMath float2, float3 and rect
GameCult.Geometry no longer carries vector or rectangle values. CultCircle and
CultSphere hold float2/float3, the isosurface and surface-nets extractors take
float3 origin, and the per-call conversion to float3 is gone. Their MessagePack
bytes are unchanged (pinned against the pre-collapse encodings), now produced
by CultMathResolver through the default CultCache options.

This is a breaking change to the GameCult.Geometry public API.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:18:09 +02:00
Meta Vens
d64de1b69d fix: reject non-finite isoValue and origin in Extract
samples and cellSize were validated but isoValue and origin were not:
iso = NaN or +inf silently returned an empty mesh, and origin = NaN gave
NaN positions. Extend Extract's existing top-of-method validation authority
to reject non-finite isoValue and non-finite origin components with
ArgumentException, matching the existing style, with tests for each
component.

Overflow at extreme magnitudes (cellSize ~3e38, or finite samples whose
interpolation overflows to inf) is a separate, float-domain limit rather
than a validated-input error; documented in the XML doc and provenance
notes, deliberately not range-checked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:31:44 +02:00
Meta Vens
b4db5cb6ed test: cover CultGeometryGridEdge.Equals(object) behaviourally
Mutating obj is CultGeometryGridEdge other && Equals(other) to && true
passed the suite: nothing exercised object.Equals directly with a mismatched
X/Y/Z/Axis, null, or an unrelated type. Add a behavioural test that checks
each component independently, rejects null and other types, and agrees with
the typed Equals and GetHashCode.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 20:29:00 +02:00
Meta Vens
6a4b0ed21f Add tests for surface-nets F1/F3/F4/F6/F7 mutation findings
- Fixed An_extremely_small_edge_delta_falls_back_to_the_edge_midpoint (renamed
  A_tiny_but_normal_edge_delta_...): it pinned the wrong value (1/6) for the
  fallback that F3's production commit deleted; now asserts the exact
  interpolated value, hand-derived in double precision independently of
  Interpolate. Added a genuinely subnormal-delta sibling test.

- Added two more vertex-placement fixtures (crossing counts 4 and 6) to kill
  the sum/count -> sum/3 mutant, each with a hand-derived expected mean.
  Counts of 1 and 2 from the finding are not used: a single cell's 12 edges
  form the cube graph Q3 (3-regular, 8 vertices), whose edge-cut size for any
  corner sign pattern is never 1 or 2 for any nonzero cut (minimum nonzero
  cut is 3, already covered by the existing symmetric/unequal fixtures) -
  see the fork note in this cut's report.

- Added three corner-order pinning tests (one per axis), each asserting the
  exact welded vertex at each of Quads[0..3] for a chosen edge against a
  hand-computed position, including the axis-1 v1/v3 swap that F4's fixed
  OrientationSign now performs. These kill the axis-0-mirrored, c0/c2-swapped
  and equivalent per-axis corner-order mutants.

- Added four degenerate-quad orientation tests (sample exactly at iso,
  large-origin/tiny-cellSize sphere, octahedron at iso, tiny-tolerance
  sphere) asserting every shared undirected edge is traversed in opposite
  directions (net zero), via a new AssertEdgeDirectionsBalance helper that
  also covers the 4-use case. Restricted the existing
  Every_quad_winds_outward_from_inside_to_outside test's geometric check to
  non-degenerate (non-zero cross product) quads, per spec.

- Added Grid_edge_inequality_is_the_negation_of_equality (F6: != is compiler-
  mandated alongside ==, and needed its own direct test) and
  A_non_finite_sample_is_rejected (F7: NaN and +-Infinity samples).

All 38 SurfaceNetsTests pass; the 7 pre-existing GeometryDocumentTests
failures from CultLib commit e420410 are untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 19:30:14 +02:00
Meta Vens
af39e05c21 Kill mutation survivors: degenerate fixtures, missing axis and edge tests
A --since:29e50ad Stryker pass found real gaps, all inside this cut's own
files:

- vertex-placement and normals fixtures anchored a vertex at the world
  origin, so a mutated (+ instead of -) or dropped cellSize multiply was
  invisible against a zero operand; moved them off the origin;
- the cube normals test only checked length, and three orthogonal
  +-2-length face contributions summed to the same length no matter which
  one a mutant negated; now checks the exact expected direction per vertex;
- the open-boundary rule only had an X-axis test, leaving TryGetQuadCells's
  Y- and Z-axis guards (and TryGetOtherEndpoint's Y/Z cases) uncovered;
  added the Y- and Z-axis twins of the existing plane test;
- the 1e-20 near-zero-delta fallback in Interpolate was never exercised;
  added a fixture with an edge delta of ~3e-21;
- CultGeometryGridEdge's Equals and ToString had no direct test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 18:38:15 +02:00
Meta Vens
dcfb267ac7 Fix the checkerboard fixture's open-boundary contamination
The 4x4x4 pure-checkerboard field had no fully-interior cell: every active
cell bordered the array edge, so some crossing edges lost a quad to the open-
boundary rule and edge usage came out odd (observed: all-3) for reasons
unrelated to the ambiguity the test means to exercise. Wrapped the
checkerboard in a one-sample uniform-outside margin (5x5x5 grid, checkerboard
only on samples 1..3) so every crossing edge under test keeps all four
surrounding cells in range, isolating the even-but-not-2 claim from
open-boundary effects.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 18:15:28 +02:00
Meta Vens
7a76b89a94 Fix expression-tree-incompatible test lambdas for FluentAssertions OnlyContain
Two spots failed to build: a method-group reference to float.IsFinite and an
`is 1 or 2` pattern inside a lambda that FluentAssertions compiles as an
Expression<Func<T, bool>>; expression trees can't contain pattern-matching
`is`, and a method group isn't implicitly convertible to an expression tree
either. Rewritten as explicit lambdas with `==`/`||`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 18:10:19 +02:00
Meta Vens
09a85edc47 Test surface nets naming, orientation, welding, and normals; scope Stryker to it
Adds SurfaceNetsTests.cs and QuadNormalsTests.cs covering the sign
convention, edge naming, outward winding, vertex placement (midpoint and
unequal-crossing means, origin/cellSize), closed-sphere welding and
Euler characteristic, an ambiguous checkerboard cell's even-but-not-2 edge
usage, open-boundary quad suppression, determinism/ordering, and
face-weighted normals (sliver-vs-large-quad area weighting, unit cube
normals, zero-area/untouched-vertex degenerate case). Adds
stryker-config.json (vstest runner; this project is NUnit 4, not xunit.v3)
and records GameCult.Geometry as scoped, diff-only, in
docs/mutation-testing.md's follow-ups.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 18:06:54 +02:00