Skip to main content

refine_crossing

Function refine_crossing 

Source
pub fn refine_crossing<S: Scalar>(
    curve: &NurbCurve<S, 4>,
    surface: &NurbSurface<S, 4>,
    t: S,
    uv: Vector2<S>,
) -> (S, Vector2<S>)
Expand description

Polish one isolated (t, uv) — as returned by curve_surface_intersect — by Newton on C(t) - S(u, v) = 0, three equations in the three unknowns t, u, v.

Subdivision and Newton divide the work: subdivision is the global method, reliably finding and separating every solution and recognizing coincidence even for a partial overlap, but converging only one bit per split; Newton cannot find anything but polishes an isolated solution quadratically. curve_surface_intersect deliberately does not apply this to everything it returns — most callers only need to know where and how many crossings there are, and refining changes results they already agree with. Call it when the parameter is about to be used as a split point, where the width genuinely matters: NurbCurve::split cannot absorb a min_subdivision_size-wide parameter (Boehm insertion amplifies it without bound), and a point evaluated at one is just as wide — which is how a wide crossing becomes a fat vertex and a fat sub-curve.

Every iterate but the last is sharpened, which is legitimate: it is only a seed for the next step. The final step is left unsharpened, so the returned widths honestly state how well the crossing is determined (see “Sharpen only where the value is a free choice” in AGENTS.md).

Infallible by construction: the incoming box is already a valid enclosure, so anything that stops Newton — a singular Jacobian at a tangential crossing or a pole, an iterate leaving the domain, a refined box disjoint from the one subdivision proved the solution lies in — just returns that box unchanged. Refinement can only tighten, never fail.