Skip to content

Surface evaluation accepts a left-handed frame, and three call sites disagree on frame validity #95

Description

@GeneralPawz

Problem

Three call sites each carried their own frame validity rule, under three different tolerance policies, and only two of the three checked handedness.

Site Tolerance used Handedness checked
sampled/field/src/config.rs tolerance.angular() yes
execution/dispatch/src/section.rs angular, clamped to 1e-6 yes
parametric/evaluate/src/surface.rs hardcoded 1e-9 no

Two consequences.

A left-handed surface frame was accepted. to_local in evaluate/surface.rs checked unit length and pairwise perpendicularity but never the triple product. A mirrored basis satisfies both, so invert accepted it and returned reflected parameters. The reflection is self-consistent: those parameters round-trip through the same bad frame and look correct.

Surface evaluation ignored the caller's tolerance. invert already takes a Tolerance, but frame validation used a hardcoded 1e-9 regardless of the model unit.

Reproduction

Both added to crates/algorithms/parametric/evaluate/tests/invert.rs:

a_left_handed_surface_frame_is_refused ... FAILED

A Frame3 with z: -Vec3::Z and identity x/y is orthonormal, mirrored, and was accepted.

Resolution

SpaceFrame in axiolid-core: origin plus a right-handed orthonormal triad, private fields, to_local/to_world. It is the 3-axis counterpart to PlaneFrame and shares its error vocabulary, now renamed FrameError with a new NotRightHanded variant.

  • Unit length, perpendicularity and handedness are dimensionless, so all three are judged against the ANGULAR tolerance.
  • Handedness compares the triple product against +1. On an orthonormal triad that value is exactly +1 right-handed and -1 mirrored, so the two are separated by a margin of 2 rather than by a tolerance.
  • Private fields make an invalid frame unrepresentable, not merely rejected.

All three call sites now delegate. dispatch/section.rs keeps its deliberate 1e-6 tolerance ceiling by capping before it calls the shared validator, so tighter caller tolerances still apply and looser ones still do not. evaluate/surface.rs threads its existing caller tolerance through instead of ignoring it.

Verification

  • workspace 1113 passed / 0 failed, GATE PASSED
  • mutation: deleting the handedness check fails a_left_handed_basis_is_refused in core AND a_left_handed_surface_frame_is_refused in the consumer, so the guard is proven at both layers
  • zero hand-rolled orthonormality checks remain in production code

Landed in 6181dd2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

needs-triageFiled but not yet accepted, sized, or scheduled

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions