pub struct OffsetEvaluator<'a> { /* private fields */ }Expand description
The pointwise offset evaluator, bound to one carrier and one orientation convention.
Construction is free — it stores three references and reads nothing — so a
caller inside a Newton loop may build one per call without paying anything.
site is a short stable label used only by [offset_normal_diagnostic].
Implementations§
Source§impl<'a> OffsetEvaluator<'a>
impl<'a> OffsetEvaluator<'a>
pub fn new( site: &'static str, surface: &'a NurbsSurface, convention: OffsetNormal, ) -> Self
Sourcepub fn normal(&self, u: f64, v: f64) -> Result<Vec3, String>
pub fn normal(&self, u: f64, v: f64) -> Result<Vec3, String>
The unit normal alone, for callers that only need the direction (a residual check, or an affine offset that shifts the whole control net by one vector). Evaluates the point only on the lanes that need it.
Sourcepub fn on_real_carrier(
&self,
u: f64,
v: f64,
tolerance: f64,
) -> Result<bool, String>
pub fn on_real_carrier( &self, u: f64, v: f64, tolerance: f64, ) -> Result<bool, String>
Whether the carrier evaluated at (u, v) is the REAL surface, or its
fiction — the question Self::at cannot answer for itself.
OffsetNormal::Raw evaluates through deriv1_extended, which
continues an OPEN direction along its boundary tangent plane without
bound instead of refusing. A solve with no solution on the real
carrier therefore converges on that continuation and reports a
residual of zero, because the extended point IS a genuine root of the
extended system. Callers must ask here, at convergence.
Being outside the domain is NOT by itself the fault, and testing for that alone over-refuses badly. Three cases:
- a CLOSED direction wraps (
rem_euclid) back onto the real surface, so it is always faithful — which is why a full cylinder cannot exhibit the problem and a trimmed arc can; - an open direction along which the surface is RULED extends exactly. A plane is a bounded bilinear patch in this kernel, and its continuation is still that plane; a cylinder’s axial direction continues as the same cylinder. A re-entrant corner touching a wall’s carrier beyond its patch is real geometry and must keep working;
- an open direction with non-zero NORMAL CURVATURE is where the ruled continuation leaves the surface, and that is the fiction.
So the test is geometric, not a domain comparison and not keyed on
NurbsSurface::analytic — an analytic-keyed guard silently no-ops on
every fitted patch. The ruled extension drops the second-order term, so
over an excursion d it departs the true surface by about
½·d²·|S_ii·n|, where S_ii·n is the second-fundamental-form
coefficient along the exceeded direction (Golovanov §4.12’s b11/b22,
the same quantities the marcher’s step budget uses). Faithful when that
departure is within tolerance.
The bound is QUADRATIC in the excursion, so a parameter a rounding bit past the boundary is faithful by many orders and a real excursion onto a curved carrier is unfaithful by many orders. The exact threshold barely matters; passing the caller’s own convergence bar keeps the answer honest to the accuracy it claims.