Skip to main content

brep_kernel/geometry/
pcurve.rs

1use crate::{
2    interpolate_curve, project_point_to_surface, project_point_to_surface_seeded, AnalyticSurface,
3    DiagnosticSeverity, KernelDiagnostics, KernelStage, KnotVector, NurbsCurve, NurbsSurface, Vec3,
4    Vec4, KNOT_IDENTITY_TOL,
5};
6
7const EPSILON: f64 = crate::tolerance::FP_FLOOR;
8const LINEAR_TOLERANCE: f64 = crate::tolerance::DEFAULT_MODEL;
9
10/// Coarse clocks only: no per-station timing overhead in a measured fit.
11struct PcurvePhaseClock {
12    started: Option<web_time::Instant>,
13    phase: &'static str,
14    samples: usize,
15    tracking: bool,
16}
17impl PcurvePhaseClock {
18    fn new(phase: &'static str, samples: usize, tracking: bool) -> Self {
19        Self { started: crate::profile::profile_enabled().then(web_time::Instant::now), phase, samples, tracking }
20    }
21}
22impl Drop for PcurvePhaseClock {
23    fn drop(&mut self) {
24        if let Some(started) = self.started {
25            crate::imprint::profile_emit(format_args!("pcurve.phase_time phase={} initial_samples={} tracking={} ms={:.3}", self.phase, self.samples, self.tracking, started.elapsed().as_secs_f64()*1000.0));
26        }
27    }
28}
29
30fn surface_domains(surface: &NurbsSurface) -> Result<([f64; 2], [f64; 2]), String> {
31    Ok((
32        KnotVector::new(surface.knots_u.clone(), surface.degree_u)?.domain(),
33        KnotVector::new(surface.knots_v.clone(), surface.degree_v)?.domain(),
34    ))
35}
36
37/// The carrier's closed directions, as [`NurbsSurface::closed_directions`]
38/// reads them (cached on the surface, seam tolerance 1e-6, and a sliver patch
39/// whose rows coincide without the surface travelling between them is OPEN).
40/// Until 2026-09-26 this was a second reading with its own tolerance; the
41/// unwrap in [`build_interpolant`] and the wrap in `evaluate_extended` must
42/// agree on what a seam is, or a trim across a sliver reads a period wide.
43fn surface_closedness(surface: &NurbsSurface) -> Result<(bool, bool), String> {
44    surface.closed_directions()
45}
46
47thread_local! {
48    static PCURVE_REJECT_BOUNDS: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
49}
50struct PcurveRejectScope(bool);
51impl PcurveRejectScope {
52    fn open(enabled: bool) -> Self {
53        Self(PCURVE_REJECT_BOUNDS.with(|state| state.replace(enabled)))
54    }
55}
56impl Drop for PcurveRejectScope {
57    fn drop(&mut self) { PCURVE_REJECT_BOUNDS.with(|state| state.set(self.0)); }
58}
59
60thread_local! {
61    static PCURVE_STACK_POINT: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
62}
63struct PcurveStackPointScope(bool);
64impl PcurveStackPointScope {
65    fn open(enabled: bool) -> Self { Self(PCURVE_STACK_POINT.with(|state| state.replace(enabled))) }
66}
67impl Drop for PcurveStackPointScope {
68    fn drop(&mut self) { PCURVE_STACK_POINT.with(|state| state.set(self.0)); }
69}
70
71/// The count-zero basis recurrence has the same operations as the value
72/// basis recurrence. Its homogeneous sum uses the same row/column order.
73/// Preserve derivative dehomogenization (multiply by reciprocal, not divide)
74/// while avoiding both the derivative grids and their allocation. Other
75/// degrees and open-direction extension keep the original API. Periodic
76/// wrap retains the original parameter arithmetic before value evaluation.
77fn section_extended_point(surface: &NurbsSurface, u: f64, v: f64, enabled: bool) -> Result<Vec3, String> {
78    if enabled && u.is_finite() && v.is_finite()
79        && surface.degree_u <= crate::curve::MAX_STACK_DEGREE
80        && surface.degree_v <= crate::curve::MAX_STACK_DEGREE {
81        let [u0,u1] = surface.domain_u()?;
82        let [v0,v1] = surface.domain_v()?;
83        let mut uu = u;
84        let mut vv = v;
85        if u < u0 || u > u1 || v < v0 || v > v1 {
86            let (closed_u, closed_v) = surface_closedness(surface)?;
87            // Identical to derivatives_extended: keep the original add,
88            // subtract and remainder order before taking the count-zero path.
89            if closed_u && (u < u0 || u > u1) { uu = u0 + (u - u0).rem_euclid(u1 - u0); }
90            if closed_v && (v < v0 || v > v1) { vv = v0 + (v - v0).rem_euclid(v1 - v0); }
91        }
92        if uu >= u0 && uu <= u1 && vv >= v0 && vv <= v1 {
93            let point = surface.evaluate_homogeneous(uu, vv)?;
94            if point.w.abs() <= EPSILON {
95                return Err("NurbsSurface: zero evaluated weight".into());
96            }
97            return Ok(Vec3::new(point.x, point.y, point.z).scale(1.0 / point.w));
98        }
99    }
100    surface.evaluate_extended(u,v)
101}
102
103/// One immutable carrier/section pair; nested fits own separate maps. Keys
104/// preserve all parameter bits, and failed evaluations are never retained.
105struct PcurveSampleCache {
106    surface: usize,
107    curve: usize,
108    curves: rustc_hash::FxHashMap<u64, Vec3>,
109    surfaces: rustc_hash::FxHashMap<(u64, u64, bool, bool), Vec3>,
110    inversions: rustc_hash::FxHashMap<[u64; 3], ([f64; 2], f64)>,
111    requests: [usize; 4],
112    hits: [usize; 4],
113    speeds: rustc_hash::FxHashMap<(u64, u64), f64>,
114}
115thread_local! {
116    static PCURVE_SAMPLES: std::cell::RefCell<Vec<Option<PcurveSampleCache>>> = const { std::cell::RefCell::new(Vec::new()) };
117}
118struct PcurveSampleScope<'a>(std::marker::PhantomData<(&'a NurbsSurface, &'a NurbsCurve)>);
119impl<'a> PcurveSampleScope<'a> {
120    fn open(surface: &'a NurbsSurface, curve: &'a NurbsCurve, enabled: bool) -> Self {
121        let cache = enabled
122            .then(|| PcurveSampleCache { surface: surface as *const _ as usize,
123                curve: curve as *const _ as usize, curves: Default::default(),
124                surfaces: Default::default(), inversions: Default::default(), requests: [0; 4], hits: [0; 4], speeds: Default::default() });
125        PCURVE_SAMPLES.with(|stack| stack.borrow_mut().push(cache));
126        Self(std::marker::PhantomData)
127    }
128}
129impl Drop for PcurveSampleScope<'_> {
130    fn drop(&mut self) {
131        PCURVE_SAMPLES.with(|stack| {
132            if let Some(Some(cache)) = stack.borrow_mut().pop() {
133                if crate::profile::profile_enabled() {
134                    profile_line!("pcurve.samples requests={:?} hits={:?} retained={:?}", cache.requests,
135                        cache.hits, [cache.curves.len(), cache.surfaces.len(), cache.inversions.len(), cache.speeds.len()]);
136                }
137            }
138        });
139    }
140}
141const PCURVE_SAMPLE_CACHE_LIMIT: usize = 16384;
142fn section_u_speed(surface: &NurbsSurface, u: f64, v: f64) -> Result<f64, String> {
143    let key = (u.to_bits(), v.to_bits());
144    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
145        let mut stack = stack.borrow_mut();
146        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
147        if cache.surface != surface as *const _ as usize { return (false, None) }
148        cache.requests[3] += 1;
149        let hit = cache.speeds.get(&key).copied();
150        cache.hits[3] += usize::from(hit.is_some());
151        (true, hit)
152    });
153    if let Some(hit) = hit { return Ok(hit) }
154    let speed = surface.deriv1(u, v)?.1.length();
155    if active { PCURVE_SAMPLES.with(|stack| {
156        let mut stack = stack.borrow_mut();
157        let cache = stack.last_mut().unwrap().as_mut().unwrap();
158        if cache.speeds.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.speeds.insert(key, speed); }
159    }); }
160    Ok(speed)
161}
162
163fn section_curve_point(curve: &NurbsCurve, parameter: f64) -> Result<Vec3, String> {
164    let key = parameter.to_bits();
165    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
166        let mut stack = stack.borrow_mut();
167        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
168        if cache.curve != curve as *const _ as usize { return (false, None) }
169        cache.requests[0] += 1;
170        let hit = cache.curves.get(&key).copied();
171        cache.hits[0] += usize::from(hit.is_some());
172        (true, hit)
173    });
174    if let Some(hit) = hit { return Ok(hit) }
175    let point = curve.evaluate(parameter)?;
176    if active { PCURVE_SAMPLES.with(|stack| {
177        let mut stack = stack.borrow_mut();
178        let cache = stack.last_mut().unwrap().as_mut().unwrap();
179        if cache.curves.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.curves.insert(key, point); }
180    }); }
181    Ok(point)
182}
183fn section_surface_point(surface: &NurbsSurface, u: f64, v: f64, extended: bool) -> Result<Vec3, String> {
184    // Extended evaluation has two arithmetic paths. Keep them separate even
185    // if a nested caller changes the stack-point policy within this scope.
186    let stack_point = PCURVE_STACK_POINT.with(|state| state.get());
187    let key = (u.to_bits(), v.to_bits(), extended, stack_point);
188    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
189        let mut stack = stack.borrow_mut();
190        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
191        if cache.surface != surface as *const _ as usize { return (false, None) }
192        cache.requests[1] += 1;
193        let hit = cache.surfaces.get(&key).copied();
194        cache.hits[1] += usize::from(hit.is_some());
195        (true, hit)
196    });
197    if let Some(hit) = hit { return Ok(hit) }
198    let point = if extended { section_extended_point(surface, u, v, stack_point)? } else { surface.evaluate(u, v)? };
199    if active { PCURVE_SAMPLES.with(|stack| {
200        let mut stack = stack.borrow_mut();
201        let cache = stack.last_mut().unwrap().as_mut().unwrap();
202        if cache.surfaces.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.surfaces.insert(key, point); }
203    }); }
204    Ok(point)
205}
206fn invert_checked(surface: &NurbsSurface, point: Vec3) -> Result<([f64; 2], f64), String> {
207    let key = [point.x.to_bits(), point.y.to_bits(), point.z.to_bits()];
208    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
209        let mut stack = stack.borrow_mut();
210        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
211        if cache.surface != surface as *const _ as usize { return (false, None) }
212        cache.requests[2] += 1;
213        let hit = cache.inversions.get(&key).copied();
214        cache.hits[2] += usize::from(hit.is_some());
215        (true, hit)
216    });
217    if let Some(hit) = hit { return Ok(hit) }
218    let projection = invert_checked_uncached(surface, point)?;
219    if active { PCURVE_SAMPLES.with(|stack| {
220        let mut stack = stack.borrow_mut();
221        let cache = stack.last_mut().unwrap().as_mut().unwrap();
222        if cache.inversions.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.inversions.insert(key, projection); }
223    }); }
224    Ok(projection)
225}
226
227fn invert_checked_uncached(surface: &NurbsSurface, point: Vec3) -> Result<([f64; 2], f64), String> {
228    let _lap = crate::projection_profile::Lap::enter(crate::projection_profile::LANE_INVERT_CHECKED, surface);
229    if surface.is_affine()? {
230        let ([u0, _], [v0, _]) = surface_domains(surface)?;
231        let (origin, du, dv) = surface.deriv1(u0, v0)?;
232        let delta = point.sub(origin);
233        let uu = du.dot(du);
234        let uv = du.dot(dv);
235        let vv = dv.dot(dv);
236        let along_u = delta.dot(du);
237        let along_v = delta.dot(dv);
238        let determinant = uu * vv - uv * uv;
239        if determinant.abs() > EPSILON {
240            let parameter = [
241                u0 + (along_u * vv - along_v * uv) / determinant,
242                v0 + (along_v * uu - along_u * uv) / determinant,
243            ];
244            // The standoff is a MEASUREMENT here as on every other carrier:
245            // until 2026-09-26 this returned 0.0 for "affine, not measured",
246            // and a curve 1e-2 off its plane read as lying on it.
247            let foot = origin.add(du.scale(parameter[0] - u0)).add(dv.scale(parameter[1] - v0));
248            return Ok((parameter, point.sub(foot).length()));
249        }
250    }
251    let projection = project_point_to_surface(surface, point)?;
252    Ok(([projection.u, projection.v], projection.distance))
253}
254
255/// Whether an end station at a cone's apex takes its nearest regular
256/// station's u (`true`), as in `build_interpolant`, or the projector's
257/// arbitrary u there as before 2026-09-27. `BREP_PCURVE_CONE_APEX_U=0`
258/// restores the projector's u, for a same-binary A/B.
259fn cone_apex_u() -> bool {
260    switch!("BREP_PCURVE_CONE_APEX_U", true)
261}
262
263/// Whether a round with more candidates than the cap has room for keeps its
264/// WORST probes (`true`), or the first in span order as before 2026-09-27.
265/// `BREP_PCURVE_WORST_FIRST=0` restores span order, for a same-binary A/B.
266fn worst_first() -> bool {
267    switch!("BREP_PCURVE_WORST_FIRST", true)
268}
269
270/// `BREP_PCURVE_C0_JOIN=0` builds one C2 interpolant through the stations as
271/// before 2026-10-03 (the C0 joins at the curve's corners off), for a
272/// same-binary A/B. Read once per process.
273fn c0_joins() -> bool {
274    switch!("BREP_PCURVE_C0_JOIN", true)
275}
276
277fn seeded_inserts() -> bool {
278    switch!("BREP_PCURVE_SEEDED_INSERTS", true)
279}
280
281/// [`invert_checked`] for a station inserted between two whose feet are known:
282/// Newton from the pcurve's own `(u, v)` at that fraction, which already lies
283/// between the neighbours' feet on their branch, and the global search only
284/// when that local foot stands off further than the neighbours do (plus the
285/// refinement floor) — a local minimum the curve does not sit at. The global
286/// search was 30 s of a 54 s `abc_00000011` import (732k calls, 41 µs each,
287/// measured 2026-09-26). Planes and analytic carriers keep their closed forms.
288/// `BREP_PCURVE_SEEDED_INSERTS=0` restores the global search at every insert,
289/// for a same-binary A/B.
290fn invert_near(
291    surface: &NurbsSurface,
292    point: Vec3,
293    seed: [f64; 2],
294    neighbour_gap: f64,
295) -> Result<([f64; 2], f64), String> {
296    if !seeded_inserts() || surface.is_affine()? || surface.analytic().is_some() || surface.affine_sphere().is_some() {
297        return invert_checked(surface, point);
298    }
299    let seeded = project_point_to_surface_seeded(surface, point, seed[0], seed[1])?;
300    if seeded.distance <= neighbour_gap + PCURVE_REFINEMENT_TOLERANCE {
301        return Ok(([seeded.u, seeded.v], seeded.distance));
302    }
303    invert_checked(surface, point)
304}
305
306fn unwrap_periodic(values: &mut [f64], minimum: f64, maximum: f64) {
307    let period = maximum - minimum;
308    for index in 1..values.len() {
309        while values[index] - values[index - 1] > period / 2.0 {
310            values[index] -= period;
311        }
312        while values[index] - values[index - 1] < -period / 2.0 {
313            values[index] += period;
314        }
315    }
316    if values.len() > 1 {
317        while values[0] - values[1] > period / 2.0 {
318            values[0] -= period;
319        }
320        while values[0] - values[1] < -period / 2.0 {
321            values[0] += period;
322        }
323    }
324    // Recenter the whole (now continuous) sequence into the domain by the
325    // whole-period shift that leaves the LEAST parameter outside [minimum,
326    // maximum]. A single middle/mean sample is NOT representative of a curve
327    // that bulges out to touch — or straddle — the periodic seam: when that
328    // sample is a boundary-kissing point (the at-seam projection unwraps a hair
329    // past the boundary), a single-sample test misfires and shoves the entire
330    // curve a full period out of range (ABC helmet 00000011/12 side channels:
331    // a touching edge's parameter run snapped a whole period off its true
332    // interior, tearing the loop open in parameter space).
333    if values.len() > 1 {
334        let excursion = |shift: f64| -> f64 {
335            values
336                .iter()
337                .map(|value| {
338                    let v = value + shift;
339                    (minimum - v).max(0.0) + (v - maximum).max(0.0)
340                })
341                .sum::<f64>()
342        };
343        let mean = values.iter().copied().sum::<f64>() / values.len() as f64;
344        let center = 0.5 * (minimum + maximum);
345        let base_k = ((center - mean) / period).round() as i64;
346        let mut best_shift = 0.0;
347        let mut best_excursion = f64::INFINITY;
348        for k in (base_k - 1)..=(base_k + 1) {
349            let shift = k as f64 * period;
350            let value = excursion(shift);
351            if value < best_excursion {
352                best_excursion = value;
353                best_shift = shift;
354            }
355        }
356        if best_shift != 0.0 {
357            for value in values.iter_mut() {
358                *value += best_shift;
359            }
360        }
361    }
362}
363
364/// The interpolant through `raw_parameters`, and what building it CLAMPED:
365/// the largest parameter distance a sample was pulled back into an open
366/// direction's domain, and the 3D distance between the extended surface at
367/// the raw parameter and the clamped foot. Both zero when nothing was pulled.
368/// A closed direction wraps and is never clamped.
369fn build_interpolant(
370    surface: &NurbsSurface,
371    raw_parameters: &[[f64; 2]],
372    curve_parameters: &[f64],
373) -> Result<(NurbsCurve, f64, f64), String> {
374    build_interpolant_joined(surface, raw_parameters, curve_parameters, &[])
375}
376
377/// [`build_interpolant`] with C0 JOINS: `joins` are values of
378/// `curve_parameters` at which the edge curve itself has a corner (a knot of
379/// multiplicity ≥ its degree, `range_breaks`). One cubic through all the
380/// stations is C2 everywhere, so across a corner it overshoots on both sides
381/// by a first-order amount however many stations are inserted: `abc_00000011`
382/// face #585 edge 179 (79 such knots on a 241-point curve) read 2.055e-4 off
383/// at 153 stations with the file's curve 2.1e-7 off the carrier (measured
384/// 2026-10-03). The stations have been planted at those knots since
385/// 2026-09-26; what was missing was the interpolant honouring them. Each
386/// piece between joins is interpolated on its own and the pieces are
387/// concatenated at knots of multiplicity 3 — the join `blend/track_fit.rs`
388/// makes for a blend track. A piece shorter than four stations cannot carry
389/// a cubic, so its join is dropped and it merges with its neighbour.
390fn build_interpolant_joined(
391    surface: &NurbsSurface,
392    raw_parameters: &[[f64; 2]],
393    curve_parameters: &[f64],
394    joins: &[f64],
395) -> Result<(NurbsCurve, f64, f64), String> {
396    let _clock = PcurvePhaseClock::new("interpolant", raw_parameters.len(), false);
397    let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
398    let (closed_u, closed_v) = surface_closedness(surface)?;
399    let mut parameters = raw_parameters.to_vec();
400    // A cone's apex has no longitude either: every u there is the same point,
401    // and the projector answers one arbitrarily (0, which unwraps to 1). A trim
402    // that ENDS at the apex then turns sideways in its last span —
403    // `abc 00008080` face #163 edge 476, a generatrix at u = 0.80255 whose
404    // apex station read u = 1.0 (2026-09-27). An apex station at either end of
405    // the run takes the u of its nearest regular station, so a generatrix's
406    // pcurve is the straight u = const it is. Interior apex crossings are left
407    // to the branch logic below. `BREP_PCURVE_CONE_APEX_U=0` switches this off,
408    // for a same-binary A/B.
409    if cone_apex_u() && matches!(surface.analytic(), Some(AnalyticSurface::RuledRevolution { .. })) && parameters.len() >= 2 {
410        let speeds = parameters
411            .iter()
412            .map(|parameter| section_u_speed(surface, parameter[0], parameter[1]))
413            .collect::<Result<Vec<_>, _>>()?;
414        let reference = speeds.iter().copied().fold(0.0_f64, f64::max);
415        let singular = |index: usize| speeds[index] <= reference * 1e-2;
416        if let (Some(first), Some(last)) = (
417            (0..parameters.len()).find(|&index| !singular(index)),
418            (0..parameters.len()).rfind(|&index| !singular(index)),
419        ) {
420            for index in 0..first {
421                parameters[index][0] = parameters[first][0];
422            }
423            for index in last + 1..parameters.len() {
424                parameters[index][0] = parameters[last][0];
425            }
426        }
427    }
428    // Longitude is undefined at a sphere pole: the surface's u tangent
429    // vanishes there, and closest-point inversion is free to return any u.
430    // Letting that arbitrary value participate in periodic unwrapping can move
431    // the first real meridian by a whole period (e.g. 0.75 -> -0.25). Analytic
432    // carriers are subsequently clamped, collapsing that meridian onto u=0.
433    //
434    // Keep this deliberately sphere- and singularity-gated. Split the u values
435    // into maximal non-pole runs, unwrap each run independently, and leave the
436    // pole samples untouched. The existing interpolant degree stays unchanged;
437    // lowering it here would also change endpoint-tangent decisions made later
438    // while stitching the face loop.
439    let sphere_u_singular = if matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })) {
440        let speeds = parameters
441            .iter()
442            .map(|parameter| {
443                section_u_speed(surface, parameter[0], parameter[1])
444            })
445            .collect::<Result<Vec<_>, _>>()?;
446        let reference = speeds.iter().copied().fold(0.0_f64, f64::max);
447        speeds
448            .into_iter()
449            // Uniform edge stations need not hit the pole exactly (ABC 5360
450            // bottoms out at v=5.5e-4). In this small conditioning band,
451            // longitude is already numerically arbitrary and must not connect
452            // the two meridian runs across the pole.
453            .map(|speed| speed <= reference * 1e-2)
454            .collect::<Vec<_>>()
455    } else {
456        vec![false; parameters.len()]
457    };
458    // Do not perturb ordinary pole-touching trims. The special path is needed
459    // only when a pole band is bracketed by nonsingular samples and its raw
460    // longitude changes by at least half a period: a true through-pole branch
461    // reset whose two meridian runs must be unwrapped independently.
462    // Prefix/suffix pole samples on normal sphere caps retain the legacy
463    // interpolation byte-for-byte. Include the exactly-half-period case so
464    // floating-point noise cannot decide which entire run is lifted (ABC 5603).
465    let has_interior_pole_crossing = sphere_u_singular
466        .iter()
467        .position(|singular| !singular)
468        .zip(sphere_u_singular.iter().rposition(|singular| !singular))
469        .is_some_and(|(first, last)| sphere_u_singular[first..=last].iter().any(|value| *value));
470    let period = (u1 - u0).abs();
471    let interior_pole_branch_reset = closed_u
472        && has_interior_pole_crossing
473        && parameters.windows(2).zip(sphere_u_singular.windows(2)).any(
474            |(parameter_pair, singular_pair)| {
475                (singular_pair[0] || singular_pair[1])
476                    && (parameter_pair[1][0] - parameter_pair[0][0]).abs()
477                        >= 0.5 * period - 1e-12 * period.max(1.0)
478            },
479        );
480    if closed_u {
481        let mut values = parameters.iter().map(|value| value[0]).collect::<Vec<_>>();
482        if interior_pole_branch_reset {
483            let mut start = 0;
484            while start < values.len() {
485                while start < values.len() && sphere_u_singular[start] {
486                    start += 1;
487                }
488                let mut end = start;
489                while end < values.len() && !sphere_u_singular[end] {
490                    end += 1;
491                }
492                unwrap_periodic(&mut values[start..end], u0, u1);
493                start = end;
494            }
495        } else {
496            unwrap_periodic(&mut values, u0, u1);
497        }
498        for (parameter, value) in parameters.iter_mut().zip(values) {
499            parameter[0] = value;
500        }
501    }
502    if closed_v {
503        let mut values = parameters.iter().map(|value| value[1]).collect::<Vec<_>>();
504        unwrap_periodic(&mut values, v0, v1);
505        for (parameter, value) in parameters.iter_mut().zip(values) {
506            parameter[1] = value;
507        }
508    }
509    // A closed direction WRAPS: an edge that straddles the seam has no single
510    // in-domain parameter run, so keep the unwrapped (possibly slightly
511    // out-of-domain) values and let the periodic evaluator wrap them — clamping
512    // them onto the seam boundary would collapse the straddling geometry (and,
513    // via the interpolant, spike neighbouring stations). This applies to
514    // analytic carriers too: a refitted cylinder can have stepped rims that
515    // cross its seam. evaluate_extended wraps every closed direction.
516    // Open directions must stay in-domain; their extension is a ruling.
517    //
518    // The clamp is MEASURED, not silent: a sample pulled back into the domain
519    // is reported as the parameter distance it moved and the 3D distance
520    // between the extended surface at its raw parameter and the clamped foot
521    // ([`PcurveFitReport::clamped_excursion`]). Until 2026-09-30 a trim that
522    // ran past its chart came back folded onto the chart's boundary with
523    // nothing in the report to say so; on the rib-base document that was
524    // 3.03e-2 of volume on a body `validate()` passes.
525    let mut excursion = 0.0_f64;
526    let mut distance = 0.0_f64;
527    let mut points = Vec::with_capacity(parameters.len());
528    for parameter in parameters {
529        let u = if closed_u {
530            parameter[0]
531        } else {
532            parameter[0].clamp(u0, u1)
533        };
534        let v = if closed_v {
535            parameter[1]
536        } else {
537            parameter[1].clamp(v0, v1)
538        };
539        let pulled = ((parameter[0] - u).powi(2) + (parameter[1] - v).powi(2)).sqrt();
540        if pulled > 0.0 {
541            excursion = excursion.max(pulled);
542            let extended = surface.evaluate_extended(parameter[0], parameter[1])?;
543            distance = distance.max(extended.sub(surface.evaluate(u, v)?).length());
544        }
545        points.push(Vec3::new(u, v, 0.0));
546    }
547    let degree = 3usize.min(points.len() - 1);
548    let mut bounds: Vec<usize> = joins
549        .iter()
550        .filter_map(|join| curve_parameters.iter().position(|parameter| parameter == join))
551        .filter(|&index| index > 0 && index + 1 < curve_parameters.len())
552        .collect();
553    bounds.sort_unstable();
554    bounds.dedup();
555    if degree < 3 || bounds.is_empty() || !c0_joins() {
556        let curve = interpolate_curve(&points, degree, curve_parameters)?;
557        return Ok((curve, excursion, distance));
558    }
559    // Every piece needs four stations for a cubic: drop the join that
560    // closes a shorter piece, from the left, until all pieces carry one.
561    let mut pieces = vec![0usize];
562    for bound in bounds {
563        if bound + 1 - pieces[pieces.len() - 1] >= 4 {
564            pieces.push(bound);
565        }
566    }
567    if curve_parameters.len() - pieces[pieces.len() - 1] < 4 {
568        pieces.pop();
569    }
570    pieces.push(curve_parameters.len() - 1);
571    if pieces.len() < 3 {
572        let curve = interpolate_curve(&points, degree, curve_parameters)?;
573        return Ok((curve, excursion, distance));
574    }
575    let mut knots: Vec<f64> = Vec::with_capacity(curve_parameters.len() + 4);
576    let mut control: Vec<Vec4> = Vec::with_capacity(curve_parameters.len());
577    let last_piece = pieces.len() - 2;
578    for piece in 0..=last_piece {
579        let (from, to) = (pieces[piece], pieces[piece + 1]);
580        let fitted = interpolate_curve(&points[from..=to], 3, &curve_parameters[from..=to])?;
581        if piece == 0 {
582            knots.extend(fitted.knots[..4].iter().copied());
583        }
584        knots.extend(fitted.knots[4..fitted.knots.len() - 4].iter().copied());
585        let multiplicity = if piece == last_piece { 4 } else { 3 };
586        knots.extend(std::iter::repeat(curve_parameters[to]).take(multiplicity));
587        control.extend(fitted.control_points.iter().skip(usize::from(piece > 0)).copied());
588    }
589    let curve = NurbsCurve::new(3, knots, control)?;
590    Ok((curve, excursion, distance))
591}
592
593/// The 3D residual a pcurve's image must reach before `build_pcurve_on_surface`
594/// accepts it, and the sample ceiling it refines up to.
595///
596/// A trimmed face's boundary is only ever as accurate as these two numbers, and
597/// every mass property is an integral over that boundary — so this is the floor
598/// under area, volume and centroid for every curved trim in the kernel.
599///
600/// These were `min(1e-3, 1e-4 * scale)` and 160, where `scale` is
601/// `1 + ||curve midpoint||` — the DISTANCE FROM THE WORLD ORIGIN of the curve's
602/// midpoint, not the part's size. That expression pinned to an absolute 1e-3
603/// once the midpoint sat more than about nine units from the origin, so on an
604/// ordinary part the bar was 1e-3 and tracked nothing.
605///
606/// Measured on `offset-shell-box-bore-dished-face`, whose dished wall is a
607/// closed-form identity at 2468.431782123 (three independent routes agree). The
608/// floor is one of TWO errors there; the other is the refitted sphere carrier
609/// that `sphere_offset_surface` now builds in closed form, and before both moved
610/// they partly CANCELLED — which is why either alone reads as a regression:
611///
612/// ```text
613/// floor     Box_O.S2            abs err     relative   gate total  worst case
614/// 1e-3   2468.442270355      +1.049e-02     4.25e-06        (old)
615/// 1e-6   2468.431785429      +3.306e-06     1.34e-09       181.4 s     31.2 s
616/// 1e-7   2468.431782170      +4.746e-08     1.92e-11       218.5 s     32.1 s
617/// 1e-9   2468.431782103      -2.037e-08    -8.25e-12       305.5 s     46.8 s
618/// ```
619///
620/// 1e-7 is chosen: 70x the accuracy of 1e-6 for +20% gate time, where 1e-9 costs
621/// a further +40% for a 2.3x residual no oracle in this corpus could resolve.
622/// All four cells are one session on one binary, so the times are comparable to
623/// each other. Every case carrying a closed-form oracle moves TOWARD it and none
624/// away (`PushFaceTest` 339x, `PushFaceTest2` 275x); no case changes class at
625/// any floor.
626///
627/// A flat ABSOLUTE is what was measured, not what was designed. This codebase
628/// otherwise keys identity bands to part size (`KernelTolerances::heal_band`,
629/// the `1e-11*(1+scale)` blend family), and on a 3000 mm part 1e-7 is 3e-11
630/// relative — refinement will exhaust `MAX_PCURVE_SAMPLES` and return whatever
631/// it reached. Until 2026-09-12 it did so SILENTLY; now the fit's
632/// [`PcurveFitReport`] carries the residual actually achieved and a
633/// [`PcurveFitExit::SampleCeiling`] exit, and the owning operation's
634/// diagnostics count it (`pcurve.unmet_floor`). That is far better than the
635/// 1e-3 it replaces but it is not a size-aware bar; deriving one from the
636/// surface's own extent is separate, unmeasured work. Being absolute does remove this gate's dependence on
637/// distance from the origin as a side effect — a real translation-VARIANCE
638/// defect, the same anti-pattern `tolerance::merge_scale` records being removed
639/// elsewhere. `drop_tolerance` and `endpoint_tolerance` below still carry it.
640pub const PCURVE_REFINEMENT_TOLERANCE: f64 = 1e-7;
641
642/// Sample ceiling for a fit's FIRST refinement pass. 160 could not reach
643/// [`PCURVE_REFINEMENT_TOLERANCE`] on a curved trim of any length; 600 is the
644/// value every cell of the table above was measured at.
645///
646/// It BINDS. On `boolean_fuzz_corpus/25_cube_pierce_solid` the fitter stopped
647/// here 1.65e-3 of volume short of the converged answer (2000 and 4000 samples
648/// agree exactly). Raising it globally to 2000 was costed and rejected: +23%
649/// case-gate time, concentrated in three offset/fillet cases, and one case
650/// (`inbox-20260910-offset-shell-collapsed-fillet`) driven 26x outside its
651/// volume band. So it is not raised here: a fit that stops at this ceiling
652/// with a residual still worse than its edge curve's own distance from the
653/// surface re-enters refinement with [`PCURVE_RAISED_SAMPLES`]
654/// ([`refine_pcurve`]); one whose residual is already that gap stops here and
655/// says so ([`PcurveFitReport::off_surface`]), because no sample count can
656/// close it.
657const MAX_PCURVE_SAMPLES: usize = 600;
658
659/// Sample ceiling for the ONE raised pass a fit may take past
660/// [`MAX_PCURVE_SAMPLES`]. 2000 is the ceiling the convergence sweep measured
661/// on `25_cube_pierce_solid`: its 2000 and 4000 cells agree to every printed
662/// digit because refinement there stops itself near 1540 samples, so the cap
663/// is not what binds.
664const PCURVE_RAISED_SAMPLES: usize = 2000;
665
666/// What a pcurve fit ACHIEVED, returned beside the curve so a ceiling exit can
667/// never be mistaken for a met floor.
668///
669/// [`fit_pcurve_on_surface`] asks for [`PCURVE_REFINEMENT_TOLERANCE`] and stops
670/// at `MAX_PCURVE_SAMPLES` — or, where that ceiling bound and the floor is
671/// reachable, at `PCURVE_RAISED_SAMPLES`. Until 2026-09-12 a trim that ran out
672/// of samples came back exactly like one that met the floor; on
673/// `boolean_fuzz_corpus/25_cube_pierce_solid` that silence hid a 1.65e-3 volume
674/// error. Now every fit says which it was: `residual` is measured on the curve
675/// that is actually returned and `exit` names why refinement stopped.
676///
677/// This is a MEASUREMENT taken at a construction, not a band.
678#[derive(Clone, Copy, Debug, PartialEq)]
679pub struct PcurveFitReport {
680    /// Largest 3D distance between the returned pcurve's image on the surface
681    /// and the edge curve. On a [`PcurveFitExit::Converged`] exit whose final
682    /// round probed every span this is that round's maximum — the refinement's
683    /// own acceptance test. On every other exit, including a converged round
684    /// that skipped spans narrower than 1e-3 of the parameter range, it is a
685    /// sweep over EVERY span of the returned curve.
686    pub residual: f64,
687    /// The residual the refinement was asked to reach.
688    pub floor: f64,
689    /// Interpolation samples in the returned curve.
690    pub samples: usize,
691    /// Why refinement stopped.
692    pub exit: PcurveFitExit,
693    /// Largest distance from the edge curve to the surface at every station
694    /// the fit inverted — the part of `residual` no pcurve can remove, since a
695    /// pcurve's image lies ON the surface. Zero for an affine carrier. A value
696    /// above `floor` says the floor is unreachable for this input; a ceiling
697    /// exit is retried only while `residual` exceeds it by more than the floor,
698    /// i.e. while the returned curve is worse than its input.
699    pub off_surface: f64,
700    /// Whether the fit re-entered refinement with `PCURVE_RAISED_SAMPLES`
701    /// after `MAX_PCURVE_SAMPLES` bound with the floor unmet.
702    pub raised: bool,
703    /// Largest parameter distance a station's inversion was pulled back into
704    /// an OPEN direction's domain when the returned curve was interpolated: a
705    /// trim asked for outside its chart is folded onto the chart's boundary,
706    /// the edge stays right and the face becomes the wrong region on a body
707    /// `validate()` passes (3.03e-2 of volume on the rib-base document). Zero
708    /// when nothing was pulled. A REPORT, not a bar: nothing here refuses on
709    /// it. Its coverage is the clamp in `build_interpolant`, which is the only
710    /// place a raw out-of-domain parameter reaches today — an affine carrier's
711    /// inversion is unclamped, so an affine plane fitted through the station
712    /// lane reads here. It does NOT see a clamp the projector applied before
713    /// the fit: the analytic `Plane` closed form (a non-affine net) clamps to
714    /// its domain, `RuledRevolution` clamps its axial parameter to `[0, 1]`
715    /// and the general Newton clamps through `fit_parameter`; those stations
716    /// arrive in-domain and read as `off_surface` instead. The exact affine
717    /// lanes (`fit_pcurve_on_surface` on an affine carrier,
718    /// `affine_pcurve_on_range`) never clamp and read zero by construction.
719    pub clamped_excursion: f64,
720    /// The 3D distance the clamp corresponds to: between the extended surface
721    /// at the raw parameter and the clamped foot, at the station of the
722    /// largest such distance. Zero when nothing was pulled.
723    pub clamped_distance: f64,
724}
725
726impl PcurveFitReport {
727    /// Whether the returned curve reaches the floor it was asked for.
728    pub fn met_floor(&self) -> bool {
729        self.residual <= self.floor
730    }
731
732    /// Whether the returned curve is on the ACCEPTANCE BAR: the floor it was
733    /// asked for, plus the stations' own standoff from the carrier.
734    ///
735    /// A pcurve's image lies on the carrier, so at a station standing `g` off
736    /// it no image can come closer than `g`; a fit whose residual is within
737    /// the floor of `off_surface` is as good as the input allows, and one over
738    /// it is worse than its input — the same condition `refine_pcurve` uses
739    /// to decide that a raise can still buy accuracy. This is the bar every
740    /// station builder refuses over ([`build_pcurve_on_surface_stations`]).
741    /// It is blind to sideways error quadratically (a station tracked `d`
742    /// aside of the projection of a point `g` off the surface reads only
743    /// `d²/(2g)` further away), which is stated rather than hidden: on the
744    /// import corpus the stations that stand off their carriers are the
745    /// FILE's curves, and the bar there is the file's own number.
746    pub fn on_bar(&self) -> bool {
747        self.residual <= self.floor + self.off_surface
748    }
749}
750
751/// Why a pcurve refinement stopped. Only [`PcurveFitExit::Converged`] means the
752/// floor was met; every other variant is a BUDGET exit, and the report's
753/// residual was measured on the returned curve rather than assumed.
754#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
755pub enum PcurveFitExit {
756    /// A probe round found every station within the floor. An affine carrier
757    /// maps exactly and reports this with a zero residual.
758    Converged,
759    /// The sample ceiling bound before the floor was met: `MAX_PCURVE_SAMPLES`
760    /// when the raise was declined (the residual is already explained by
761    /// [`PcurveFitReport::off_surface`]), `PCURVE_RAISED_SAMPLES` when it was
762    /// taken and bound too.
763    SampleCeiling,
764    /// Every refinement round was spent and the last one still inserted
765    /// samples, so the curve it built was never re-checked by the loop.
766    RoundBudget,
767    /// A round found stations over the floor but could improve none of them:
768    /// the edge point could not be inverted inside the drop band, or (in the
769    /// raised pass) the pcurve already tracks the surface's nearest point to
770    /// within the floor. Either way the edge curve itself sits off the surface
771    /// there and no pcurve can close that gap; the residual reports how far.
772    /// The range lane's end-span challenger (its station fitter's TRACKING
773    /// mode) also exits here when a round's probes all track their feet
774    /// within the floor while the deviation residual, which includes the
775    /// edge's standoff, stays over it.
776    Stalled,
777    /// The last probe round found every span it PROBED within the floor, but
778    /// skipped spans narrower than the loop's own resolution floor — 1e-3 of
779    /// the parameter range in `refine_pcurve`, `SPAN_FLOOR` (1e-6) in
780    /// [`fit_pcurve_on_surface_stations`] — and a sweep over those found the
781    /// floor unmet.
782    /// Until 2026-09-12 this exit was reported as `Converged` with the probed
783    /// spans' maximum: on `25_cube_pierce_solid` a 1539-sample fit with 1537
784    /// narrow spans read 7e-8 that way while every span read 1.9e-4.
785    SpanFloor,
786}
787
788/// A fitted pcurve with what the fit achieved.
789#[derive(Clone, Debug)]
790pub struct PcurveFit {
791    pub curve: NurbsCurve,
792    pub report: PcurveFitReport,
793}
794
795/// Per-operation tally of pcurve fits and how many missed their floor.
796///
797/// [`build_pcurve_on_surface`] and its marched twin are called from some forty
798/// sites, most of which have no diagnostics record to write into. Rather than
799/// thread one through every layer, an operation that returns
800/// [`KernelDiagnostics`] opens a [`PcurveFitScope`]; every fit made on that
801/// thread while the scope is open is tallied here, and closing the scope hands
802/// the tally back for [`PcurveFitLedger::report_into`]. This is the shape the
803/// boolean's `CONFORMANCE_REPAIRS` counter already uses. With no scope open,
804/// recording is a no-op.
805///
806/// Scopes nest: CLOSING a child folds it into its parent, so an offset shell
807/// sees the fits of the booleans it ran. A scope that is DROPPED without being
808/// closed is discarded, not folded — a boolean attempt that refused (and may be
809/// retried under perturbation) must not leave its fits on the caller's tally.
810///
811/// Thread-local by construction: a fit made on a rayon worker (the `parallel`
812/// feature's STEP body import) is not seen by a scope on the calling thread. No
813/// diagnostics-returning operation builds pcurves off-thread today.
814#[derive(Clone, Copy, Debug, Default, PartialEq)]
815pub struct PcurveFitLedger {
816    /// Fits recorded, exact affine ones included.
817    pub fits: u64,
818    /// Fits whose returned curve did not reach its floor.
819    pub unmet: u64,
820    /// Unmet fits that stopped at a sample ceiling.
821    pub sample_ceiling: u64,
822    /// Unmet fits that spent every refinement round.
823    pub round_budget: u64,
824    /// Unmet fits that could insert nothing.
825    pub stalled: u64,
826    /// Unmet fits whose remaining over-floor spans were all below the loop's
827    /// 1e-3 span floor.
828    pub span_floor: u64,
829    /// Largest residual among the unmet fits; zero when there are none.
830    pub worst_unmet_residual: f64,
831    /// Fits that re-entered refinement with `PCURVE_RAISED_SAMPLES`, met or
832    /// not.
833    pub raised: u64,
834    /// Unmet ceiling exits that were NOT raised because the residual is
835    /// already within the floor of the edge curve's own gap from the surface.
836    pub raise_declined: u64,
837    /// Largest [`PcurveFitReport::off_surface`] over every fit.
838    pub worst_off_surface: f64,
839    /// Fits whose interpolant was clamped into an open direction's domain
840    /// ([`PcurveFitReport::clamped_excursion`] above zero), met or not.
841    pub clamped: u64,
842    /// Largest [`PcurveFitReport::clamped_excursion`] over every fit.
843    pub worst_clamped_excursion: f64,
844    /// Largest [`PcurveFitReport::clamped_distance`] over every fit.
845    pub worst_clamped_distance: f64,
846}
847
848impl PcurveFitLedger {
849    fn record(&mut self, report: &PcurveFitReport) {
850        self.fits += 1;
851        if report.raised {
852            self.raised += 1;
853        }
854        self.worst_off_surface = self.worst_off_surface.max(report.off_surface);
855        if report.clamped_excursion > 0.0 {
856            self.clamped += 1;
857            self.worst_clamped_excursion = self.worst_clamped_excursion.max(report.clamped_excursion);
858            self.worst_clamped_distance = self.worst_clamped_distance.max(report.clamped_distance);
859        }
860        if report.met_floor() {
861            return;
862        }
863        self.unmet += 1;
864        match report.exit {
865            PcurveFitExit::Converged => {}
866            PcurveFitExit::SampleCeiling => {
867                self.sample_ceiling += 1;
868                if !report.raised {
869                    self.raise_declined += 1;
870                }
871            }
872            PcurveFitExit::RoundBudget => self.round_budget += 1,
873            PcurveFitExit::Stalled => self.stalled += 1,
874            PcurveFitExit::SpanFloor => self.span_floor += 1,
875        }
876        self.worst_unmet_residual = self.worst_unmet_residual.max(report.residual);
877    }
878
879    fn fold(&mut self, child: &PcurveFitLedger) {
880        self.fits += child.fits;
881        self.unmet += child.unmet;
882        self.sample_ceiling += child.sample_ceiling;
883        self.round_budget += child.round_budget;
884        self.stalled += child.stalled;
885        self.span_floor += child.span_floor;
886        self.worst_unmet_residual = self.worst_unmet_residual.max(child.worst_unmet_residual);
887        self.raised += child.raised;
888        self.raise_declined += child.raise_declined;
889        self.worst_off_surface = self.worst_off_surface.max(child.worst_off_surface);
890        self.clamped += child.clamped;
891        self.worst_clamped_excursion = self.worst_clamped_excursion.max(child.worst_clamped_excursion);
892        self.worst_clamped_distance = self.worst_clamped_distance.max(child.worst_clamped_distance);
893    }
894
895    /// Write the tally into an operation's diagnostics: the `pcurve.*`
896    /// counters and measurements always, plus one `pcurve.unmet_floor` event at
897    /// [`DiagnosticSeverity::Degraded`] when any fit missed its floor. Degraded,
898    /// not Error: the result is still the kernel's best construction and stays
899    /// shippable, but it no longer claims the accuracy its floor states.
900    pub fn report_into(&self, diagnostics: &mut KernelDiagnostics) {
901        diagnostics.count_n("pcurve.fits", self.fits);
902        diagnostics.count_n("pcurve.unmet_floor", self.unmet);
903        diagnostics.count_n("pcurve.exit.sample_ceiling", self.sample_ceiling);
904        diagnostics.count_n("pcurve.exit.round_budget", self.round_budget);
905        diagnostics.count_n("pcurve.exit.stalled", self.stalled);
906        diagnostics.count_n("pcurve.exit.span_floor", self.span_floor);
907        diagnostics.count_n("pcurve.budget_raised", self.raised);
908        diagnostics.count_n("pcurve.budget_raise_declined", self.raise_declined);
909        diagnostics.measure_max("pcurve.worst_unmet_residual", self.worst_unmet_residual);
910        diagnostics.measure_max("pcurve.worst_off_surface", self.worst_off_surface);
911        diagnostics.count_n("pcurve.clamped", self.clamped);
912        diagnostics.measure_max("pcurve.worst_clamped_excursion", self.worst_clamped_excursion);
913        diagnostics.measure_max("pcurve.worst_clamped_distance", self.worst_clamped_distance);
914        if self.unmet > 0 {
915            diagnostics.event(
916                DiagnosticSeverity::Degraded,
917                KernelStage::Refine,
918                "pcurve.unmet_floor",
919                format!(
920                    "{} of {} pcurve fits did not reach the {:.0e} floor \
921                     (sample ceiling {}, round budget {}, stalled {}, span floor {}); \
922                     worst residual {:.3e}; budget raised on {}, declined on {}; \
923                     edge curves sit off their surfaces by up to {:.3e}{}",
924                    self.unmet,
925                    self.fits,
926                    PCURVE_REFINEMENT_TOLERANCE,
927                    self.sample_ceiling,
928                    self.round_budget,
929                    self.stalled,
930                    self.span_floor,
931                    self.worst_unmet_residual,
932                    self.raised,
933                    self.raise_declined,
934                    self.worst_off_surface,
935                    if self.clamped > 0 {
936                        format!(
937                            "; {} fit(s) clamped into their chart by up to {:.3e} in parameter, {:.3e} in 3D",
938                            self.clamped, self.worst_clamped_excursion, self.worst_clamped_distance
939                        )
940                    } else {
941                        String::new()
942                    },
943                ),
944            );
945        }
946    }
947}
948
949thread_local! {
950    /// The open [`FootMemo`] on this thread, if any ([`FootMemoScope`]).
951    static FOOT_MEMO: std::cell::RefCell<Option<FootMemo>> = const { std::cell::RefCell::new(None) };
952}
953
954/// Exact-input memo of the common reader's projections on ONE surface: the
955/// global foot of an edge point and the foot seeded at a (u, v), keyed by the
956/// bit patterns of their inputs. Both projectors are pure functions of
957/// (surface, point[, seed]), so a hit returns the value a fresh call would:
958/// the readings, decisions and fits are bit-identical with or without it.
959/// It exists for cost: within one coedge the same edge points are read by
960/// the trigger read, every tracking-mode verification round, the
961/// challenger's final read and the importer's keep read, each of which
962/// projected them again (`importTestWorking`, 2026-10-05: about 10k probes
963/// read 3-5 times on each of nine off-carrier refits, 3-5 s apiece).
964///
965/// Feet computed while [`defer_foot_inserts`] is on are appended to the
966/// `pending_*` lists instead of hashed, and folded into the maps at the first
967/// lookup that misses while it is off. A tracking pair that reads clean is
968/// never read again, so its 20-30k feet per read are never hashed (16% of
969/// the reader on the elephant, 2026-11-03); a candidate read or
970/// fit that follows sees every one of them. Deferral changes no answer: a
971/// lookup that misses recomputes the same pure function.
972struct FootMemo {
973    surface: *const NurbsSurface,
974    global: rustc_hash::FxHashMap<[u64; 3], Option<crate::SurfaceProjection>>,
975    seeded: rustc_hash::FxHashMap<[u64; 5], Option<crate::SurfaceProjection>>,
976    pending_global: Vec<([u64; 3], Option<crate::SurfaceProjection>)>,
977    pending_seeded: Vec<([u64; 5], Option<crate::SurfaceProjection>)>,
978}
979
980impl FootMemo {
981    fn new(surface: *const NurbsSurface) -> Self {
982        Self { surface, global: Default::default(), seeded: Default::default(), pending_global: Vec::new(), pending_seeded: Vec::new() }
983    }
984
985    /// Fold the deferred feet into the maps (a later insert of the same key
986    /// would carry the same value, so the order of folding is immaterial).
987    fn fold_pending(&mut self) {
988        if !self.pending_global.is_empty() {
989            self.global.reserve(self.pending_global.len());
990            self.global.extend(self.pending_global.drain(..));
991        }
992        if !self.pending_seeded.is_empty() {
993            self.seeded.reserve(self.pending_seeded.len());
994            self.seeded.extend(self.pending_seeded.drain(..));
995        }
996    }
997}
998
999thread_local! {
1000    static DEFER_FOOT_INSERTS: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
1001}
1002
1003/// Run `read` with new feet appended to the open memo's pending lists rather
1004/// than hashed ([`FootMemo`]); restores the previous setting.
1005pub(crate) fn defer_foot_inserts<T>(read: impl FnOnce() -> T) -> T {
1006    let previous = DEFER_FOOT_INSERTS.with(|cell| cell.replace(true));
1007    let result = read();
1008    DEFER_FOOT_INSERTS.with(|cell| cell.set(previous));
1009    result
1010}
1011
1012/// Opens a [`FootMemo`] for `surface` on this thread until dropped. Opening
1013/// one where a memo for the SAME surface is already open reuses it (an inner
1014/// scope, e.g. the range challenger inside an importer coedge); a memo for
1015/// another surface is set aside and restored on drop. The borrow of `surface`
1016/// keeps it alive and unmodified for the scope, so the pointer key cannot be
1017/// reused by another surface while the memo answers for it.
1018pub(crate) struct FootMemoScope<'a> {
1019    previous: Option<Option<FootMemo>>,
1020    _surface: std::marker::PhantomData<&'a NurbsSurface>,
1021    /// Not `Send`: the scope must close on the thread that opened it.
1022    _thread_bound: std::marker::PhantomData<*const ()>,
1023}
1024
1025impl<'a> FootMemoScope<'a> {
1026    pub(crate) fn open(surface: &'a NurbsSurface) -> Self {
1027        let key = surface as *const NurbsSurface;
1028        let previous = FOOT_MEMO.with(|memo| {
1029            let mut memo = memo.borrow_mut();
1030            if memo.as_ref().is_some_and(|open| std::ptr::eq(open.surface, key)) {
1031                None
1032            } else {
1033                Some(memo.replace(FootMemo::new(key)))
1034            }
1035        });
1036        Self { previous, _surface: std::marker::PhantomData, _thread_bound: std::marker::PhantomData }
1037    }
1038}
1039
1040impl Drop for FootMemoScope<'_> {
1041    fn drop(&mut self) {
1042        if let Some(previous) = self.previous.take() {
1043            FOOT_MEMO.with(|memo| *memo.borrow_mut() = previous);
1044        }
1045    }
1046}
1047
1048fn point_bits(point: Vec3) -> [u64; 3] {
1049    [point.x.to_bits(), point.y.to_bits(), point.z.to_bits()]
1050}
1051
1052/// [`project_point_to_surface`] as `.ok()`, through the open memo for this
1053/// surface when there is one. `#[track_caller]`: the projector still sees the
1054/// reader's own call site. Under a `BREP_PROJECTION_GLOBAL_SITES`/`_EXCEPT`
1055/// filter the projector's answer depends on that site, so the memo is not
1056/// consulted then.
1057#[track_caller]
1058fn memo_global_foot(surface: &NurbsSurface, point: Vec3) -> Option<crate::SurfaceProjection> {
1059    if crate::projection::global_site_filter_active() {
1060        return project_point_to_surface(surface, point).ok();
1061    }
1062    let key = point_bits(point);
1063    let deferring = DEFER_FOOT_INSERTS.with(|cell| cell.get());
1064    let hit = FOOT_MEMO.with(|memo| {
1065        memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)).map(|open| {
1066            match open.global.get(&key).copied() {
1067                Some(foot) => Some(foot),
1068                None if !deferring && !open.pending_global.is_empty() => {
1069                    open.fold_pending();
1070                    open.global.get(&key).copied()
1071                }
1072                None => None,
1073            }
1074        })
1075    });
1076    match hit {
1077        Some(Some(foot)) => foot,
1078        Some(None) => {
1079            let foot = project_point_to_surface(surface, point).ok();
1080            FOOT_MEMO.with(|memo| {
1081                if let Some(open) = memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)) {
1082                    if deferring {
1083                        open.pending_global.push((key, foot));
1084                    } else {
1085                        open.global.insert(key, foot);
1086                    }
1087                }
1088            });
1089            foot
1090        }
1091        None => project_point_to_surface(surface, point).ok(),
1092    }
1093}
1094
1095/// [`project_point_to_surface_seeded`] as `.ok()`, through the open memo for
1096/// this surface when there is one.
1097fn memo_seeded_foot(surface: &NurbsSurface, point: Vec3, seed_u: f64, seed_v: f64) -> Option<crate::SurfaceProjection> {
1098    let [x, y, z] = point_bits(point);
1099    let key = [x, y, z, seed_u.to_bits(), seed_v.to_bits()];
1100    let deferring = DEFER_FOOT_INSERTS.with(|cell| cell.get());
1101    let hit = FOOT_MEMO.with(|memo| {
1102        memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)).map(|open| {
1103            match open.seeded.get(&key).copied() {
1104                Some(foot) => Some(foot),
1105                None if !deferring && !open.pending_seeded.is_empty() => {
1106                    open.fold_pending();
1107                    open.seeded.get(&key).copied()
1108                }
1109                None => None,
1110            }
1111        })
1112    });
1113    match hit {
1114        Some(Some(foot)) => foot,
1115        Some(None) => {
1116            let foot = project_point_to_surface_seeded(surface, point, seed_u, seed_v).ok();
1117            FOOT_MEMO.with(|memo| {
1118                if let Some(open) = memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)) {
1119                    if deferring {
1120                        open.pending_seeded.push((key, foot));
1121                    } else {
1122                        open.seeded.insert(key, foot);
1123                    }
1124                }
1125            });
1126            foot
1127        }
1128        None => project_point_to_surface_seeded(surface, point, seed_u, seed_v).ok(),
1129    }
1130}
1131
1132thread_local! {
1133    /// The open [`PcurveFitScope`]s on this thread, innermost last.
1134    static PCURVE_FIT_SCOPES: std::cell::RefCell<Vec<PcurveFitLedger>> =
1135        const { std::cell::RefCell::new(Vec::new()) };
1136}
1137
1138/// `BREP_DEBUG_PCURVE_FIT` only: a process-wide id per [`refine_pcurve`]
1139/// call, so its first-pass and candidate `PCURVE-TRACK` lines pair up even
1140/// when fits run on several threads.
1141static PCURVE_TRACK_CALL: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
1142
1143/// An open tally of the pcurve fits made on this thread — see
1144/// [`PcurveFitLedger`]. Open it where an operation starts, [`close`] it where
1145/// the operation returns its diagnostics; a `?` that unwinds past it drops the
1146/// tally.
1147///
1148/// [`close`]: PcurveFitScope::close
1149pub struct PcurveFitScope {
1150    /// Not `Send`: the scope must close on the thread that opened it.
1151    _thread_bound: std::marker::PhantomData<*const ()>,
1152}
1153
1154impl PcurveFitScope {
1155    pub fn open() -> Self {
1156        PCURVE_FIT_SCOPES.with(|scopes| scopes.borrow_mut().push(PcurveFitLedger::default()));
1157        Self {
1158            _thread_bound: std::marker::PhantomData,
1159        }
1160    }
1161
1162    /// Take the tally, folding it into the enclosing scope if there is one.
1163    pub fn close(self) -> PcurveFitLedger {
1164        let ledger = PCURVE_FIT_SCOPES.with(|scopes| {
1165            let mut scopes = scopes.borrow_mut();
1166            let ledger = scopes.pop().unwrap_or_default();
1167            if let Some(parent) = scopes.last_mut() {
1168                parent.fold(&ledger);
1169            }
1170            ledger
1171        });
1172        std::mem::forget(self);
1173        ledger
1174    }
1175}
1176
1177impl Drop for PcurveFitScope {
1178    fn drop(&mut self) {
1179        PCURVE_FIT_SCOPES.with(|scopes| {
1180            scopes.borrow_mut().pop();
1181        });
1182    }
1183}
1184
1185pub(crate) fn record_fit(report: &PcurveFitReport) {
1186    // Per-fit trace for the convergence probes (`trim_floor_sweep_probe` and
1187    // its offset-shell sibling): one line per fit with the whole report, the
1188    // way `BREP_DEBUG_PCURVE` traces an endpoint failure.
1189    if env_read!("BREP_DEBUG_PCURVE_FIT").is_some() {
1190        eprintln!("PCURVE-FIT {report:?}");
1191    }
1192    PCURVE_FIT_SCOPES.with(|scopes| {
1193        if let Some(open) = scopes.borrow_mut().last_mut() {
1194            open.record(report);
1195        }
1196    });
1197}
1198
1199/// Largest 3D distance between `pcurve`'s image and `curve` at the
1200/// quarter-points of every span of `parameters` — the stations refinement
1201/// probes, over EVERY span. Evaluations only; nothing is inverted. The sweep
1202/// measures, it does not decide.
1203fn probe_residual(
1204    surface: &NurbsSurface,
1205    curve: &NurbsCurve,
1206    pcurve: &NurbsCurve,
1207    parameters: &[f64],
1208    domain: [f64; 2],
1209    _u_domain: [f64; 2],
1210    _v_domain: [f64; 2],
1211) -> Result<f64, String> {
1212    probe_residual_at(surface, curve, pcurve, parameters, domain, &[0.25, 0.5, 0.75])
1213}
1214
1215/// Extra interior points per sample span, at `j/17` for `j = 1..=16`, that
1216/// [`tracking_acceptance_residual`] reads IN ADDITION to [`probe_residual`]'s
1217/// quarter, mid and three-quarter points (nineteen fractions per span in
1218/// all), so it can never read below the three-point maximum on the same
1219/// curve. The three quarter-points under-read the sixteen-point maximum by
1220/// 3.3–6.5 % on the constructed-cylinder union's imprint pcurves, and sixteen
1221/// sit within 0.4 % of sixty-four there (2026-10-04); the Converged path keeps
1222/// its own read.
1223const TRACKING_ACCEPTANCE_POINTS: usize = 16;
1224
1225/// The same-parameter image-vs-edge distance of `pcurve` at `locals` (span
1226/// fractions) inside every span of `parameters`: the largest, or an error if
1227/// any is not finite.
1228fn probe_residual_at(
1229    surface: &NurbsSurface,
1230    curve: &NurbsCurve,
1231    pcurve: &NurbsCurve,
1232    parameters: &[f64],
1233    [t0, t1]: [f64; 2],
1234    locals: &[f64],
1235) -> Result<f64, String> {
1236    let mut worst = 0.0_f64;
1237    for span in parameters.windows(2) {
1238        for &local in locals {
1239            let fraction = span[0] + (span[1] - span[0]) * local;
1240            let parameter = pcurve.evaluate(fraction)?;
1241            let on_surface =
1242                section_surface_point(surface, parameter.x, parameter.y, true)?;
1243            let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1244            // `f64::max` drops a NaN operand, so a non-finite distance would
1245            // leave `worst` reading the finite stations only. A residual that
1246            // can accept a curve must have measured every station: fail
1247            // closed instead.
1248            let distance = on_surface.sub(on_curve).length();
1249            if !distance.is_finite() {
1250                return Err(format!(
1251                    "probe_residual: non-finite image distance {distance} at fraction {fraction}"
1252                ));
1253            }
1254            worst = worst.max(distance);
1255        }
1256    }
1257    Ok(worst)
1258}
1259
1260/// The probe fractions a native read takes for the given pcurves: both
1261/// domain ENDPOINTS, and the quarter points plus 16 interior points of every
1262/// span between each curve's OWN distinct knots (the installed interpolant's
1263/// spans, not the construction stations). Merged over all the curves, sorted
1264/// and deduplicated, so a standing fit and a candidate are read at the SAME
1265/// fractions.
1266pub(crate) fn native_probe_fractions(curves: &[&NurbsCurve]) -> Result<Vec<f64>, String> {
1267    let locals: Vec<f64> = [0.25, 0.5, 0.75]
1268        .into_iter()
1269        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
1270        .collect();
1271    let mut fractions = Vec::new();
1272    for curve in curves {
1273        let [q0, q1] = curve.domain()?;
1274        fractions.push(q0);
1275        fractions.push(q1);
1276        let mut knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k >= q0 && *k <= q1).collect();
1277        knots.dedup();
1278        for span in knots.windows(2).filter(|w| w[1] > w[0]) {
1279            for &local in &locals {
1280                fractions.push(span[0] + (span[1] - span[0]) * local);
1281            }
1282        }
1283    }
1284    fractions.sort_by(f64::total_cmp);
1285    fractions.dedup();
1286    Ok(fractions)
1287}
1288
1289/// One pcurve read at given probe fractions against the edge curve (whose
1290/// parameter is t0 + (t1 - t0) x fraction): the image's distance from the
1291/// edge point's FOOT on the carrier (its TRACKING, the part a pcurve can
1292/// improve; the foot is seeded at the pcurve's own uv, closed form on an
1293/// analytic carrier), the image's distance from the edge point itself (the
1294/// same-parameter DEVIATION), and the edge point's distance from the carrier
1295/// (its INHERITED STANDOFF). Maxima over the probes; fails closed on any
1296/// non-finite point or distance.
1297#[derive(Clone, Copy, Debug, PartialEq)]
1298struct NativeRead {
1299    tracking: f64,
1300    deviation: f64,
1301    standoff: f64,
1302}
1303
1304fn native_read(surface: &NurbsSurface, curve: &NurbsCurve, pcurve: &NurbsCurve, [t0, t1]: [f64; 2], fractions: &[f64]) -> Result<NativeRead, String> {
1305    let mut read = NativeRead { tracking: 0.0, deviation: 0.0, standoff: 0.0 };
1306    for &fraction in fractions {
1307        let parameter = pcurve.evaluate(fraction)?;
1308        let image = section_surface_point(surface, parameter.x, parameter.y, true)?;
1309        let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1310        let foot = crate::projection::project_point_to_surface_from_seed(surface, on_curve, [parameter.x, parameter.y])?;
1311        let tracking = image.sub(foot.point).length();
1312        let deviation = image.sub(on_curve).length();
1313        if !(tracking.is_finite() && deviation.is_finite() && foot.distance.is_finite()) {
1314            return Err(format!("native read: non-finite reading at fraction {fraction}"));
1315        }
1316        read.tracking = read.tracking.max(tracking);
1317        read.deviation = read.deviation.max(deviation);
1318        read.standoff = read.standoff.max(foot.distance);
1319    }
1320    Ok(read)
1321}
1322
1323/// Whether an off-carrier tracking candidate replaces the standing fit, both
1324/// read at the SAME probes ([`native_probe_fractions`] of both curves): its
1325/// tracking finite, within the unchanged floor and strictly lower, AND its
1326/// same-parameter deviation no worse (the reported total, inherited standoff
1327/// included, must not grow), AND its own refinement fields finite.
1328fn standoff_candidate_accepted(standing: NativeRead, candidate: NativeRead, candidate_fields_finite: bool, floor: f64) -> bool {
1329    candidate_fields_finite
1330        && candidate.tracking.is_finite()
1331        && candidate.deviation.is_finite()
1332        && candidate.tracking <= floor
1333        && candidate.tracking < standing.tracking
1334        && candidate.deviation <= standing.deviation
1335}
1336
1337/// [`probe_residual_at`] at [`probe_residual`]'s three quarter-points plus
1338/// [`TRACKING_ACCEPTANCE_POINTS`] evenly spaced interior points of every span
1339/// (nineteen per span): the maximum of the old three-point reading and the
1340/// sixteen-point one. It is the reading a budget-exit tracking candidate is
1341/// accepted on, and the residual it is then reported with.
1342fn tracking_acceptance_residual(
1343    surface: &NurbsSurface,
1344    curve: &NurbsCurve,
1345    pcurve: &NurbsCurve,
1346    parameters: &[f64],
1347    domain: [f64; 2],
1348) -> Result<f64, String> {
1349    let locals: Vec<f64> = [0.25, 0.5, 0.75]
1350        .into_iter()
1351        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
1352        .collect();
1353    probe_residual_at(surface, curve, pcurve, parameters, domain, &locals)
1354}
1355
1356/// Whether a projection-tracking candidate replaces the fit standing in
1357/// [`refine_pcurve`], given the `reading` it is judged on (see
1358/// [`judge_tracking_candidate`]). `standing_dense` says the standing fit's
1359/// reading is itself a nineteen-point one: a budget-exit candidate was taken.
1360///
1361/// While the standing reading is the fitter's own, a `Converged` candidate is
1362/// taken exactly as before (within the floor, better). A BUDGET exit
1363/// (`SampleCeiling`, `RoundBudget`, `Stalled`, `SpanFloor`) is taken only to
1364/// repair a standing fit that MISSES the floor, and only when its
1365/// nineteen-point reading is finite, within the unchanged floor and strictly
1366/// better. Once the standing reading is a nineteen-point one, every later
1367/// candidate is compared nineteen against nineteen: a Converged one must read
1368/// finite, within the floor and strictly better on the same stencil, and a
1369/// budget exit is never taken (the standing fit is then within the floor).
1370/// The exit label says how the loop stopped, not whether the curve is good: on
1371/// the 15° constructed-cylinder union all six imprint pcurves that shipped
1372/// 1.3e-7..7.0e-6 off had a tracking candidate reading 1.4e-8..9.95e-8 at
1373/// three points per span, discarded for its label (2026-10-04). A standing
1374/// fit already within the floor is never replaced by a budget exit, so every
1375/// in-floor fit is unchanged; a taken candidate keeps its own exit, samples
1376/// and raise, and reports the reading it was taken on.
1377fn tracking_candidate_accepted(standing: f64, standing_dense: bool, floor: f64, exit: PcurveFitExit, reading: f64) -> bool {
1378    if exit == PcurveFitExit::Converged && !standing_dense {
1379        return reading <= floor && reading < standing;
1380    }
1381    if exit != PcurveFitExit::Converged && !(standing > floor) {
1382        return false;
1383    }
1384    reading.is_finite() && reading <= floor && reading < standing
1385}
1386
1387/// The reading a tracking candidate is judged on, and whether it replaces the
1388/// standing fit: `own` (the candidate's own residual) for a Converged
1389/// candidate while the standing reading is the fitter's own; otherwise
1390/// `dense` ([`tracking_acceptance_residual`]'s nineteen points per span), read
1391/// only when the candidate could be taken. An error from `dense` declines.
1392/// [`refine_pcurve`] decides and traces through this one function.
1393fn judge_tracking_candidate(
1394    standing: f64,
1395    standing_dense: bool,
1396    floor: f64,
1397    exit: PcurveFitExit,
1398    own: f64,
1399    dense: impl FnOnce() -> Result<f64, String>,
1400) -> (Result<Option<f64>, String>, bool) {
1401    judge_tracking_candidate_with_bounds(standing, standing_dense, floor, exit, own, dense, false)
1402}
1403
1404fn judge_tracking_candidate_with_bounds(
1405    standing: f64,
1406    standing_dense: bool,
1407    floor: f64,
1408    exit: PcurveFitExit,
1409    own: f64,
1410    dense: impl FnOnce() -> Result<f64, String>,
1411    bounds: bool,
1412) -> (Result<Option<f64>, String>, bool) {
1413    // A budget exit's own residual probes the quarter points of every
1414    // returned span. They are a subset of the nineteen-point stencil, so its
1415    // maximum cannot fall below this already over-floor lower bound.
1416    if bounds && exit != PcurveFitExit::Converged && own > floor {
1417        if crate::profile::profile_enabled() { profile_line!("pcurve.reject_bound kind=quarter_residual"); }
1418        return (Ok(Some(own)), false);
1419    }
1420    let reading = if exit == PcurveFitExit::Converged && !standing_dense {
1421        Ok(Some(own))
1422    } else if exit == PcurveFitExit::Converged || standing > floor {
1423        dense().map(Some)
1424    } else {
1425        Ok(None)
1426    };
1427    let accepted = matches!(
1428        reading,
1429        Ok(Some(value)) if tracking_candidate_accepted(standing, standing_dense, floor, exit, value)
1430    );
1431    (reading, accepted)
1432}
1433
1434/// What one call to [`refine_pcurve`] achieved, beside the curve it left in
1435/// place.
1436struct Refinement {
1437    exit: PcurveFitExit,
1438    residual: f64,
1439    off_surface: f64,
1440    raised: bool,
1441    /// [`PcurveFitReport::clamped_excursion`] and
1442    /// [`PcurveFitReport::clamped_distance`] of the curve left in place.
1443    clamped: [f64; 2],
1444}
1445
1446/// Adaptive 3D-residual refinement of an interpolant, with the PER-TRIM sample
1447/// budget. Shared by [`fit_pcurve_on_surface`] (global inversion) and
1448/// [`fit_pcurve_on_surface_marched`] (seeded projection); `insert` is the one
1449/// step that differs — given a probe station's fraction, the current pcurve's
1450/// parameter there and the edge point, it returns the surface parameter to
1451/// interpolate through (or `None` to decline the station) and the distance
1452/// from the edge point to the surface at that station, its GAP.
1453///
1454/// **First pass.** Four rounds at [`MAX_PCURVE_SAMPLES`], each probing the
1455/// quarter-points of every span wider than 1e-3 of the parameter range and
1456/// inserting the stations over `floor`. Byte-for-byte the pre-2026-09-12
1457/// loop; every exit is classified ([`PcurveFitExit`]) and the residual is
1458/// measured on the RETURNED curve — over every span, unless the final round
1459/// probed every span, in which case that round's maximum already is.
1460///
1461/// **The raise.** A [`PcurveFitExit::SampleCeiling`] exit re-enters the four
1462/// rounds ONCE with [`PCURVE_RAISED_SAMPLES`], continuing from the samples it
1463/// has, when the residual exceeds `off_surface` by more than the floor — the
1464/// returned curve is worse than the edge curve's own distance from the
1465/// surface, so more samples CAN improve it. Measured on `25_cube_pierce_solid`
1466/// (2026-09-12): the edge curves there sit off their surfaces by up to 1.9e-4,
1467/// four of the eight ceiling exits already read their gap to four digits, and
1468/// raising those spent 900 inversions each for no change in the swept
1469/// residual. The raised pass therefore inserts only where the pcurve's surface
1470/// point is further than the floor from the PROJECTION of the edge point — its
1471/// tracking error, which the inversion just computed: it stops when the pcurve
1472/// tracks the surface's nearest point to the floor, which is the best any
1473/// pcurve can do, and reports [`PcurveFitExit::Stalled`] with the deviation it
1474/// actually reached when that is still over the floor. The limit of that pass
1475/// as the floor tightens is the projected edge curve itself, so a volume built
1476/// on it can be shown to converge; the deviation test alone cannot say that on
1477/// off-surface input. Grow-once, capped, deterministic.
1478#[allow(clippy::too_many_arguments)]
1479fn refine_pcurve(
1480    surface: &NurbsSurface,
1481    curve: &NurbsCurve,
1482    domain: [f64; 2],
1483    u_domain: [f64; 2],
1484    v_domain: [f64; 2],
1485    floor: f64,
1486    joins: &[f64],
1487    parameters: &mut Vec<f64>,
1488    raw: &mut Vec<[f64; 2]>,
1489    pcurve: &mut NurbsCurve,
1490    off_surface: f64,
1491    clamped: [f64; 2],
1492    mut insert: impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1493) -> Result<Refinement, String> {
1494    // Trace only (`BREP_DEBUG_PCURVE_FIT`): reads values the passes already
1495    // computed and decides nothing.
1496    let trace = env_read!("BREP_DEBUG_PCURVE_FIT").is_some();
1497    let call = if trace {
1498        PCURVE_TRACK_CALL.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + 1
1499    } else {
1500        0
1501    };
1502    let reject_bounds = PCURVE_REJECT_BOUNDS.with(|state| state.get());
1503    let mut best = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain,
1504        floor, joins, parameters, raw, pcurve, off_surface, clamped, false, 1.0, false, &mut insert, false)?;
1505    if trace {
1506        eprintln!(
1507            "PCURVE-TRACK call={call} first-pass exit={:?} residual={:e} floor={floor:e} off_surface={:e} samples={} raised={} tracking={}",
1508            best.exit,
1509            best.residual,
1510            best.off_surface,
1511            parameters.len(),
1512            best.raised,
1513            if best.off_surface <= floor { "eligible" } else { "standoff-tracking" }
1514        );
1515    }
1516    if best.off_surface > floor {
1517        // The edge curve itself stands off the carrier by more than the floor
1518        // (its INHERITED standoff), so no pcurve can bring the image within the
1519        // floor of the edge point. What a pcurve CAN improve is its tracking
1520        // error: the image's distance from the edge point's foot. Measured
1521        // 2026-10-04 (a2b401d4d, 15-degree crossing, turn 295): a first pass
1522        // ended RoundBudget at 6.726e-6 over a 1.316e-7 standoff and every
1523        // tracking pass was skipped. No candidate refinement when the ACTUAL
1524        // tracking request is met: the first pass's own tracking, read on its
1525        // native spans and endpoints (a diagnostic read; it adds no station),
1526        // within the floor ([`standoff_tracking_rungs`]). A total residual
1527        // under standoff + floor does not prove that: a tangential slip t over
1528        // a standoff g reads sqrt(g^2 + t^2) < g + t.
1529        // `BREP_PCURVE_STANDOFF_TRACKING=0`: diagnostic A/B hatch, not a
1530        // policy. It restores the pre-lane answer (35c8610a1's parent: an
1531        // off-carrier first pass is returned as it stands) for a same-binary
1532        // attribution of a volume or census delta to this lane. Default (unset
1533        // or any other value) is unchanged. It does not touch the in-floor
1534        // tracking rungs or their raise rule, nor the range lane's end-span
1535        // challenger.
1536        if !standoff_tracking_enabled() {
1537            return Ok(best);
1538        }
1539        return standoff_tracking_rungs(surface, curve, domain, u_domain, v_domain, floor, joins,
1540            parameters, raw, pcurve, best, trace, call, &mut insert);
1541    }
1542    // Each target starts from the same baseline station set: retaining the
1543    // coarser target's inserts can exhaust the cap before the finer target
1544    // places its own error-directed stations. Keep the best rung
1545    // [`tracking_candidate_accepted`] takes.
1546    let baseline_parameters = parameters.clone();
1547    let baseline_raw = raw.clone();
1548    let baseline_curve = pcurve.clone();
1549    let baseline_off_surface = best.off_surface;
1550    let baseline_clamped = best.clamped;
1551    // Whether the first pass MISSED the floor: only then may a tracking
1552    // candidate that reaches the sample ceiling still missing its request take
1553    // the existing one-time raise (2026-10-04, 20-degree crossing, turn 295:
1554    // a 1.964e-6 first pass, a candidate at 600 samples reading 1.068e-7,
1555    // declined; the raise needed residual > off_surface + floor). A first pass
1556    // within the floor keeps exactly the work it did before.
1557    // (On this path the edge stands within the floor of the carrier, so a
1558    // first pass over the floor is a tracking miss, not inherited standoff.)
1559    let standing_misses = best.residual > floor;
1560    Ok(tracking_rungs(
1561        best,
1562        floor,
1563        trace,
1564        call,
1565        true,
1566        |fraction| {
1567            let mut refined_parameters = baseline_parameters.clone();
1568            let mut refined_raw = baseline_raw.clone();
1569            let mut refined_curve = baseline_curve.clone();
1570            let candidate = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain,
1571                floor, joins, &mut refined_parameters, &mut refined_raw, &mut refined_curve,
1572                baseline_off_surface, baseline_clamped, true, fraction, standing_misses, &mut insert, reject_bounds && !standing_misses);
1573            (candidate, (refined_parameters, refined_raw, refined_curve))
1574        },
1575        |state: &RungState| tracking_acceptance_residual(surface, curve, &state.2, &state.0, domain),
1576        |state: &RungState| state.0.len(),
1577        |(refined_parameters, refined_raw, refined_curve): RungState| {
1578            *parameters = refined_parameters;
1579            *raw = refined_raw;
1580            *pcurve = refined_curve;
1581        },
1582    ))
1583}
1584
1585/// A tracking candidate's station parameters, raw surface parameters and
1586/// pcurve, as [`refine_pcurve`] hands them to [`tracking_rungs`].
1587type RungState = (Vec<f64>, Vec<[f64; 2]>, NurbsCurve);
1588
1589/// The tracking rungs of [`refine_pcurve`] after an eligible first pass: for
1590/// each tracking fraction, skip it if the standing fit is already that far
1591/// inside the floor, otherwise run the candidate pass (`run_pass`), judge it
1592/// ([`judge_tracking_candidate`], reading `dense` only when needed), trace
1593/// it, and either take it (`adopt` its state; it becomes the standing fit) or
1594/// stop. `samples` is the candidate's station count, for the trace. Separated
1595/// so the accepted-budget state can be driven with scripted passes;
1596/// `thread_dense` is `true` in production and `false` only to show, in a
1597/// test, what dropping the nineteen-point standing flag would take.
1598#[allow(clippy::too_many_arguments)]
1599fn tracking_rungs<S>(
1600    mut best: Refinement,
1601    floor: f64,
1602    trace: bool,
1603    call: u64,
1604    thread_dense: bool,
1605    mut run_pass: impl FnMut(f64) -> (Result<Refinement, String>, S),
1606    mut dense: impl FnMut(&S) -> Result<f64, String>,
1607    samples: impl Fn(&S) -> usize,
1608    mut adopt: impl FnMut(S),
1609) -> Refinement {
1610    // Whether the standing reading is a nineteen-point one (a budget-exit
1611    // candidate was taken); every later candidate is then judged on it.
1612    let mut standing_dense = false;
1613    let reject_bounds = PCURVE_REJECT_BOUNDS.with(|state| state.get());
1614    for fraction in [0.1, 0.01] {
1615        if best.residual <= floor * fraction {
1616            if trace {
1617                eprintln!(
1618                    "PCURVE-TRACK call={call} candidate fraction={fraction} skipped best_residual={:e} <= {:e}",
1619                    best.residual,
1620                    floor * fraction
1621                );
1622            }
1623            continue;
1624        }
1625        let (candidate, state) = run_pass(fraction);
1626        // The reading the candidate is judged on and the decision (see
1627        // judge_tracking_candidate); an unreadable read declines like a
1628        // failed pass.
1629        let judged_dense = matches!(&candidate, Ok(seen) if seen.exit != PcurveFitExit::Converged || standing_dense);
1630        let (effective, accepted) = match &candidate {
1631            Ok(seen) => judge_tracking_candidate_with_bounds(best.residual, standing_dense, floor, seen.exit, seen.residual, || {
1632                dense(&state)
1633            }, reject_bounds),
1634            Err(_) => (Ok(None), false),
1635        };
1636        if trace {
1637            let judged_on = match &effective {
1638                Ok(Some(reading)) => format!("{reading:e}"),
1639                Ok(None) => "-".to_string(),
1640                Err(message) => format!("error:{message:?}"),
1641            };
1642            match &candidate {
1643                Ok(seen) => eprintln!(
1644                    "PCURVE-TRACK call={call} candidate fraction={fraction} exit={:?} residual={:e} judged_on={judged_on} standing_dense={standing_dense} floor={floor:e} off_surface={:e} samples={} raised={} residual_meets_floor={} decision={}",
1645                    seen.exit,
1646                    seen.residual,
1647                    seen.off_surface,
1648                    samples(&state),
1649                    seen.raised,
1650                    seen.residual <= floor,
1651                    if accepted { "accept" } else { "decline-stop" }
1652                ),
1653                Err(message) => eprintln!(
1654                    "PCURVE-TRACK call={call} candidate fraction={fraction} error={message:?} decision=decline-stop"
1655                ),
1656            }
1657        }
1658        match candidate {
1659            Ok(mut candidate) if accepted => {
1660                // Report the reading it was taken on (its own, if Converged).
1661                if let Ok(Some(reading)) = effective {
1662                    candidate.residual = reading;
1663                }
1664                // From here on the standing reading is a nineteen-point one.
1665                if thread_dense {
1666                    standing_dense |= judged_dense;
1667                }
1668                adopt(state);
1669                best = candidate;
1670            }
1671            _ => break,
1672        }
1673    }
1674    best
1675}
1676
1677/// Whether [`refine_pcurve`] takes [`standoff_tracking_rungs`] for an
1678/// off-carrier first pass: true unless `BREP_PCURVE_STANDOFF_TRACKING=0`
1679/// (diagnostic A/B hatch, read once per process).
1680fn standoff_tracking_enabled() -> bool {
1681    switch!("BREP_PCURVE_STANDOFF_TRACKING", true)
1682}
1683
1684/// The tracking rungs for an edge curve that stands OFF its carrier by more
1685/// than the floor ([`refine_pcurve`]). The first pass is read natively
1686/// ([`native_read`] on its own knot spans and endpoints); when its tracking is
1687/// within the floor, or the read fails, nothing more is done. Otherwise each
1688/// candidate pass (fractions 0.1 then 0.01 of the floor, from the same
1689/// baseline stations, taking the one-time raise when its own tracking target
1690/// is cut short by the ceiling) is read with the standing fit at the SAME
1691/// probes (both curves' native spans and endpoints) and taken only per
1692/// [`standoff_candidate_accepted`]: tracking finite, within the unchanged
1693/// floor and strictly lower, same-parameter deviation no worse, refinement
1694/// fields finite. A taken fit is REPORTED with its same-probe deviation
1695/// (inherited standoff included, so still over the floor) and with an
1696/// `off_surface` that is the larger of its station reading and the probes'
1697/// standoff. Any error, or a candidate that does not qualify, stops the loop
1698/// and keeps the standing curve and report.
1699#[allow(clippy::too_many_arguments)]
1700fn standoff_tracking_rungs(
1701    surface: &NurbsSurface,
1702    curve: &NurbsCurve,
1703    domain: [f64; 2],
1704    u_domain: [f64; 2],
1705    v_domain: [f64; 2],
1706    floor: f64,
1707    joins: &[f64],
1708    parameters: &mut Vec<f64>,
1709    raw: &mut Vec<[f64; 2]>,
1710    pcurve: &mut NurbsCurve,
1711    mut best: Refinement,
1712    trace: bool,
1713    call: u64,
1714    insert: &mut impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1715) -> Result<Refinement, String> {
1716    let first = native_probe_fractions(&[&*pcurve]).and_then(|probes| native_read(surface, curve, pcurve, domain, &probes));
1717    if trace {
1718        eprintln!("PCURVE-TRACK call={call} standoff-tracking first-pass native={first:?} floor={floor:e}");
1719    }
1720    let Ok(first) = first else { return Ok(best) };
1721    if first.tracking <= floor {
1722        return Ok(best);
1723    }
1724    let baseline_parameters = parameters.clone();
1725    let baseline_raw = raw.clone();
1726    let baseline_curve = pcurve.clone();
1727    for fraction in [0.1, 0.01] {
1728        let mut refined_parameters = baseline_parameters.clone();
1729        let mut refined_raw = baseline_raw.clone();
1730        let mut refined_curve = baseline_curve.clone();
1731        let candidate = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain, floor, joins,
1732            &mut refined_parameters, &mut refined_raw, &mut refined_curve, best.off_surface, best.clamped,
1733            true, fraction, true, &mut *insert, false);
1734        let reads = candidate.as_ref().ok().map(|_| {
1735            native_probe_fractions(&[&*pcurve, &refined_curve]).and_then(|probes| {
1736                Ok((native_read(surface, curve, pcurve, domain, &probes)?, native_read(surface, curve, &refined_curve, domain, &probes)?))
1737            })
1738        });
1739        let fields_finite = matches!(&candidate, Ok(seen) if seen.residual.is_finite() && seen.off_surface.is_finite());
1740        let decision = match &reads {
1741            Some(Ok((standing, read))) => standoff_rung_decision(*standing, *read, fields_finite, floor),
1742            _ => RungDecision::Stop,
1743        };
1744        if trace {
1745            eprintln!(
1746                "PCURVE-TRACK call={call} standoff-tracking fraction={fraction} candidate={} reads={reads:?} decision={}",
1747                match &candidate { Ok(seen) => format!("{:?}/{:e}/raised={}", seen.exit, seen.residual, seen.raised), Err(message) => format!("error:{message:?}") },
1748                match decision { RungDecision::Accept => "accept", RungDecision::Continue => "decline-continue", RungDecision::Stop => "decline-stop" }
1749            );
1750        }
1751        let (Ok(mut taken), Some(Ok((_, read))), RungDecision::Accept) = (candidate, reads, decision) else {
1752            if decision == RungDecision::Continue {
1753                continue;
1754            }
1755            break;
1756        };
1757        taken.residual = read.deviation;
1758        taken.off_surface = taken.off_surface.max(read.standoff);
1759        *parameters = refined_parameters;
1760        *raw = refined_raw;
1761        *pcurve = refined_curve;
1762        best = taken;
1763        if read.tracking <= floor * 0.01 {
1764            break;
1765        }
1766    }
1767    Ok(best)
1768}
1769
1770/// What one off-carrier tracking rung does with its candidate
1771/// ([`standoff_tracking_rungs`]).
1772#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1773enum RungDecision {
1774    /// Taken ([`standoff_candidate_accepted`]).
1775    Accept,
1776    /// Not taken, but it read finite and LOWER tracking than the standing fit
1777    /// while over the floor: the finer fraction is still tried from the same
1778    /// baseline (fixture 25 on e90c30c94: one use read 2.33e-7 at 0.1 and
1779    /// stopped while its partner was taken at 9.0e-9).
1780    Continue,
1781    /// Not taken and not improving (or unreadable): the rungs end.
1782    Stop,
1783}
1784
1785fn standoff_rung_decision(standing: NativeRead, candidate: NativeRead, fields_finite: bool, floor: f64) -> RungDecision {
1786    if standoff_candidate_accepted(standing, candidate, fields_finite, floor) {
1787        RungDecision::Accept
1788    } else if candidate.tracking.is_finite() && candidate.tracking < standing.tracking {
1789        RungDecision::Continue
1790    } else {
1791        RungDecision::Stop
1792    }
1793}
1794
1795/// The one-time raise decision of [`refine_pcurve_pass`]: a ceiling exit not
1796/// yet raised, when the returned curve is worse than the edge's own gap by
1797/// more than the floor (the original rule), or when a tracking pass for an
1798/// unmet first pass returned a curve whose own tracking still misses the
1799/// pass's target (`unmet_tracking`, read on the returned curve). Nothing else
1800/// raises.
1801fn takes_raise(exit: PcurveFitExit, raised: bool, residual: f64, off_surface: f64, floor: f64, unmet_tracking: bool) -> bool {
1802    exit == PcurveFitExit::SampleCeiling && !raised && (residual > off_surface + floor || unmet_tracking)
1803}
1804
1805fn refine_pcurve_pass(
1806    surface: &NurbsSurface,
1807    curve: &NurbsCurve,
1808    [t0, t1]: [f64; 2],
1809    [u0, u1]: [f64; 2],
1810    [v0, v1]: [f64; 2],
1811    floor: f64,
1812    joins: &[f64],
1813    parameters: &mut Vec<f64>,
1814    raw: &mut Vec<[f64; 2]>,
1815    pcurve: &mut NurbsCurve,
1816    mut off_surface: f64,
1817    mut clamped: [f64; 2],
1818    track_projection: bool,
1819    tracking_fraction: f64,
1820    raise_unmet_tracking: bool,
1821    mut insert: impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1822    reject_budget: bool,
1823) -> Result<Refinement, String> {
1824    let _clock = PcurvePhaseClock::new("refinement", parameters.len(), track_projection);
1825    let tracking_floor = if track_projection { floor * tracking_fraction } else { floor };
1826    let mut max_samples = MAX_PCURVE_SAMPLES;
1827    let mut raised = false;
1828    loop {
1829        // Every way out of this loop is CLASSIFIED (`PcurveFitExit`); a budget
1830        // exit returns the curve it built, but says so. Falling off the end
1831        // after a fourth round of inserts is the round-budget exit.
1832        let mut exit = PcurveFitExit::RoundBudget;
1833        let mut residual = None;
1834        for round in 0..4 {
1835            if parameters.len() >= max_samples {
1836                exit = PcurveFitExit::SampleCeiling;
1837                break;
1838            }
1839            let mut inserts = Vec::new();
1840            let mut round_max = 0.0_f64;
1841            let mut truncated = false;
1842            let mut skipped_narrow = false;
1843            for index in 0..parameters.len() - 1 {
1844                if parameters.len() + inserts.len() >= max_samples {
1845                    truncated = true;
1846                    break;
1847                }
1848                let start = parameters[index];
1849                let end = parameters[index + 1];
1850                // Keep construction's existing first-pass policy. Extended
1851                // residual probes must not silently change its station ladder;
1852                // projection tracking retains its established finer floor.
1853                if end - start < if track_projection { SPAN_FLOOR } else { 1e-3 } {
1854                    skipped_narrow = true;
1855                    continue;
1856                }
1857                for local_fraction in [0.25, 0.5, 0.75] {
1858                    if parameters.len() + inserts.len() >= max_samples {
1859                        truncated = true;
1860                        break;
1861                    }
1862                    let fraction = start + (end - start) * local_fraction;
1863                    let parameter = pcurve.evaluate(fraction)?;
1864                    let on_surface =
1865                        section_surface_point(surface, parameter.x, parameter.y, true)?;
1866                    let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1867                    let deviation = on_surface.sub(on_curve).length();
1868                    // A non-finite distance must not reach `f64::max` (which
1869                    // drops NaN) or the classification below, where a round
1870                    // with an unreadable station could still exit Converged on
1871                    // its readable ones. Fail closed: a first pass's error
1872                    // goes to its caller, a tracking candidate's declines it.
1873                    if !deviation.is_finite() {
1874                        return Err(format!(
1875                            "refine_pcurve_pass: non-finite station distance {deviation} at fraction {fraction}"
1876                        ));
1877                    }
1878                    round_max = round_max.max(deviation);
1879                    if deviation <= tracking_floor {
1880                        continue;
1881                    }
1882                    let (surface_parameter, gap) = insert(fraction, parameter, on_curve)?;
1883                    off_surface = off_surface.max(gap);
1884                    if let Some(surface_parameter) = surface_parameter {
1885                        // The raised pass stops where the pcurve TRACKS the
1886                        // edge curve's projection to the floor — the best any
1887                        // pcurve can do at this station. Not `deviation - gap`:
1888                        // a surface point at tangential distance d from the
1889                        // projection of a point g off the surface is only
1890                        // d^2/(2g) further from it, so the deviation test is
1891                        // quadratically blind to sideways error on off-surface
1892                        // input (6e-6 of slop at g = 1.9e-4, floor 1e-7).
1893                        if raised || track_projection {
1894                            let projected =
1895                                section_surface_point(surface, surface_parameter[0], surface_parameter[1], false)?;
1896                            if on_surface.sub(projected).length() <= tracking_floor {
1897                                continue;
1898                            }
1899                        }
1900                        inserts.push((index + 1, fraction, surface_parameter));
1901                    }
1902                }
1903            }
1904            if inserts.is_empty() {
1905                // Nothing to insert: every probed station is within the floor
1906                // (converged — unless a narrow span was skipped, in which case
1907                // the sweep below decides), or the ones over it could not be
1908                // improved (stalled — the edge curve is off the surface there).
1909                exit = if truncated {
1910                    PcurveFitExit::SampleCeiling
1911                } else if round_max > floor {
1912                    PcurveFitExit::Stalled
1913                } else if skipped_narrow {
1914                    PcurveFitExit::SpanFloor
1915                } else {
1916                    residual = Some(round_max);
1917                    PcurveFitExit::Converged
1918                };
1919                break;
1920            }
1921            // With inserts still needed after the fourth non-truncated
1922            // round, this exit is RoundBudget. An in-floor standing fit
1923            // never adopts any budget exit; rebuilding and probing this
1924            // discarded candidate cannot affect its curve or report.
1925            if reject_budget && round == 3 && !truncated {
1926                if crate::profile::profile_enabled() { profile_line!("pcurve.reject_bound kind=fifth_round"); }
1927                return Err("pcurve tracking candidate requires a fifth round".into());
1928            }
1929            for (at, fraction, surface_parameter) in inserts.into_iter().rev() {
1930                parameters.insert(at, fraction);
1931                raw.insert(at, surface_parameter);
1932            }
1933            let (rebuilt, excursion, distance) = build_interpolant_joined(surface, raw, parameters, joins)?;
1934            *pcurve = rebuilt;
1935            clamped = [excursion, distance];
1936            if truncated {
1937                exit = PcurveFitExit::SampleCeiling;
1938                break;
1939            }
1940        }
1941        let residual = match residual {
1942            Some(measured) => measured,
1943            // A budget exit never re-checked the curve it is returning, and a
1944            // converged round that skipped narrow spans never checked those:
1945            // measure every span.
1946            None => probe_residual(
1947                surface,
1948                curve,
1949                pcurve,
1950                parameters,
1951                [t0, t1],
1952                [u0, u1],
1953                [v0, v1],
1954            )?,
1955        };
1956        if exit == PcurveFitExit::SpanFloor && residual <= floor {
1957            exit = PcurveFitExit::Converged;
1958        }
1959        // The per-trim budget decision. Deterministic, grow-once, capped (I3):
1960        // the ceiling bound and the returned curve is worse than the edge
1961        // curve's own gap from the surface by more than the floor, so samples
1962        // can still buy accuracy. A curve already at its gap stops here —
1963        // reported, not retried.
1964        // A TRACKING pass for a standing fit that missed the floor (and only
1965        // then) also takes the same one-time raise when it hits the ceiling
1966        // still over the floor: its request is the projection's tracking, and
1967        // the ceiling cut it short. The raised maximum itself is unchanged.
1968        // The added raise serves a TRACKING pass for an unmet first pass whose
1969        // RETURNED curve still misses the pass's own target: its tracking (the
1970        // image against the projected foot, read natively on its own knot spans
1971        // and endpoints) over the tracking floor (floor x fraction). Reaching
1972        // the ceiling alone is exhaustion, not a miss, and the inherited
1973        // standoff never triggers it. Read only at a ceiling exit not yet
1974        // raised; an unreadable read does not raise.
1975        let unmet_tracking = track_projection
1976            && raise_unmet_tracking
1977            && exit == PcurveFitExit::SampleCeiling
1978            && !raised
1979            && native_probe_fractions(&[&*pcurve])
1980                .and_then(|probes| native_read(surface, curve, pcurve, [t0, t1], &probes))
1981                .is_ok_and(|read| read.tracking > tracking_floor);
1982        if takes_raise(exit, raised, residual, off_surface, floor, unmet_tracking) {
1983            raised = true;
1984            max_samples = PCURVE_RAISED_SAMPLES;
1985            continue;
1986        }
1987        return Ok(Refinement {
1988            exit,
1989            residual,
1990            off_surface,
1991            raised,
1992            clamped,
1993        });
1994    }
1995}
1996
1997/// The exact inverse of an affine carrier's parameterization.
1998///
1999/// An affine patch (2x2 net, degree 1 both ways, equal weights) maps `uv` to 3D
2000/// by an affine map, so the inverse — a 3D point to the `uv` of its orthogonal
2001/// projection — is affine too. An affine map commutes with the rational basis:
2002/// sending a curve's control points through it and keeping the weights
2003/// produces the EXACT image of that curve in parameter space, not a fit of it.
2004struct AffineInversion {
2005    origin: Vec3,
2006    du: Vec3,
2007    dv: Vec3,
2008    u0: f64,
2009    v0: f64,
2010    uu: f64,
2011    uv: f64,
2012    vv: f64,
2013    determinant: f64,
2014}
2015
2016impl AffineInversion {
2017    /// `None` when `surface` is not affine, or when its two directions are
2018    /// parallel enough that the inverse is not determined. The caller decides
2019    /// what that means: a refusal on the whole-curve lane, the sampled lane on
2020    /// the range lane.
2021    fn of(surface: &NurbsSurface) -> Result<Option<Self>, String> {
2022        if !surface.is_affine()? {
2023            return Ok(None);
2024        }
2025        let ([u0, _], [v0, _]) = surface_domains(surface)?;
2026        let (origin, du, dv) = surface.deriv1(u0, v0)?;
2027        let uu = du.dot(du);
2028        let uv = du.dot(dv);
2029        let vv = dv.dot(dv);
2030        let determinant = uu * vv - uv * uv;
2031        if determinant.abs() <= 1e-18 {
2032            return Ok(None);
2033        }
2034        Ok(Some(Self {
2035            origin,
2036            du,
2037            dv,
2038            u0,
2039            v0,
2040            uu,
2041            uv,
2042            vv,
2043            determinant,
2044        }))
2045    }
2046
2047    fn uv_of(&self, point: Vec3) -> [f64; 2] {
2048        let delta = point.sub(self.origin);
2049        let along_u = delta.dot(self.du);
2050        let along_v = delta.dot(self.dv);
2051        [
2052            self.u0 + (along_u * self.vv - along_v * self.uv) / self.determinant,
2053            self.v0 + (along_v * self.uu - along_u * self.uv) / self.determinant,
2054        ]
2055    }
2056
2057    /// The exact image of `curve` in this carrier's parameter space, with the
2058    /// curve's own degree, knots and weights.
2059    fn image_of(&self, curve: &NurbsCurve) -> Result<NurbsCurve, String> {
2060        let control_points = curve
2061            .control_points
2062            .iter()
2063            .map(|control| {
2064                let [u, v] = self.uv_of(control.point()?);
2065                Ok(Vec4::from_point(Vec3::new(u, v, 0.0), control.w))
2066            })
2067            .collect::<Result<Vec<_>, String>>()?;
2068        NurbsCurve::new(curve.degree, curve.knots.clone(), control_points)
2069    }
2070}
2071
2072fn sphere_iso_enabled() -> bool {
2073    env_read!("BREP_PCURVE_SPHERE_ISO").is_none_or(|mode| mode != "0")
2074}
2075
2076/// A complete native meridian with the same rational basis as the section.
2077/// Equal positive weights and affinely identical knots make its image minus
2078/// the section a convex combination of control-point differences. Thus their
2079/// maximum norm bounds the whole curve, including the pole endpoints. This
2080/// avoids fitting an arbitrary longitude at a pole into a meridian's interior.
2081/// Every failed recognition retains the ordinary fitter and its diagnostics.
2082fn sphere_iso_fit(surface: &NurbsSurface, curve: &NurbsCurve) -> Option<PcurveFit> {
2083    // Native sphere recognition requires quadratic u. Avoid warming other
2084    // carriers, and validate before recognition indexes a deserialized net.
2085    if surface.degree_u != 2 { return None; }
2086    let [t0, t1] = curve.domain().ok()?;
2087    let [u0, u1] = surface.domain_u().ok()?;
2088    let [v0, v1] = surface.domain_v().ok()?;
2089    if !matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })) { return None; }
2090    let middle = curve.evaluate(t0 + (t1 - t0) * 0.5).ok()?;
2091    let projected = project_point_to_surface(surface, middle).ok()?;
2092    let mut candidates = vec![projected.u];
2093    // Cardinal meridians can invert an ulp beside their native knot. A snap
2094    // is only a candidate: the complete control-net bound below must hold.
2095    for &knot in &surface.knots_u {
2096        if (knot - projected.u).abs() <= 1e-12 && !candidates.contains(&knot) { candidates.push(knot); }
2097    }
2098    for u in candidates {
2099        if !(u >= u0 && u <= u1) { continue; }
2100        let iso = surface.iso_curve_u(u).ok()?;
2101        if iso.degree != curve.degree || iso.knots.len() != curve.knots.len()
2102            || iso.control_points.len() != curve.control_points.len() { continue; }
2103        for reverse in [false, true] {
2104            let n = iso.control_points.len();
2105            // Rounded quotient equality alone does not prove equal bases.
2106            // TwoDiff proves the subtractions exact; FMA then proves that
2107            // each normalized knot times its span equals the exact offset.
2108            // Conservative magnitude bounds keep all product residuals well
2109            // above underflow. Unusual domains simply use the ordinary fit.
2110            fn exact_difference(a: f64, b: f64) -> Option<f64> {
2111                if !(a.is_finite() && b.is_finite()) || a.abs().max(b.abs()) > 1e100 { return None; }
2112                let x = a - b;
2113                let bv = a - x;
2114                let av = x + bv;
2115                let error = (a - av) + (bv - b);
2116                (error == 0.).then_some(x)
2117            }
2118            fn exact_fraction(offset: f64, span: f64) -> Option<f64> {
2119                if !(1e-100..=1e100).contains(&span) { return None; }
2120                let ratio = offset / span;
2121                if !(0.0..=1.0).contains(&ratio) || (ratio != 0. && ratio < 1e-100) { return None; }
2122                (ratio.mul_add(span, -offset) == 0.).then_some(ratio)
2123            }
2124            let knots_match = (|| {
2125                let section_span = exact_difference(t1, t0)?;
2126                let native_span = exact_difference(v1, v0)?;
2127                for (i, &knot) in curve.knots.iter().enumerate() {
2128                    let section = exact_difference(knot, t0)?;
2129                    let native = if reverse { exact_difference(v1, iso.knots[iso.knots.len() - 1 - i])? }
2130                        else { exact_difference(iso.knots[i], v0)? };
2131                    if exact_fraction(section, section_span)? != exact_fraction(native, native_span)? { return None; }
2132                }
2133                Some(())
2134            })().is_some();
2135            if !knots_match { continue; }
2136            let mut bound = 0.0_f64;
2137            let mut matches = true;
2138            for (i, control) in curve.control_points.iter().enumerate() {
2139                let native = &iso.control_points[if reverse { n - 1 - i } else { i }];
2140                if !(control.w > 0.) || control.w != native.w { matches = false; break; }
2141                let distance = control.point().ok()?.sub(native.point().ok()?).length();
2142                if !distance.is_finite() { matches = false; break; }
2143                bound = bound.max(distance);
2144            }
2145            if !matches || bound > PCURVE_REFINEMENT_TOLERANCE * 0.0625 { continue; }
2146            let (start, end) = if reverse { (v1, v0) } else { (v0, v1) };
2147            let pcurve = NurbsCurve::new(1, vec![0., 0., 1., 1.], vec![
2148                Vec4::from_point(Vec3::new(u, start, 0.), 1.),
2149                Vec4::from_point(Vec3::new(u, end, 0.), 1.),
2150            ]).ok()?;
2151            // Confirm the actual floating-point evaluation too, on the
2152            // ordinary first pass's 24 intervals and quarter stations. The
2153            // control-net proof covers between probes; these reads guard
2154            // roundoff from differing surface/curve evaluation orders.
2155            for i in 0..=96 {
2156                let fraction = i as f64 / 96.;
2157                let uv = pcurve.evaluate(fraction).ok()?;
2158                let image = surface.evaluate(uv.x, uv.y).ok()?;
2159                let on_curve = curve.evaluate(t0 + (t1 - t0) * fraction).ok()?;
2160                let error = image.sub(on_curve).length();
2161                if !error.is_finite() { matches = false; break; }
2162                bound = bound.max(error);
2163            }
2164            if !matches || bound > PCURVE_REFINEMENT_TOLERANCE * 0.0625 { continue; }
2165            return Some(PcurveFit { curve: pcurve, report: PcurveFitReport {
2166                residual: bound, floor: PCURVE_REFINEMENT_TOLERANCE, samples: 2,
2167                exit: PcurveFitExit::Converged, off_surface: bound, raised: false,
2168                clamped_excursion: 0., clamped_distance: 0.,
2169            } });
2170        }
2171    }
2172    None
2173}
2174
2175/// Build a parameter-space curve for a 3D curve lying on a surface, and say
2176/// what the fit achieved.
2177///
2178/// This mirrors the reference imprint implementation: affine patches map
2179/// homogeneous control points exactly; general patches use sampled inversion,
2180/// periodic seam unwrapping, and adaptive 3D residual refinement. The report
2181/// beside the curve carries the residual the RETURNED curve reaches and why
2182/// refinement stopped ([`PcurveFitReport`]); the curve itself is what
2183/// [`build_pcurve_on_surface`] has always returned.
2184pub fn fit_pcurve_on_surface(
2185    surface: &NurbsSurface,
2186    curve: &NurbsCurve,
2187) -> Result<PcurveFit, String> {
2188    if sphere_iso_enabled() {
2189        if let Some(fit) = sphere_iso_fit(surface, curve) { return Ok(fit); }
2190    }
2191    let mode = env_read!("BREP_PCURVE_EVAL_CACHE").unwrap_or_default();
2192    let bounds = env_read!("BREP_PCURVE_REJECT_BOUNDS").unwrap_or_else(|| "on".into());
2193    let stack = env_read!("BREP_PCURVE_STACK_POINT").unwrap_or_else(|| "on".into());
2194    if mode == "check" || bounds == "check" || stack == "check" {
2195        let old = fit_pcurve_on_surface_cached(surface, curve, false, false, false)?;
2196        if matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })) {
2197            let candidate = fit_pcurve_on_surface_cached(surface, curve, mode == "check" || mode == "on" || mode == "1", bounds == "check" || bounds == "on" || bounds == "1", stack == "check" || stack == "on" || stack == "1");
2198            let identical = candidate.as_ref().is_ok_and(|new| {
2199                old.curve.degree == new.curve.degree
2200                    && old.curve.knots.len() == new.curve.knots.len()
2201                    && old.curve.knots.iter().zip(&new.curve.knots).all(|(a, b)| a.to_bits() == b.to_bits())
2202                    && old.curve.control_points.len() == new.curve.control_points.len()
2203                    && old.curve.control_points.iter().zip(&new.curve.control_points).all(|(a, b)| {
2204                        [a.x.to_bits(), a.y.to_bits(), a.z.to_bits(), a.w.to_bits()]
2205                            == [b.x.to_bits(), b.y.to_bits(), b.z.to_bits(), b.w.to_bits()]
2206                    }) && old.report == new.report
2207            });
2208            if let Ok(path) = std::env::var("BREP_PCURVE_EVAL_CENSUS") {
2209                use std::io::Write;
2210                if let Ok(mut file) = std::fs::OpenOptions::new().create(true).append(true).open(path) {
2211                    let _ = writeln!(file, "pcurve.eval_census identical={identical} controls={} samples={}", old.curve.control_points.len(), old.report.samples);
2212                }
2213            }
2214        }
2215        return Ok(old);
2216    }
2217    fit_pcurve_on_surface_cached(surface, curve, mode == "1" || mode == "on", bounds == "1" || bounds == "on", stack == "1" || stack == "on")
2218}
2219
2220fn fit_pcurve_on_surface_cached(surface: &NurbsSurface, curve: &NurbsCurve, enabled: bool, bounds: bool, stack: bool) -> Result<PcurveFit, String> {
2221    let _stack = PcurveStackPointScope::open(stack && matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })));
2222    // Non-sphere refinement repeats expensive global inversions and surface
2223    // probes. Retain successful exact inputs for this immutable fit only.
2224    // The older sphere-global experiment keeps its existing opt-in policy.
2225    let _samples = PcurveSampleScope::open(surface, curve, enabled
2226        || !matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })));
2227    let _bounds = PcurveRejectScope::open(bounds && matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })));
2228    let [t0, t1] = curve.domain()?;
2229    if surface.is_affine()? {
2230        let Some(inversion) = AffineInversion::of(surface)? else {
2231            return Err("build_pcurve_on_surface: singular affine parameterization".into());
2232        };
2233        let pcurve = inversion.image_of(curve)?;
2234        return Ok(PcurveFit {
2235            report: PcurveFitReport {
2236                residual: 0.0,
2237                floor: PCURVE_REFINEMENT_TOLERANCE,
2238                samples: pcurve.control_points.len(),
2239                exit: PcurveFitExit::Converged,
2240                off_surface: 0.0,
2241                raised: false,
2242                clamped_excursion: 0.0,
2243                clamped_distance: 0.0,
2244            },
2245            curve: pcurve,
2246        });
2247    }
2248
2249    let scale = 1.0 + curve.evaluate((t0 + t1) / 2.0)?.length();
2250    let drop_tolerance = 1e-4 * scale;
2251    let endpoint_tolerance = 1e-3 * scale;
2252    let refinement_tolerance = PCURVE_REFINEMENT_TOLERANCE;
2253    let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2254    let invert =
2255        |fraction: f64| invert_checked(surface, section_curve_point(curve, t0 + (t1 - t0) * fraction)?);
2256
2257    let mut parameters = Vec::with_capacity(25);
2258    let mut raw_surface_parameters = Vec::with_capacity(25);
2259    // The edge curve's own distance from the surface at every station inverted,
2260    // accepted or not: the floor below which no pcurve can bring the residual.
2261    let mut off_surface = 0.0_f64;
2262    // The edge's own C0 knots must remain corners of its parameter image.
2263    // Plant those stations before inversion; refinement retains their joins.
2264    let corners = range_breaks(curve, t0, t1, true);
2265    let mut stations: Vec<f64> = (0..=24).map(|index| index as f64 / 24.0).collect();
2266    // Replace nearby uniform seeds, never the native corner itself. Keep
2267    // endpoints and other native corners even when their spans are short.
2268    stations.retain(|station| {
2269        *station == 0.0 || *station == 1.0 || corners.contains(station)
2270            || !corners.iter().any(|corner| (*station - corner).abs() <= SPAN_FLOOR)
2271    });
2272    for &corner in &corners {
2273        let at = stations.partition_point(|value| *value < corner);
2274        if stations.get(at) != Some(&corner) {
2275            stations.insert(at, corner);
2276        }
2277    }
2278    let joins = corners;
2279    for (index, &fraction) in stations.iter().enumerate() {
2280        let (parameter, distance) = invert(fraction)?;
2281        off_surface = off_surface.max(distance);
2282        if distance > drop_tolerance && index != 0 && index != stations.len() - 1 {
2283            continue;
2284        }
2285        if distance > endpoint_tolerance {
2286            if std::env::var("BREP_DEBUG_PCURVE").is_ok() {
2287                let p3 = curve.evaluate(t0 + (t1 - t0) * fraction).ok();
2288                let p0 = curve.evaluate(t0).ok();
2289                let p1 = curve.evaluate(t1).ok();
2290                eprintln!(
2291                    "PCURVE-FAIL idx={index} frac={fraction} dist={distance} endpt_tol={endpoint_tolerance} scale={scale}\n  curve3D@frac={p3:?}\n  curve3D@t0={p0:?} curve3D@t1={p1:?}\n  surf_domain=u[{u0},{u1}] v[{v0},{v1}] invpar={parameter:?}\n  surf@invpar={:?}",
2292                    surface.evaluate(parameter[0], parameter[1]).ok()
2293                );
2294            }
2295            return Err(format!(
2296                "build_pcurve_on_surface: endpoint projection failed (distance={distance})"
2297            ));
2298        }
2299        parameters.push(fraction);
2300        raw_surface_parameters.push(parameter);
2301    }
2302
2303    let (mut pcurve, excursion, distance) =
2304        build_interpolant_joined(surface, &raw_surface_parameters, &parameters, &joins)?;
2305    let refinement = refine_pcurve(
2306        surface,
2307        curve,
2308        [t0, t1],
2309        [u0, u1],
2310        [v0, v1],
2311        refinement_tolerance,
2312        &joins,
2313        &mut parameters,
2314        &mut raw_surface_parameters,
2315        &mut pcurve,
2316        off_surface,
2317        [excursion, distance],
2318        |fraction, _parameter, _on_curve| {
2319            let (surface_parameter, distance) = invert(fraction)?;
2320            Ok((
2321                (distance <= drop_tolerance).then_some(surface_parameter),
2322                distance,
2323            ))
2324        },
2325    )?;
2326    Ok(PcurveFit {
2327        curve: pcurve,
2328        report: PcurveFitReport {
2329            residual: refinement.residual,
2330            floor: refinement_tolerance,
2331            samples: parameters.len(),
2332            exit: refinement.exit,
2333            off_surface: refinement.off_surface,
2334            raised: refinement.raised,
2335            clamped_excursion: refinement.clamped[0],
2336            clamped_distance: refinement.clamped[1],
2337        },
2338    })
2339}
2340
2341/// [`fit_pcurve_on_surface`] for the callers that only need the curve. The
2342/// report is not dropped: it is tallied on the open [`PcurveFitScope`], if any,
2343/// so the operation that owns this fit can say in its diagnostics whether every
2344/// trim reached the floor.
2345pub fn build_pcurve_on_surface(
2346    surface: &NurbsSurface,
2347    curve: &NurbsCurve,
2348) -> Result<NurbsCurve, String> {
2349    let fit = fit_pcurve_on_surface(surface, curve)?;
2350    record_fit(&fit.report);
2351    Ok(fit.curve)
2352}
2353
2354/// Optional section-fit clock; records every early fallback without changing it.
2355struct SectionFitClock {
2356    started: Option<web_time::Instant>,
2357    global: std::time::Duration,
2358    seeded: bool,
2359}
2360impl SectionFitClock {
2361    fn new() -> Self {
2362        Self { started: crate::profile::profile_enabled().then(web_time::Instant::now),
2363            global: std::time::Duration::ZERO, seeded: false }
2364    }
2365}
2366impl Drop for SectionFitClock {
2367    fn drop(&mut self) {
2368        if let Some(started) = self.started {
2369            crate::imprint::profile_emit(format_args!("pcurve.section_time global={:.3} seeded={:.3} result={}",
2370                self.global.as_secs_f64() * 1000.0,
2371                started.elapsed().saturating_sub(self.global).as_secs_f64() * 1000.0,
2372                if self.seeded { "seeded" } else { "global" }));
2373        }
2374    }
2375}
2376
2377/// SECTION-PCURVE SEEDED MARCH (t222: cone × ABC 00000327, non-integral genus).
2378///
2379/// `build_pcurve_on_surface` inverts every sample by GLOBAL closest point. Where
2380/// the carrier surface is COMPRESSED / self-overlapping along the row the
2381/// section rides, the global search aliases interior samples onto a DISTANT
2382/// preimage sheet, folding the pcurve out past the trim boundary and re-crossing
2383/// it. The arrangement then splits the shared section at that phantom crossing,
2384/// while the mate face (whose carrier is not folded there) keeps the section
2385/// whole — so the two operands' fragments disagree and the section strands
2386/// one-use (non-integral genus). Ground truth for t222: 00000327 face 496's
2387/// v≈0.7875 row maps u∈[0.55,0.81] into a ~0.18mm neighbourhood of the section
2388/// endpoint A; the global pcurve for piece 9 folded out to u=0.806 and back,
2389/// re-crossing trim edge 349 at v≈0.784, 0.003 below the corner vertex A.
2390///
2391/// This marches the interior inversions with each seeded from the PREVIOUS
2392/// accepted parameters, so a marched sample
2393/// adopts the nearby branch instead of the momentarily-closest distant sheet.
2394/// The two ENDPOINT samples keep the deterministic global inversion (they are
2395/// the piece's shared junction vertices — same reasoning as
2396/// `repair_branch_jumps`). Additive + fail-soft: the marched chain is used ONLY
2397/// when it CLOSES onto the global far endpoint (its last interior sample is
2398/// parameter-adjacent to it, measured against the chain's own median step);
2399/// otherwise the plain global build is returned byte-for-byte. A single-preimage
2400/// carrier (the cone side of the same section) marches to the same samples the
2401/// global search already had. Use the analytic-aware seeded projector for both
2402/// the march and inserted stations: raw Newton stops at 1e-7 even on an exact
2403/// cylinder, introducing avoidable trim error. General folded carriers retain
2404/// their local seeded Newton path; analytic carriers take their closed form.
2405///
2406/// Escape hatch: `BREP_SECTION_PCURVE_MARCH=0`.
2407pub fn fit_pcurve_on_surface_marched(
2408    surface: &NurbsSurface,
2409    curve: &NurbsCurve,
2410) -> Result<PcurveFit, String> {
2411    fn run(surface: &NurbsSurface, curve: &NurbsCurve, eager: bool) -> Result<PcurveFit, String> {
2412        // The global fallback owns a nested scope; it cannot populate or
2413        // invalidate the marched fit's immutable carrier/curve entries.
2414        let _samples = PcurveSampleScope::open(surface, curve, true);
2415        let mut clock = SectionFitClock::new();
2416        // The global builder owns only scoped sample caches. Its fit/report is
2417        // discarded on a successful seeded route; do that work on fallback only.
2418        // Profile phase/sample lines for the discarded global fit disappear ON.
2419        let mut fallback = || {
2420            let started = clock.started.map(|_| web_time::Instant::now());
2421            let fit = fit_pcurve_on_surface(surface, curve);
2422            if let Some(started) = started { clock.global += started.elapsed(); }
2423            fit
2424        };
2425        let global = if eager { Some(fallback()?) } else { None };
2426        // The global builder's first fallible geometry read validates the
2427        // curve domain. Preserve that error priority before the affine probe
2428        // when the unused global fit is deferred (both inputs may be invalid).
2429        if !eager { curve.domain()?; }
2430        if env_read!("BREP_SECTION_PCURVE_MARCH").as_deref() == Some("0") || surface.is_affine()? {
2431            return global.map_or_else(&mut fallback, Ok);
2432        }
2433        let [t0, t1] = curve.domain()?;
2434        // A closed (ring) section has no distinct endpoints to anchor the march;
2435        // leave it to the existing path (closed rings are handled elsewhere).
2436        if curve.evaluate(t0)?.sub(curve.evaluate(t1)?).length() <= 1e-6 {
2437            return global.map_or_else(&mut fallback, Ok);
2438        }
2439        const SAMPLES: usize = 24;
2440        let fractions: Vec<f64> = (0..=SAMPLES).map(|i| i as f64 / SAMPLES as f64).collect();
2441        let edge: Vec<Vec3> = fractions
2442            .iter()
2443            .map(|fraction| curve.evaluate(t0 + (t1 - t0) * fraction))
2444            .collect::<Result<Vec<_>, _>>()?;
2445        let scale = 1.0 + curve.evaluate((t0 + t1) / 2.0)?.length();
2446        let endpoint_tolerance = 1e-3 * scale;
2447        let (first, first_distance) = invert_checked(surface, edge[0])?;
2448        let (last, last_distance) = invert_checked(surface, edge[SAMPLES])?;
2449        if first_distance > endpoint_tolerance || last_distance > endpoint_tolerance {
2450            return global.map_or_else(&mut fallback, Ok);
2451        }
2452        // The edge curve's distance from the surface at every station this chain
2453        // inverts — on the MARCHED branch, which is the one being fitted.
2454        let mut off_surface = first_distance.max(last_distance);
2455        let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2456        let u_span = (u1 - u0).abs().max(EPSILON);
2457        let v_span = (v1 - v0).abs().max(EPSILON);
2458        let (closed_u, closed_v) = surface_closedness(surface)?;
2459        let norm_step = |a: [f64; 2], b: [f64; 2]| -> f64 {
2460            let mut du = a[0] - b[0];
2461            if closed_u {
2462                while du > 0.5 * u_span {
2463                    du -= u_span;
2464                }
2465                while du < -0.5 * u_span {
2466                    du += u_span;
2467                }
2468            }
2469            let mut dv = a[1] - b[1];
2470            if closed_v {
2471                while dv > 0.5 * v_span {
2472                    dv -= v_span;
2473                }
2474                while dv < -0.5 * v_span {
2475                    dv += v_span;
2476                }
2477            }
2478            ((du / u_span).powi(2) + (dv / v_span).powi(2)).sqrt()
2479        };
2480        // Forward seeded march over the interior samples.
2481        let mut raw = vec![first];
2482        let mut previous = first;
2483        for index in 1..SAMPLES {
2484            let seeded =
2485                crate::projection::project_point_to_surface_from_seed(surface, edge[index], previous)?;
2486            let (_, global_distance) = invert_checked(surface, edge[index])?;
2487            // The seeded footpoint must still sit on the surface — as tight as the
2488            // fit band or the global answer already had it. If it fell off (the
2489            // seed led Newton into a valley), abandon the march and keep global.
2490            if seeded.distance > 4.0 * global_distance + endpoint_tolerance {
2491                return global.map_or_else(&mut fallback, Ok);
2492            }
2493            off_surface = off_surface.max(seeded.distance);
2494            previous = [seeded.u, seeded.v];
2495            raw.push(previous);
2496        }
2497        raw.push(last);
2498        // CLOSURE GATE: the last marched interior sample must be parameter-adjacent
2499        // to the global far endpoint — the march stayed on ONE branch the whole way.
2500        // Measure the endpoint gap against the chain's OWN median step so a genuine
2501        // long edge is not rejected while a sheet-hop (which leaves a big gap to the
2502        // endpoint) is.
2503        let mut steps: Vec<f64> = (1..raw.len())
2504            .map(|i| norm_step(raw[i], raw[i - 1]))
2505            .collect();
2506        let endpoint_gap = steps.pop().unwrap_or(0.0);
2507        steps.sort_by(f64::total_cmp);
2508        let median = steps
2509            .get(steps.len() / 2)
2510            .copied()
2511            .unwrap_or(0.0)
2512            .max(EPSILON);
2513        if endpoint_gap > (4.0 * median).max(0.05) {
2514            return global.map_or_else(&mut fallback, Ok);
2515        }
2516        // Build the interpolant from the marched samples, then refine — re-projecting
2517        // each insert SEEDED from the interpolant (already on the marched branch), so
2518        // a mid-refinement global inversion cannot re-alias onto the far sheet.
2519        let mut parameters = fractions;
2520        let (mut pcurve, excursion, distance) = build_interpolant(surface, &raw, &parameters)?;
2521        let refinement_tolerance = PCURVE_REFINEMENT_TOLERANCE;
2522        // Same classified exits and budget ladder as `fit_pcurve_on_surface`. A
2523        // seeded insert always lands, so this loop cannot stall.
2524        let refinement = refine_pcurve(
2525            surface,
2526            curve,
2527            [t0, t1],
2528            [u0, u1],
2529            [v0, v1],
2530            refinement_tolerance,
2531            &[],
2532            &mut parameters,
2533            &mut raw,
2534            &mut pcurve,
2535            off_surface,
2536            [excursion, distance],
2537            |_fraction, seed, on_curve| {
2538                let seeded = crate::projection::project_point_to_surface_from_seed(surface, on_curve, [seed.x, seed.y])?;
2539                Ok((Some([seeded.u, seeded.v]), seeded.distance))
2540            },
2541        )?;
2542        clock.seeded = true;
2543        Ok(PcurveFit {
2544            curve: pcurve,
2545            report: PcurveFitReport {
2546                residual: refinement.residual,
2547                floor: refinement_tolerance,
2548                samples: parameters.len(),
2549                exit: refinement.exit,
2550                off_surface: refinement.off_surface,
2551                raised: refinement.raised,
2552                clamped_excursion: refinement.clamped[0],
2553                clamped_distance: refinement.clamped[1],
2554            },
2555        })
2556    }
2557
2558    let mode = match std::env::var("BREP_PCURVE_LAZY_GLOBAL") {
2559        Ok(mode) => mode,
2560        Err(std::env::VarError::NotPresent) => "on".to_owned(),
2561        Err(std::env::VarError::NotUnicode(_)) => String::new(),
2562    };
2563    if mode != "check" {
2564        return run(surface, curve, !matches!(mode.as_str(), "1" | "on"));
2565    }
2566    // Clone BEFORE eager evaluation: lazy must start with the same carrier
2567    // cache state, rather than benefiting from eager's recognition/projection.
2568    let lazy_surface = surface.clone();
2569    let lazy_curve = curve.clone();
2570    let eager = run(surface, curve, true);
2571    let lazy = run(&lazy_surface, &lazy_curve, false);
2572    let identical = match (&eager, &lazy) {
2573        (Ok(a), Ok(b)) => {
2574            a.curve.degree == b.curve.degree
2575                && a.curve.knots.len() == b.curve.knots.len()
2576                && a.curve.knots.iter().zip(&b.curve.knots).all(|(a,b)| a.to_bits() == b.to_bits())
2577                && a.curve.control_points.len() == b.curve.control_points.len()
2578                && a.curve.control_points.iter().zip(&b.curve.control_points).all(|(a,b)| {
2579                    [a.x.to_bits(),a.y.to_bits(),a.z.to_bits(),a.w.to_bits()]
2580                        == [b.x.to_bits(),b.y.to_bits(),b.z.to_bits(),b.w.to_bits()]
2581                })
2582                && a.report == b.report
2583                && [a.report.residual, a.report.floor, a.report.off_surface,
2584                    a.report.clamped_excursion, a.report.clamped_distance].map(f64::to_bits)
2585                    == [b.report.residual, b.report.floor, b.report.off_surface,
2586                        b.report.clamped_excursion, b.report.clamped_distance].map(f64::to_bits)
2587        }
2588        (Err(a), Err(b)) => a == b,
2589        _ => false,
2590    };
2591    if let Ok(path) = std::env::var("BREP_PCURVE_LAZY_GLOBAL_CENSUS") {
2592        use std::io::Write;
2593        let mut file = std::fs::OpenOptions::new().create(true).append(true).open(path)
2594            .expect("open lazy-global differential ledger");
2595        writeln!(file, "pcurve.lazy_global identical={identical} eager_ok={} lazy_ok={} degree={} controls={}",
2596            eager.is_ok(), lazy.is_ok(), curve.degree, curve.control_points.len())
2597            .expect("append lazy-global differential ledger");
2598    }
2599    assert!(identical, "lazy global pcurve fallback changed the curve, report or error");
2600    eager
2601}
2602
2603/// [`fit_pcurve_on_surface_marched`] for the callers that only need the curve;
2604/// the report is tallied on the open [`PcurveFitScope`] exactly as
2605/// [`build_pcurve_on_surface`] does.
2606pub fn build_pcurve_on_surface_marched(
2607    surface: &NurbsSurface,
2608    curve: &NurbsCurve,
2609) -> Result<NurbsCurve, String> {
2610    let fit = fit_pcurve_on_surface_marched(surface, curve)?;
2611    record_fit(&fit.report);
2612    Ok(fit.curve)
2613}
2614
2615/// Build a pcurve for a represented subrange of a larger edge curve.
2616///
2617/// On an affine carrier the answer is exact and is taken as such
2618/// (`affine_pcurve_on_range`). Otherwise this samples only the represented
2619/// interval, which is essential when off-interval control points do not lie on
2620/// the target carrier — the exact lane restricts the net by knot insertion
2621/// first, so those control points are removed rather than ignored.
2622pub fn fit_pcurve_on_surface_range(
2623    surface: &NurbsSurface,
2624    curve: &NurbsCurve,
2625    edge_start: f64,
2626    edge_end: f64,
2627    forward: bool,
2628    tolerance: f64,
2629) -> Result<PcurveFit, String> {
2630    if let Some(exact) =
2631        affine_pcurve_on_range(surface, curve, edge_start, edge_end, forward, tolerance)?
2632    {
2633        return Ok(exact);
2634    }
2635    fit_pcurve_on_surface_range_dense(
2636        surface, curve, edge_start, edge_end, forward, tolerance, 64, 3, 513,
2637    )
2638}
2639
2640/// [`fit_pcurve_on_surface_range`] for the callers that only need the curve:
2641/// the fit is ACCEPTED or REFUSED on its bar (`accept_fit`), never returned
2642/// off it.
2643pub fn build_pcurve_on_surface_range(
2644    surface: &NurbsSurface,
2645    curve: &NurbsCurve,
2646    edge_start: f64,
2647    edge_end: f64,
2648    forward: bool,
2649    tolerance: f64,
2650) -> Result<NurbsCurve, String> {
2651    accept_fit(fit_pcurve_on_surface_range(
2652        surface, curve, edge_start, edge_end, forward, tolerance,
2653    )?)
2654}
2655
2656/// `BREP_DEBUG_STATION_FIT`: trace every station fit round by round, and the
2657/// stations around the worst span of a fit off its bar. Read once per process.
2658fn station_fit_tracing() -> bool {
2659    debug_flag!("BREP_DEBUG_STATION_FIT")
2660}
2661
2662/// Narrowest span, as a fraction of the parameter range, that
2663/// [`fit_pcurve_on_surface_stations`] subdivides. `refine_pcurve` floors at
2664/// 1e-3 from 25 base samples; this fitter starts from 64 and quarters, so a
2665/// floor of 1e-3 bound on its first pass and refused 67 of the 57-document
2666/// corpus's bodies (measured 2026-09-26). 1e-6 admits every halving a real
2667/// trim needs and stops the runaway that fits stations 4e-7 apart.
2668const SPAN_FLOOR: f64 = 1e-6;
2669
2670/// Rounds the raised pass of [`fit_pcurve_on_surface_stations`] may spend:
2671/// enough halvings for any span the sample cap can resolve.
2672const RAISED_ROUNDS: usize = 40;
2673
2674/// The refusal every station builder returns for a fit off its bar.
2675pub const PCURVE_OFF_BAR: &str = "pcurve fit refused: the trim misses its stations by";
2676
2677/// The one acceptance decision behind [`build_pcurve_on_surface_range`],
2678/// [`build_pcurve_on_surface_range_dense`] and
2679/// [`build_pcurve_on_surface_stations`]: a fit on its bar
2680/// ([`PcurveFitReport::on_bar`]) is the curve, a fit off it is a refusal that
2681/// names the residual, the bar, what was asked, how far the stations stand off
2682/// the carrier and why refinement stopped.
2683///
2684/// Until 2026-09-26 these builders returned whatever their last round built
2685/// without measuring it (the 2026-09-18 census: 4564 of 54556 imported pcurves
2686/// over the ask they were built to, 2072 of them at a station the refinement
2687/// itself had tested and given up on). Nothing here widens a band: the bar is
2688/// the caller's own ask plus what the input makes unreachable.
2689fn accept_fit(fit: PcurveFit) -> Result<NurbsCurve, String> {
2690    let report = fit.report;
2691    if report.on_bar() {
2692        return Ok(fit.curve);
2693    }
2694    Err(off_bar_message(&report))
2695}
2696
2697fn off_bar_message(report: &PcurveFitReport) -> String {
2698    format!(
2699        "{PCURVE_OFF_BAR} {:.3e} out of sample against a bar of {:.3e} (asked {:.1e}, the \
2700         stations stand {:.3e} off the carrier; {:?} at {} samples{}{})",
2701        report.residual,
2702        report.floor + report.off_surface,
2703        report.floor,
2704        report.off_surface,
2705        report.exit,
2706        report.samples,
2707        if report.raised { ", after the raise" } else { "" },
2708        if report.clamped_excursion > 0.0 {
2709            format!(
2710                "; clamped into the chart by {:.3e} in parameter, {:.3e} in 3D",
2711                report.clamped_excursion, report.clamped_distance
2712            )
2713        } else {
2714            String::new()
2715        },
2716    )
2717}
2718
2719/// The class slug of a pcurve fit refused off its bar
2720/// ([`crate::RefusalClass::NonConvergence`]): minted by
2721/// [`build_pcurve_on_surface_range_classed`] and read by
2722/// [`is_pcurve_off_bar`], so a dispatcher decides on the class, never on the
2723/// message text.
2724pub(crate) const PCURVE_OFF_BAR_WHAT: &str = "pcurve_fit_off_bar";
2725
2726/// Whether `refusal` is a pcurve fit that could not reach its bar.
2727pub(crate) fn is_pcurve_off_bar(refusal: &crate::KernelRefusal) -> bool {
2728    matches!(&refusal.class, crate::RefusalClass::NonConvergence { what } if what == PCURVE_OFF_BAR_WHAT)
2729}
2730
2731/// [`build_pcurve_on_surface_range`] with a typed refusal: a fit off its bar
2732/// is `NonConvergence { what: PCURVE_OFF_BAR_WHAT }` at `stage`, with the same
2733/// message; any other failure of the fit is `Internal` under `what`.
2734pub(crate) fn build_pcurve_on_surface_range_classed(
2735    surface: &NurbsSurface,
2736    curve: &NurbsCurve,
2737    edge_start: f64,
2738    edge_end: f64,
2739    forward: bool,
2740    tolerance: f64,
2741    stage: KernelStage,
2742    what: &'static str,
2743) -> Result<NurbsCurve, crate::KernelRefusal> {
2744    use crate::OrRefuse;
2745    let fit = fit_pcurve_on_surface_range(surface, curve, edge_start, edge_end, forward, tolerance)
2746        .or_refuse(stage, what)?;
2747    accept_fit_classed(fit, stage)
2748}
2749
2750/// [`accept_fit`] with the refusal typed: `NonConvergence { what:
2751/// PCURVE_OFF_BAR_WHAT }` at `stage`, the message unchanged.
2752pub(crate) fn accept_fit_classed(fit: PcurveFit, stage: KernelStage) -> Result<NurbsCurve, crate::KernelRefusal> {
2753    if fit.report.on_bar() {
2754        return Ok(fit.curve);
2755    }
2756    Err(crate::KernelRefusal {
2757        class: crate::RefusalClass::NonConvergence { what: PCURVE_OFF_BAR_WHAT.into() },
2758        stage,
2759        message: off_bar_message(&fit.report),
2760    })
2761}
2762
2763/// The EXACT pcurve for a coedge's subrange of `curve` on an affine carrier,
2764/// or `None` when there is no such answer and the sampled lane must run.
2765///
2766/// [`fit_pcurve_on_surface`] has always mapped a WHOLE curve's control net
2767/// exactly on an affine carrier. A coedge's trim is that same curve restricted
2768/// to `[edge_start, edge_end]` and oriented by `forward`, and both operations
2769/// are exact on a NURBS: [`NurbsCurve::split`] subdivides by knot insertion,
2770/// [`NurbsCurve::reversed`] mirrors the net, and rescaling the knots to
2771/// `[0, 1]` is affine in the edge's own parameter — which is precisely the
2772/// fraction convention the sampled lane uses, so the pcurve's correspondence
2773/// with the edge is the same one either lane produces.
2774///
2775/// Sampling where an exact answer exists leaves a real error: measured
2776/// 2026-09-17, a booleaned band rim's two planar trims sat 2.379e-4 and
2777/// 2.395e-4 off their edges, where this lane lands 1.4e-13 off.
2778///
2779/// The image is verified against the caller's own `tolerance` before it is
2780/// returned. The exact image of a curve that does NOT lie on this carrier is
2781/// its orthogonal projection, which is not that coedge's trim, so every such
2782/// case falls through to the sampled lane and keeps the refusals that lane
2783/// makes today.
2784fn affine_pcurve_on_range(
2785    surface: &NurbsSurface,
2786    curve: &NurbsCurve,
2787    edge_start: f64,
2788    edge_end: f64,
2789    forward: bool,
2790    tolerance: f64,
2791) -> Result<Option<PcurveFit>, String> {
2792    // Opt-out for A/B bisection of this lane against the sampled one, in the
2793    // shape of the two hatches beside it (`BREP_NO_PCURVE_REPAIR`,
2794    // `BREP_SECTION_PCURVE_MARCH`). It is what showed that the boolean's
2795    // planar residuals do NOT come through here: the same binary with this set
2796    // and unset read identically to every digit on 21_band_rim.
2797    if std::env::var("BREP_AFFINE_RANGE_PCURVE").as_deref() == Ok("0") {
2798        return Ok(None);
2799    }
2800    let Some(inversion) = AffineInversion::of(surface)? else {
2801        return Ok(None);
2802    };
2803    if !(edge_start.is_finite() && edge_end.is_finite() && edge_start < edge_end) {
2804        // The sampled lane owns this refusal; it is not this lane's to reword.
2805        return Ok(None);
2806    }
2807    let [t0, t1] = curve.domain()?;
2808    let start = edge_start.max(t0);
2809    let end = edge_end.min(t1);
2810    // A range narrower than the knot identity tolerance cannot be split onto
2811    // its own endpoints at all.
2812    if end - start <= 2.0 * KNOT_IDENTITY_TOL {
2813        return Ok(None);
2814    }
2815    let mut restricted = curve.clone();
2816    if end < t1 - KNOT_IDENTITY_TOL {
2817        restricted = restricted.split(end)?.0;
2818    }
2819    if start > t0 + KNOT_IDENTITY_TOL {
2820        restricted = restricted.split(start)?.1;
2821    }
2822    let mut pcurve = inversion.image_of(&restricted)?;
2823    if !forward {
2824        pcurve = pcurve.reversed()?;
2825    }
2826    let first = pcurve.knots[0];
2827    let last = pcurve.knots[pcurve.knots.len() - 1];
2828    if !(last - first > 0.0) {
2829        return Ok(None);
2830    }
2831    let knots = pcurve
2832        .knots
2833        .iter()
2834        .map(|knot| (knot - first) / (last - first))
2835        .collect::<Vec<_>>();
2836    let pcurve = NurbsCurve::new(pcurve.degree, knots, pcurve.control_points.clone())?;
2837
2838    // Verify against the range the CALLER asked for, not the one the
2839    // restriction produced: `split` snaps onto a nearby knot, so a snap that
2840    // moved the correspondence reads here as a deviation. Sampling at
2841    // fractions that are not the stations any lane interpolates through keeps
2842    // this a check on the whole trim rather than on its endpoints.
2843    let scale = 1.0 + curve.evaluate((start + end) / 2.0)?.length();
2844    let bar = tolerance.max(1e-11 * scale);
2845    let mut residual = 0.0_f64;
2846    for index in 0..=32 {
2847        let fraction = index as f64 / 32.0;
2848        let uv = pcurve.evaluate(fraction)?;
2849        // `evaluate` CLAMPS out-of-domain uv. A planar carrier's domain is a
2850        // bounding rectangle that a booleaned trim can leave, and an affine
2851        // patch's extension is the same plane, so read it unclamped.
2852        let on_carrier = surface.evaluate_extended(uv.x, uv.y)?;
2853        let edge_fraction = if forward { fraction } else { 1.0 - fraction };
2854        let on_edge = curve.evaluate(start + (end - start) * edge_fraction)?;
2855        residual = residual.max(on_carrier.sub(on_edge).length());
2856        if residual > bar {
2857            return Ok(None);
2858        }
2859    }
2860    let samples = pcurve.control_points.len();
2861    Ok(Some(PcurveFit {
2862        curve: pcurve,
2863        report: PcurveFitReport {
2864            residual,
2865            // The floor this lane VERIFIED against: the caller's ask, or the
2866            // floating-point floor of an exact map on a part this size. An
2867            // exact image is on its bar by construction; a caller asking for
2868            // less than the map's own precision is not refused for it.
2869            floor: bar,
2870            samples,
2871            exit: PcurveFitExit::Converged,
2872            off_surface: 0.0,
2873            raised: false,
2874            clamped_excursion: 0.0,
2875            clamped_distance: 0.0,
2876        },
2877    }))
2878}
2879
2880fn align_collapsed_endpoints(surface: &NurbsSurface, raw: &mut [[f64; 2]]) -> Result<(), String> {
2881    let anchor = surface.control_points[0][0].point()?;
2882    let mut extent = 0.0_f64;
2883    for control in surface.control_points.iter().flatten() {
2884        extent = extent.max(control.point()?.sub(anchor).length());
2885    }
2886    // This is a geometric identity check, independent of the fitting allowance
2887    // and of world position. Positive rational weights keep the whole iso-curve
2888    // inside the convex hull of its Euclidean controls. Cap the size coupling
2889    // at the linear tolerance so a large patch cannot erase a thin finite row.
2890    let pole_band = (1e-10 * (1.0 + extent)).min(LINEAR_TOLERANCE);
2891    for (endpoint, neighbor) in [(0, 1), (raw.len() - 1, raw.len() - 2)] {
2892        let point = surface.evaluate(raw[endpoint][0], raw[endpoint][1])?;
2893        for axis in 0..2 {
2894            let mut candidate = raw[endpoint];
2895            candidate[axis] = raw[neighbor][axis];
2896            if candidate == raw[endpoint]
2897                || surface
2898                    .evaluate(candidate[0], candidate[1])?
2899                    .sub(point)
2900                    .length()
2901                    > pole_band
2902            {
2903                continue;
2904            }
2905            let row = if axis == 0 {
2906                surface.iso_curve_v(raw[endpoint][1])?
2907            } else {
2908                surface.iso_curve_u(raw[endpoint][0])?
2909            };
2910            let mut collapsed = true;
2911            for control in &row.control_points {
2912                if control.point()?.sub(point).length() > pole_band {
2913                    collapsed = false;
2914                    break;
2915                }
2916            }
2917            if collapsed {
2918                raw[endpoint] = candidate;
2919            }
2920        }
2921    }
2922    Ok(())
2923}
2924
2925/// Re-seat any raw inversion sample that BRANCH-JUMPED — snapped to a distant
2926/// fold of a self-overlapping general carrier — back onto the branch traced by
2927/// its neighbours.
2928///
2929/// Each entry in `raw` is an INDEPENDENT global closest-point inversion of the
2930/// corresponding 3D edge sample. Every one is geometrically valid (on the
2931/// surface, at the edge), but they need not be CONTIGUOUS: where a rational
2932/// B-spline surface folds back over the small trimmed patch it carries, the
2933/// momentarily-closest fold flips from one sample to the next, so the raw
2934/// polygon zig-zags across the whole domain and self-crosses — and the region
2935/// its interpolant bounds no longer covers the true face (its surface flux can
2936/// exceed its own area). We anchor on the LONGEST run of mutually-continuous
2937/// samples — the fold the trimmed patch actually lies on, since a small face
2938/// lives on ONE fold and the jumped samples are the minority the global search
2939/// snapped elsewhere — then walk outward in both directions, re-seeding Newton
2940/// from the last good parameters and adopting the continuous footpoint whenever
2941/// it is geometrically as valid as the global one. Anchoring on consensus (not
2942/// blindly on sample 0, which can itself be an outlier that would drag the
2943/// whole edge onto the wrong branch and tear the loop open at its endpoint)
2944/// leaves continuous nonsingular fits unchanged. Certified collapsed endpoint
2945/// rows first adopt their neighbour's branch; a bad seed in the subsequent
2946/// jump repair cannot make a sample worse than the global search already had it.
2947fn repair_branch_jumps(
2948    surface: &NurbsSurface,
2949    edge_points: &[Vec3],
2950    raw: &mut [[f64; 2]],
2951    tolerance: f64,
2952) -> Result<(), String> {
2953    if raw.len() < 3 {
2954        return Ok(());
2955    }
2956    // Affine carriers invert linearly and exactly — no folds, nothing to chase.
2957    // Checked first so the common planar/affine face never touches the env.
2958    if surface.is_affine()? {
2959        return Ok(());
2960    }
2961    // Opt-out for A/B bisection of a STEP-import regression against this repair.
2962    if std::env::var("BREP_NO_PCURVE_REPAIR").is_ok() {
2963        return Ok(());
2964    }
2965    // A pole has no unique coordinate along its collapsed row. Continuing the
2966    // adjacent sample's branch is safe only when the ENTIRE row is collapsed;
2967    // coincident points across an ordinary seam or fold are not enough.
2968    align_collapsed_endpoints(surface, raw)?;
2969    let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2970    let u_span = (u1 - u0).abs().max(EPSILON);
2971    let v_span = (v1 - v0).abs().max(EPSILON);
2972    let (closed_u, closed_v) = surface_closedness(surface)?;
2973    // Normalised, seam-aware step between two parameter samples. Wrapping the
2974    // closed directions keeps a legitimate seam crossing SMALL, so the seam /
2975    // periodic-unwrap machinery elsewhere is never disturbed by this repair.
2976    let norm_step = |a: [f64; 2], b: [f64; 2]| -> f64 {
2977        let mut du = a[0] - b[0];
2978        if closed_u {
2979            while du > 0.5 * u_span {
2980                du -= u_span;
2981            }
2982            while du < -0.5 * u_span {
2983                du += u_span;
2984            }
2985        }
2986        let mut dv = a[1] - b[1];
2987        if closed_v {
2988            while dv > 0.5 * v_span {
2989                dv -= v_span;
2990            }
2991            while dv < -0.5 * v_span {
2992                dv += v_span;
2993            }
2994        }
2995        ((du / u_span).powi(2) + (dv / v_span).powi(2)).sqrt()
2996    };
2997    // A jump crosses a large fraction of the WHOLE domain — orders above the
2998    // per-sample motion of any real (even domain-spanning) edge, which advances
2999    // ~1/N of its traversal between consecutive stations.
3000    const JUMP_THRESHOLD: f64 = 0.2;
3001    let count = raw.len();
3002
3003    // Locate the longest maximal run of consecutive continuous samples — the
3004    // branch to anchor on. If nothing jumps, this spans [0, count-1] and both
3005    // re-seat passes below are empty, leaving `raw` untouched.
3006    let (mut best_start, mut best_len, mut run_start) = (0usize, 1usize, 0usize);
3007    for index in 1..count {
3008        if norm_step(raw[index], raw[index - 1]) > JUMP_THRESHOLD {
3009            if index - run_start > best_len {
3010                best_len = index - run_start;
3011                best_start = run_start;
3012            }
3013            run_start = index;
3014        }
3015    }
3016    if count - run_start > best_len {
3017        best_len = count - run_start;
3018        best_start = run_start;
3019    }
3020    let (spine_lo, spine_hi) = (best_start, best_start + best_len - 1);
3021
3022    // Adopt the continuous footpoint only when it (a) still sits on the surface
3023    // — as tight as the fit band or the global answer — and (b) genuinely
3024    // closes the jump rather than trading it for another. Returns the parameter
3025    // to carry forward as the next seed (the repaired one, or the untouched
3026    // global when no repair applies).
3027    let reseat = |edge_point: Vec3,
3028                  previous: [f64; 2],
3029                  global: [f64; 2]|
3030     -> Result<[f64; 2], String> {
3031        let global_step = norm_step(global, previous);
3032        if global_step <= JUMP_THRESHOLD {
3033            return Ok(global);
3034        }
3035        let seeded =
3036            project_point_to_surface_seeded(surface, edge_point, previous[0], previous[1])?;
3037        let candidate = [seeded.u, seeded.v];
3038        let global_residual = surface
3039            .evaluate(global[0], global[1])?
3040            .sub(edge_point)
3041            .length();
3042        let on_surface = seeded.distance <= 4.0 * global_residual + tolerance.max(1e-12);
3043        if on_surface && norm_step(candidate, previous) < 0.5 * global_step {
3044            if std::env::var("BREP_DEBUG_PCURVE").is_ok() {
3045                eprintln!(
3046                    "pcurve repair: jump {global_step:.4} ({global:?}) -> {:.4} ({candidate:?}) res {:.2e}->{:.2e}",
3047                    norm_step(candidate, previous),
3048                    global_residual,
3049                    seeded.distance
3050                );
3051            }
3052            Ok(candidate)
3053        } else {
3054            Ok(global)
3055        }
3056    };
3057
3058    // Walk forward off the spine's high end, then backward off its low end,
3059    // chaining each repaired sample as the next seed so continuity propagates.
3060    //
3061    // Apart from the certified collapsed rows above, the two ENDPOINT samples
3062    // (fraction 0 and 1) are NEVER moved: they are the
3063    // edge's shared loop vertices. The global inversion is deterministic, so the
3064    // two coedges meeting at a vertex land it at the SAME parameters even when
3065    // that vertex sits on a fold reachable from two branches — moving one side
3066    // to a different branch tears the loop open there (`synthesize_pole_edge`
3067    // then rejects the non-collapsed gap). A vertex's genuine fold transition
3068    // (an edge whose interior rides u≈0.08 but whose endpoint must meet its
3069    // neighbour at u≈0.95) is exactly this case and must be preserved, not
3070    // "continuity-repaired" back onto the interior branch.
3071    let mut previous = raw[spine_hi];
3072    for index in (spine_hi + 1)..count.saturating_sub(1) {
3073        raw[index] = reseat(edge_points[index], previous, raw[index])?;
3074        previous = raw[index];
3075    }
3076    let mut previous = raw[spine_lo];
3077    for index in (1..spine_lo).rev() {
3078        raw[index] = reseat(edge_points[index], previous, raw[index])?;
3079        previous = raw[index];
3080    }
3081    Ok(())
3082}
3083
3084/// Range fitter with explicit sampling knobs, reporting what the fit achieved.
3085/// [`fit_pcurve_on_surface_range`] keeps the long-standing (base 64, 3
3086/// refinement rounds, 513 cap) budget; a fit that binds at that cap with the
3087/// bar unmet grows once to `PCURVE_RAISED_SAMPLES`
3088/// ([`fit_pcurve_on_surface_stations`]).
3089///
3090/// NOTE (2026-09-03): this comment used to say "STEP import retries failed fits
3091/// with a denser budget". No caller passes these knobs any more — that retry
3092/// was removed and the sentence outlived it. The knobs are kept because they
3093/// are the honest way to ASK whether a fit had headroom left, which is what
3094/// `examples/pcurve_residual_probe.rs` uses them for: on every ABC corpus
3095/// coedge that failed `validate`'s pcurve check, budgets up to (512, 8, 8193)
3096/// with a 1000x tighter target reproduced the coarse fit's deviation to six
3097/// decimals, because that deviation is the edge-vs-surface closest-point
3098/// residual and a curve ON the surface cannot beat it.
3099#[allow(clippy::too_many_arguments)]
3100pub fn fit_pcurve_on_surface_range_dense(
3101    surface: &NurbsSurface,
3102    curve: &NurbsCurve,
3103    edge_start: f64,
3104    edge_end: f64,
3105    forward: bool,
3106    tolerance: f64,
3107    base_samples: usize,
3108    refinement_rounds: usize,
3109    parameter_cap: usize,
3110) -> Result<PcurveFit, String> {
3111    if !(edge_start.is_finite() && edge_end.is_finite() && edge_start < edge_end) {
3112        return Err("build_pcurve_on_surface_range: invalid edge interval".into());
3113    }
3114    let evaluate_edge = |fraction: f64| {
3115        let edge_fraction = if forward { fraction } else { 1.0 - fraction };
3116        curve.evaluate(edge_start + (edge_end - edge_start) * edge_fraction)
3117    };
3118    let breaks = range_breaks(curve, edge_start, edge_end, forward);
3119    let ask = tolerance.max(PCURVE_REFINEMENT_TOLERANCE);
3120    let fit = fit_station_pcurve(
3121        surface,
3122        &evaluate_edge,
3123        &breaks,
3124        &breaks,
3125        ask,
3126        base_samples,
3127        refinement_rounds,
3128        parameter_cap,
3129        SPAN_FLOOR,
3130    )?;
3131    end_span_challenger(surface, curve, &evaluate_edge, edge_start, edge_end, forward, &breaks, ask, base_samples, refinement_rounds, parameter_cap, fit)
3132}
3133
3134/// The edge curve's OWN distinct interior knots inside `[edge_start,
3135/// edge_end]`, mapped through the trim's range and sense to coedge
3136/// fractions, that fall inside `pcurve`'s FIRST or LAST span (between the
3137/// domain end and its nearest interior knot), sorted.
3138fn native_end_knot_fractions(curve: &NurbsCurve, edge_start: f64, edge_end: f64, forward: bool, pcurve: &NurbsCurve) -> Result<Vec<f64>, String> {
3139    let [q0, q1] = pcurve.domain()?;
3140    let mut interior: Vec<f64> = pcurve.knots.iter().copied().filter(|k| *k > q0 && *k < q1).collect();
3141    interior.dedup();
3142    let (Some(&first), Some(&last)) = (interior.first(), interior.last()) else { return Ok(Vec::new()) };
3143    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3144    let span = edge_end - edge_start;
3145    let mut fractions: Vec<f64> = curve
3146        .knots
3147        .iter()
3148        .copied()
3149        .filter(|k| *k > low && *k < high)
3150        .map(|k| {
3151            let along = (k - edge_start) / span;
3152            if forward { along } else { 1.0 - along }
3153        })
3154        .filter(|f| f.is_finite() && ((*f > q0 && *f < first) || (*f > last && *f < q1)))
3155        .collect();
3156    fractions.sort_by(f64::total_cmp);
3157    fractions.dedup();
3158    Ok(fractions)
3159}
3160
3161/// The admission rule for a foot read against an edge point: finite distance,
3162/// finite point, finite (u, v) inside the native domain. Shared by
3163/// [`common_station_read`] and the station fitter's tracking mode.
3164fn foot_admitted(foot: &crate::SurfaceProjection, [u0, u1]: [f64; 2], [v0, v1]: [f64; 2]) -> bool {
3165    let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
3166    foot.distance.is_finite() && finite(foot.point) && foot.u.is_finite() && foot.v.is_finite() && (u0..=u1).contains(&foot.u) && (v0..=v1).contains(&foot.v)
3167}
3168
3169/// The tracking mode's verification probes: the current pcurve's native probes
3170/// ([`native_probe_fractions`]: endpoints, quarters and 16 interior points of
3171/// each knot span), its EXACT knots (the final common read includes them, and
3172/// the native probes do not), and the caller's fixed fractions; finite, in
3173/// [0, 1], sorted, deduplicated.
3174fn verification_fractions(pcurve: &NurbsCurve, verify: &[f64]) -> Result<Vec<f64>, String> {
3175    let mut fractions = native_probe_fractions(&[pcurve])?;
3176    fractions.extend(pcurve.knots.iter().copied());
3177    fractions.extend(verify.iter().copied());
3178    fractions.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3179    fractions.sort_by(f64::total_cmp);
3180    fractions.dedup();
3181    Ok(fractions)
3182}
3183
3184/// The off-carrier candidate admission, at the same probes and shared feet
3185/// (`[tracking, deviation, excess]` per curve, [`common_station_read_with_excess`]):
3186/// every reading finite, the candidate's tracking strictly lower, and EITHER
3187/// its maximum deviation no worse than the legacy's (the original rule) OR the
3188/// candidate meeting the ORIGINAL floors outright, tracking and excess both
3189/// within `PCURVE_REFINEMENT_TOLERANCE` (1e-7).
3190///
3191/// Why the second branch: for fits whose images follow the shared admitted
3192/// feet, the maximum deviation can be dominated by the edge's standoff.
3193/// Their measured maxima can then differ by rounding while tracking improves.
3194/// This does not assert that the admitted foot is a certified global nearest
3195/// point or that an arbitrary pcurve has the same maximum deviation.
3196/// next5 fixture 25 (BREP_DEBUG_STATION_FIT): every tracking candidate reached
3197/// the floor (9.52e-8 .. 9.94e-8 tracking) and was declined on a deviation
3198/// 1.2e-14 .. 6.7e-13 above the legacy's at 2.1e-5 .. 9.0e-4 standoffs, while
3199/// the legacy kept 5.9e-7 .. 8.5e-5 tracking. A candidate within the original
3200/// floors on both readings is what those controls require; it is not a
3201/// standoff allowance and no bar moves.
3202pub(crate) fn floor_admits(old: [f64; 3], new: [f64; 3]) -> bool {
3203    let floor = PCURVE_REFINEMENT_TOLERANCE;
3204    old.iter().chain(new.iter()).all(|v| v.is_finite())
3205        && new[0] < old[0]
3206        && (new[1] <= old[1] || (new[0] <= floor && new[2] <= floor))
3207}
3208
3209/// The common reader's foot: the NEAREST admitted ([`foot_admitted`]) of the
3210/// global projection, the projection seeded at the reference (legacy) uv and
3211/// the one seeded at the candidate (image) uv, in THAT order, so that between
3212/// admitted feet at equal distance the first in this order is taken
3213/// (`min_by` keeps the first minimum). [`common_station_read`] and the station
3214/// fitter's tracking mode both take their foot here, so an equal-distance tie
3215/// resolves to the same foot in both.
3216fn common_foot(
3217    global: Option<crate::SurfaceProjection>,
3218    reference: Option<crate::SurfaceProjection>,
3219    candidate: Option<crate::SurfaceProjection>,
3220    domain_u: [f64; 2],
3221    domain_v: [f64; 2],
3222) -> Option<crate::SurfaceProjection> {
3223    [global, reference, candidate]
3224        .into_iter()
3225        .flatten()
3226        .filter(|f| foot_admitted(f, domain_u, domain_v))
3227        .min_by(|a, b| a.distance.total_cmp(&b.distance))
3228}
3229
3230/// The probes a RANGE trim is read at by the common reader: `curves`'
3231/// native spans (endpoints, quarters and 16 interior points of each knot
3232/// span) and exact knots, plus the edge curve's own knots CLIPPED to
3233/// `[t0, t1]` (with the range ends) and the same 19 points on every clipped
3234/// span, mapped through the coedge's sense to fractions; finite, in [0, 1],
3235/// sorted, deduplicated.
3236pub(crate) fn range_use_probes(curves: &[&NurbsCurve], edge_curve: &NurbsCurve, t0: f64, t1: f64, forward: bool) -> Result<Vec<f64>, String> {
3237    let mut probes = native_probe_fractions(curves)?;
3238    for curve in curves {
3239        probes.extend(curve.knots.iter().copied());
3240    }
3241    let span = t1 - t0;
3242    if span.is_finite() && span != 0.0 {
3243        let (low, high) = (t0.min(t1), t0.max(t1));
3244        let mut knots: Vec<f64> = edge_curve.knots.iter().copied().filter(|k| *k >= low && *k <= high).collect();
3245        knots.push(low);
3246        knots.push(high);
3247        knots.sort_by(f64::total_cmp);
3248        knots.dedup();
3249        let locals: Vec<f64> = [0.25, 0.5, 0.75]
3250            .into_iter()
3251            .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
3252            .collect();
3253        let mut ts = knots.clone();
3254        for pair in knots.windows(2).filter(|w| w[1] > w[0]) {
3255            for &local in &locals {
3256                ts.push(pair[0] + (pair[1] - pair[0]) * local);
3257            }
3258        }
3259        for t in ts {
3260            let along = (t - t0) / span;
3261            probes.push(if forward { along } else { 1.0 - along });
3262        }
3263    }
3264    probes.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3265    probes.sort_by(f64::total_cmp);
3266    probes.dedup();
3267    Ok(probes)
3268}
3269
3270/// [`common_station_read`] for two RANGE trims of one coedge (`old`, `new`,
3271/// both on the coedge fraction domain [0, 1]) against the edge curve over
3272/// `[t0, t1]` in the coedge's sense, at [`range_use_probes`] of both: the same
3273/// probes and one shared admitted foot per probe, finite or an error. A trim
3274/// not on [0, 1] is an error.
3275// Unused by the import lane since the tracking trigger and keep were withdrawn
3276// for this merge; kept, with its controls, for their re-proposal.
3277#[cfg_attr(not(test), allow(dead_code))]
3278pub(crate) fn range_common_read(
3279    surface: &NurbsSurface,
3280    edge_curve: &NurbsCurve,
3281    t0: f64,
3282    t1: f64,
3283    forward: bool,
3284    old: &NurbsCurve,
3285    new: &NurbsCurve,
3286) -> Result<((f64, f64), (f64, f64)), String> {
3287    let (o, n) = range_common_read_with_excess(surface, edge_curve, t0, t1, forward, old, new)?;
3288    Ok(((o[0], o[1]), (n[0], n[1])))
3289}
3290
3291/// [`range_common_read`] with each trim's maximum pointwise excess over the
3292/// shared admitted foot's own distance: `[tracking, deviation, excess]` per
3293/// trim ([`common_station_read_with_excess`]).
3294// Unused by the import lane since the tracking trigger and keep were withdrawn
3295// for this merge; kept, with its controls, for their re-proposal.
3296#[cfg_attr(not(test), allow(dead_code))]
3297pub(crate) fn range_common_read_with_excess(
3298    surface: &NurbsSurface,
3299    edge_curve: &NurbsCurve,
3300    t0: f64,
3301    t1: f64,
3302    forward: bool,
3303    old: &NurbsCurve,
3304    new: &NurbsCurve,
3305) -> Result<([f64; 3], [f64; 3]), String> {
3306    for curve in [old, new] {
3307        if !matches!(curve.domain(), Ok([a, b]) if a == 0.0 && b == 1.0) {
3308            return Err("range common read: a trim not on [0, 1]".into());
3309        }
3310    }
3311    let probes = range_use_probes(&[old, new], edge_curve, t0, t1, forward)?;
3312    let evaluate = |fraction: f64| -> Result<Vec3, String> {
3313        let along = if forward { fraction } else { 1.0 - fraction };
3314        edge_curve.evaluate(t0 + (t1 - t0) * along)
3315    };
3316    common_station_read_with_excess(surface, &evaluate, old, new, &probes)
3317}
3318
3319/// The legacy and candidate pcurves read against the edge at the SAME probes
3320/// and against the SAME foot per probe: at each fraction, the edge point's
3321/// foot is the NEAREST admitted one among the global projection and the
3322/// projections seeded at the legacy and the candidate image's (u, v). A foot
3323/// is admitted with a finite distance and point and a finite (u, v) inside the
3324/// native domain. Both images are then measured against that one shared foot
3325/// (TRACKING) and against the edge point (same-parameter DEVIATION). The
3326/// shared foot is the nearest of these three, not a certified global nearest.
3327/// Any non-finite image, point or distance, or a probe with no admitted foot,
3328/// is an error (the caller keeps the legacy fit). Returns
3329/// ((legacy tracking, legacy deviation), (candidate tracking, candidate
3330/// deviation)), maxima over the probes.
3331pub(crate) fn common_station_read(
3332    surface: &NurbsSurface,
3333    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3334    legacy: &NurbsCurve,
3335    candidate: &NurbsCurve,
3336    probes: &[f64],
3337) -> Result<((f64, f64), (f64, f64)), String> {
3338    let (old, new) = common_station_read_with_excess(surface, evaluate_edge, legacy, candidate, probes)?;
3339    Ok(((old[0], old[1]), (new[0], new[1])))
3340}
3341
3342/// [`common_station_read`] that also returns, per curve, the maximum
3343/// pointwise EXCESS: the same-parameter deviation minus the shared admitted
3344/// foot's own distance at that probe (the part over the edge's standoff
3345/// there, which the every-use controls bar at the original 1e-7). Returns
3346/// `[tracking, deviation, excess]` for the legacy and the candidate.
3347pub(crate) fn common_station_read_with_excess(
3348    surface: &NurbsSurface,
3349    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3350    legacy: &NurbsCurve,
3351    candidate: &NurbsCurve,
3352    probes: &[f64],
3353) -> Result<([f64; 3], [f64; 3]), String> {
3354    let (domain_u, domain_v) = surface_domains(surface)?;
3355    let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
3356    // [tracking, deviation, excess] per curve; the excess (deviation minus
3357    // the shared foot's distance, per probe) starts at -inf, so a read with no
3358    // probe is not finite and admits nothing.
3359    let mut read = ([0.0_f64, 0.0, f64::NEG_INFINITY], [0.0_f64, 0.0, f64::NEG_INFINITY]);
3360    // Reading ONE curve against itself (`legacy` and `candidate` the same
3361    // object, as a tracking read and a trigger's read are): the candidate's
3362    // parameter, image and seeded projection are the reference's on identical
3363    // inputs, so each is computed once (same results, same tie order).
3364    let same = std::ptr::eq(legacy, candidate);
3365    // On an affine-sphere carrier with no analytic kind, the global projector
3366    // and the seeded one both return the ellipsoid's closed form whenever it
3367    // answers (`projection::project_point_to_surface` and
3368    // `project_point_to_surface_seeded`), whatever the seed: one closed form
3369    // stands for all three feet (2026-11-03: two thirds of the
3370    // elephant's tracking projections).
3371    let ellipsoid = if same && surface.analytic().is_none() { surface.affine_sphere() } else { None };
3372    for &fraction in probes {
3373        let point = evaluate_edge(fraction)?;
3374        let old_uv = legacy.evaluate(fraction)?;
3375        let new_uv = if same { old_uv } else { candidate.evaluate(fraction)? };
3376        let old_image = surface.evaluate_extended(old_uv.x, old_uv.y)?;
3377        let new_image = if same { old_image } else { surface.evaluate_extended(new_uv.x, new_uv.y)? };
3378        if !(finite(point) && finite(old_image) && finite(new_image)) {
3379            return Err(format!("common station read: non-finite point at fraction {fraction}"));
3380        }
3381        let closed_form = ellipsoid.and_then(|ellipsoid| ellipsoid.project(surface, point));
3382        let foot = if let Some(foot) = closed_form {
3383            common_foot(Some(foot), Some(foot), Some(foot), domain_u, domain_v)
3384        } else {
3385            let reference_foot = memo_seeded_foot(surface, point, old_uv.x, old_uv.y);
3386            let candidate_foot = if same {
3387                reference_foot
3388            } else {
3389                memo_seeded_foot(surface, point, new_uv.x, new_uv.y)
3390            };
3391            common_foot(
3392                memo_global_foot(surface, point),
3393                reference_foot,
3394                candidate_foot,
3395                domain_u,
3396                domain_v,
3397            )
3398        }
3399        .ok_or_else(|| format!("common station read: no admitted foot at fraction {fraction}"))?;
3400        let values = [
3401            old_image.sub(foot.point).length(),
3402            old_image.sub(point).length(),
3403            new_image.sub(foot.point).length(),
3404            new_image.sub(point).length(),
3405        ];
3406        if values.iter().any(|v| !v.is_finite()) {
3407            return Err(format!("common station read: non-finite distance at fraction {fraction}"));
3408        }
3409        if !foot.distance.is_finite() {
3410            return Err(format!("common station read: non-finite foot distance at fraction {fraction}"));
3411        }
3412        read.0[0] = read.0[0].max(values[0]);
3413        read.0[1] = read.0[1].max(values[1]);
3414        read.0[2] = read.0[2].max(values[1] - foot.distance);
3415        read.1[0] = read.1[0].max(values[2]);
3416        read.1[1] = read.1[1].max(values[3]);
3417        read.1[2] = read.1[2].max(values[3] - foot.distance);
3418    }
3419    Ok(read)
3420}
3421
3422/// The interior probe fractions of the edge curve's own FIRST and LAST native
3423/// knot spans inside `[edge_start, edge_end]` (quarter points and 16 interior
3424/// points of each), mapped through the trim's range and sense to coedge
3425/// fractions in [0, 1].
3426fn edge_end_span_fractions(curve: &NurbsCurve, edge_start: f64, edge_end: f64, forward: bool) -> Vec<f64> {
3427    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3428    let mut knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k > low && *k < high).collect();
3429    knots.dedup();
3430    let spans = match (knots.first(), knots.last()) {
3431        (Some(&first), Some(&last)) => vec![(low, first), (last, high)],
3432        _ => vec![(low, high)],
3433    };
3434    let span = edge_end - edge_start;
3435    let mut out = Vec::new();
3436    for (a, b) in spans {
3437        if !(b > a) {
3438            continue;
3439        }
3440        for local in [0.25, 0.5, 0.75].into_iter().chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64)) {
3441            let along = (a + (b - a) * local - edge_start) / span;
3442            let fraction = if forward { along } else { 1.0 - along };
3443            if fraction.is_finite() && (0.0..=1.0).contains(&fraction) {
3444                out.push(fraction);
3445            }
3446        }
3447    }
3448    out.sort_by(f64::total_cmp);
3449    out.dedup();
3450    out
3451}
3452
3453/// At most this many of the legacy pcurve's worst spans are seeded.
3454const WORST_SPANS: usize = 4;
3455/// Interior stations seeded in each of them.
3456const WORST_SPAN_SEEDS: usize = 7;
3457
3458/// The seed fractions of [`end_span_challenger`]'s worst-span source: the
3459/// legacy pcurve's own spans (between its distinct knots) whose same-parameter
3460/// deviation, read at the quarter points and 16 interior points, and at any of
3461/// `extra_probes` (the edge's own end-span interior points mapped to coedge
3462/// fractions) that fall inside the span, exceeds
3463/// `bar`, worst first, at most [`WORST_SPANS`] of them, each seeded with
3464/// [`WORST_SPAN_SEEDS`] evenly spaced interior fractions. Fails closed on any
3465/// non-finite reading.
3466fn legacy_worst_span_seeds(
3467    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3468    surface: &NurbsSurface,
3469    pcurve: &NurbsCurve,
3470    bar: f64,
3471    extra_probes: &[f64],
3472) -> Result<Vec<f64>, String> {
3473    let [q0, q1] = pcurve.domain()?;
3474    let mut knots: Vec<f64> = pcurve.knots.iter().copied().filter(|k| *k >= q0 && *k <= q1).collect();
3475    knots.dedup();
3476    let locals: Vec<f64> = [0.25, 0.5, 0.75]
3477        .into_iter()
3478        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
3479        .collect();
3480    let mut over: Vec<(f64, f64, f64)> = Vec::new();
3481    for span in knots.windows(2).filter(|w| w[1] > w[0]) {
3482        let mut worst = 0.0_f64;
3483        let inside = extra_probes.iter().copied().filter(|f| *f > span[0] && *f < span[1]);
3484        for fraction in locals.iter().map(|local| span[0] + (span[1] - span[0]) * local).chain(inside) {
3485            let uv = pcurve.evaluate(fraction)?;
3486            let deviation = surface.evaluate_extended(uv.x, uv.y)?.sub(evaluate_edge(fraction)?).length();
3487            if !deviation.is_finite() {
3488                return Err(format!("worst-span read: non-finite deviation at fraction {fraction}"));
3489            }
3490            worst = worst.max(deviation);
3491        }
3492        if worst > bar {
3493            over.push((worst, span[0], span[1]));
3494        }
3495    }
3496    over.sort_by(|a, b| b.0.total_cmp(&a.0).then(a.1.total_cmp(&b.1)));
3497    over.truncate(WORST_SPANS);
3498    Ok(over
3499        .into_iter()
3500        .flat_map(|(_, lo, hi)| (1..=WORST_SPAN_SEEDS).map(move |index| lo + (hi - lo) * index as f64 / (WORST_SPAN_SEEDS + 1) as f64))
3501        .collect())
3502}
3503
3504/// Why the range lane's [`end_span_challenger`] runs.
3505#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3506enum ChallengerTrigger {
3507    /// The legacy residual misses `ask + standoff` (the original trigger).
3508    Deviation,
3509    /// The legacy residual is within `ask + standoff`, the edge stands off its
3510    /// carrier by more than the ask, and the legacy fit's COMMON tracking
3511    /// (`common_station_read` at the fixed probes) misses the ask.
3512    Tracking,
3513}
3514
3515/// The challenger's trigger. The original rule reads the same-parameter
3516/// DEVIATION against `ask + standoff`; over a standoff `g` a tangential slip
3517/// `d` adds only about d²/(2g) to it, so a slip up to sqrt(ask² + 2·ask·g)
3518/// never triggers (about 1.3e-5 at g = 9e-4, the fixture-25 inherited edges).
3519/// When the deviation rule does not fire and the edge stands off its carrier
3520/// by more than the ask (the same gate `refine_pcurve` takes its
3521/// standoff-tracking lane on), the legacy fit's common tracking is read
3522/// (`tracking`, called only then): over the ask, the challenger runs on
3523/// tracking. An unread tracking (None or non-finite) never triggers.
3524fn challenger_trigger(residual: f64, off_surface: f64, ask: f64, tracking: impl FnOnce() -> Option<f64>) -> Option<ChallengerTrigger> {
3525    if residual > ask + off_surface {
3526        return Some(ChallengerTrigger::Deviation);
3527    }
3528    if !(off_surface > ask) {
3529        return None;
3530    }
3531    match tracking() {
3532        Some(value) if value.is_finite() && value > ask => Some(ChallengerTrigger::Tracking),
3533        _ => None,
3534    }
3535}
3536
3537/// The END-SPAN CHALLENGER of the range lane (2026-10-05, the four original
3538/// fitter rows of `abc_00000011/12` edges 7 and 243). On e90c30c94 their worst
3539/// excess (4.58e-6 and 5.14e-6) sat in the installed pcurve's LAST span, at the
3540/// edge's start, where the edge curve's own first knot span is only 4.5e-6
3541/// (e7) and 1.2e-4 (e243) wide while the fitter's end span was 1.4e-4 wide at
3542/// its cap. It runs when [`challenger_trigger`] fires: the legacy fit misses
3543/// its bar (residual over the ask plus its standoff), or, on an edge standing
3544/// off its carrier by more than the ask, its common tracking misses the ask.
3545/// It refits with the edge's own interior knots that
3546/// fall inside the legacy pcurve's first or last span as additional stations
3547/// (not joins; corners stay the legacy ones), through the same fitter with the
3548/// unchanged ask, SPAN_FLOOR, cap and rounds. The candidate replaces the legacy
3549/// fit only when both, read at COMMON probes (both pcurves' own knot spans,
3550/// knots and endpoints, plus the edge's own knots and knot spans mapped to
3551/// fractions) against one SHARED foot per probe ([`common_station_read`]),
3552/// read finite, the candidate's tracking is strictly lower and its
3553/// same-parameter deviation no worse. Otherwise, or on any error or unreadable read, the legacy fit
3554/// stands exactly.
3555#[allow(clippy::too_many_arguments)]
3556fn end_span_challenger(
3557    surface: &NurbsSurface,
3558    curve: &NurbsCurve,
3559    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3560    edge_start: f64,
3561    edge_end: f64,
3562    forward: bool,
3563    breaks: &[f64],
3564    ask: f64,
3565    base_samples: usize,
3566    refinement_rounds: usize,
3567    parameter_cap: usize,
3568    legacy: PcurveFit,
3569) -> Result<PcurveFit, String> {
3570    // On the bar by deviation: nothing is read (the original zero-work
3571    // path). The TRACKING trigger (538dd700c: an off-carrier edge on its
3572    // deviation bar challenged on its common tracking) is withdrawn from this
3573    // merge (Claude master's ruling, 2026-10-05): bisected as the first commit
3574    // that moved step_import's a_trim_off_its_bar_is_accepted_and_named, and
3575    // the four original fitter rows do not need it (they enter on the
3576    // deviation trigger).
3577    if !(legacy.report.residual > ask + legacy.report.off_surface) {
3578        return Ok(legacy);
3579    }
3580    // The trigger read, the candidate's tracking verification and the final
3581    // read project the same edge points again: memoized, same answers.
3582    let _feet = FootMemoScope::open(surface);
3583    let Ok(end_knots) = native_end_knot_fractions(curve, edge_start, edge_end, forward, &legacy.curve) else { return Ok(legacy) };
3584    // The legacy fit's own WORST native spans (2026-10-05, root's boundary
3585    // audit of the four rows): the e90 witnesses read a 4.58e-6 / 5.14e-6
3586    // pointwise excess at q 0.99996 inside the closed native domain, in the
3587    // legacy pcurve's last span, where no edge knot falls. Each span between the
3588    // legacy pcurve's own distinct knots is read at its 19 probes; the spans
3589    // whose same-parameter deviation exceeds the ask plus the legacy standoff,
3590    // worst first and at most WORST_SPANS of them, each get WORST_SPAN_SEEDS
3591    // evenly spaced interior stations. Unreadable reads decline.
3592    // The edge's OWN first and last native knot spans, read at their quarter
3593    // points and 16 interior points, mapped through the trim's range and sense
3594    // to coedge fractions (e7's first edge span [0, 4.496e-6] of a
3595    // 0.018661-long trim maps reversed to q in [0.99976, 1], overlapping the
3596    // legacy pcurve's last span [0.99986, 1]).
3597    let edge_end_probes = edge_end_span_fractions(curve, edge_start, edge_end, forward);
3598    // The FIXED part of the common probe set, known before the candidate is
3599    // fitted: the legacy pcurve's own spans, endpoints and knots, and the
3600    // edge's own end-span probes, knot-span quarters and knots (every probe
3601    // that could have TRIGGERED the challenger among them). The candidate fit
3602    // verifies against these as well as its own spans, so it stops on the
3603    // reader that judges it.
3604    let Ok(mut fixed) = native_probe_fractions(&[&legacy.curve]) else { return Ok(legacy) };
3605    fixed.extend(edge_end_probes.iter().copied());
3606    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3607    let mut edge_knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k >= low && *k <= high).collect();
3608    edge_knots.push(low);
3609    edge_knots.push(high);
3610    edge_knots.sort_by(f64::total_cmp);
3611    edge_knots.dedup();
3612    let to_fraction = |t: f64| {
3613        let along = (t - edge_start) / (edge_end - edge_start);
3614        if forward { along } else { 1.0 - along }
3615    };
3616    for span in edge_knots.windows(2).filter(|w| w[1] > w[0]) {
3617        for local in [0.25, 0.5, 0.75] {
3618            fixed.push(to_fraction(span[0] + (span[1] - span[0]) * local));
3619        }
3620    }
3621    fixed.extend(edge_knots.iter().map(|&t| to_fraction(t)));
3622    fixed.extend(end_knots.iter().copied());
3623    fixed.extend(legacy.curve.knots.iter().copied());
3624    fixed.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3625    fixed.sort_by(f64::total_cmp);
3626    fixed.dedup();
3627    let trigger = challenger_trigger(legacy.report.residual, legacy.report.off_surface, ask, || {
3628        common_station_read(surface, evaluate_edge, &legacy.curve, &legacy.curve, &fixed).ok().map(|((tracking, _), _)| tracking)
3629    });
3630    let Some(trigger) = trigger else { return Ok(legacy) };
3631    let Ok(worst_seeds) = legacy_worst_span_seeds(evaluate_edge, surface, &legacy.curve, ask + legacy.report.off_surface, &edge_end_probes) else { return Ok(legacy) };
3632    // The original guard holds for the deviation trigger only: a tracking
3633    // trigger needs no added station (the tracking mode and its verification
3634    // read the fixed probes).
3635    if trigger == ChallengerTrigger::Deviation && end_knots.is_empty() && worst_seeds.is_empty() {
3636        return Ok(legacy);
3637    }
3638    let mut stations: Vec<f64> = breaks.iter().copied().chain(end_knots.iter().copied()).chain(worst_seeds.iter().copied()).collect();
3639    stations.sort_by(f64::total_cmp);
3640    stations.dedup();
3641    // The fitter's cap is max(requested cap, initial station count): the added
3642    // stations must not raise it. Decline when the merged initial count
3643    // (base stations plus every break and end knot) could exceed the
3644    // requested cap.
3645    let initial = base_samples.max(1).checked_add(1).and_then(|count| count.checked_add(stations.len()));
3646    if initial.is_none_or(|count| count > parameter_cap) {
3647        return Ok(legacy);
3648    }
3649    let Ok(candidate) = fit_station_pcurve_mode(surface, evaluate_edge, &stations, breaks, ask, base_samples, refinement_rounds, parameter_cap, SPAN_FLOOR, true, Some(&legacy.curve), &fixed) else {
3650        return Ok(legacy);
3651    };
3652    if !(candidate.report.residual.is_finite() && candidate.report.off_surface.is_finite() && candidate.report.clamped_excursion.is_finite() && candidate.report.clamped_distance.is_finite()) {
3653        return Ok(legacy);
3654    }
3655    // Common probes: the fixed set plus the candidate's own knot spans,
3656    // endpoints and knots (the same set as both curves' native probes plus
3657    // the edge's, as before).
3658    let Ok(mut probes) = native_probe_fractions(&[&candidate.curve]) else { return Ok(legacy) };
3659    probes.extend(fixed.iter().copied());
3660    probes.extend(candidate.curve.knots.iter().copied());
3661    probes.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3662    probes.sort_by(f64::total_cmp);
3663    probes.dedup();
3664    let readings = common_station_read_with_excess(surface, evaluate_edge, &legacy.curve, &candidate.curve, &probes);
3665    let accepted = matches!(&readings, Ok((old, new)) if floor_admits(*old, *new));
3666    if station_fit_tracing() {
3667        eprintln!(
3668            "STATION-FIT end-span challenger: trigger={trigger:?} end_knots={} worst_span_seeds={} edge_end_probes={} legacy={:?}/{:e} candidate={:?}/{:e} common={readings:?} decision={}",
3669            end_knots.len(), worst_seeds.len(), edge_end_probes.len(), legacy.report.exit, legacy.report.residual, candidate.report.exit, candidate.report.residual,
3670            if accepted { "candidate" } else { "legacy" }
3671        );
3672    }
3673    Ok(if accepted { candidate } else { legacy })
3674}
3675
3676
3677/// [`fit_pcurve_on_surface_range_dense`] for the callers that only need the
3678/// curve, accepted or refused on its bar (`accept_fit`).
3679#[allow(clippy::too_many_arguments)]
3680pub fn build_pcurve_on_surface_range_dense(
3681    surface: &NurbsSurface,
3682    curve: &NurbsCurve,
3683    edge_start: f64,
3684    edge_end: f64,
3685    forward: bool,
3686    tolerance: f64,
3687    base_samples: usize,
3688    refinement_rounds: usize,
3689    parameter_cap: usize,
3690) -> Result<NurbsCurve, String> {
3691    accept_fit(fit_pcurve_on_surface_range_dense(
3692        surface,
3693        curve,
3694        edge_start,
3695        edge_end,
3696        forward,
3697        tolerance,
3698        base_samples,
3699        refinement_rounds,
3700        parameter_cap,
3701    )?)
3702}
3703
3704/// The fractions of `[edge_start, edge_end]`, walked in the coedge's sense, at
3705/// which `curve` is not C2: interior knots of multiplicity at least its
3706/// degree. A rational-quadratic arc past a quarter turn is two segments joined
3707/// at a double knot, and an interpolant through uniform samples across that
3708/// joint cannot represent the second-derivative jump: on the 2026-09-18 import
3709/// census 1511 of the 2979 arc trims blamed on the fitter had their worst
3710/// miss at fraction 0.49–0.51, the mid double knot, exactly as the fillet's
3711/// corner patch had measured (`blend/track_fit.rs::curve_breaks`, which this
3712/// mirrors for a range).
3713pub(crate) fn range_breaks(
3714    curve: &NurbsCurve,
3715    edge_start: f64,
3716    edge_end: f64,
3717    forward: bool,
3718) -> Vec<f64> {
3719    let mut fractions = Vec::new();
3720    let span = edge_end - edge_start;
3721    if !(span.abs() > 0.0) {
3722        return fractions;
3723    }
3724    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3725    let mut index = 0;
3726    while index < curve.knots.len() {
3727        let value = curve.knots[index];
3728        let run = curve.knots[index..]
3729            .iter()
3730            .take_while(|knot| **knot == value)
3731            .count();
3732        if value > low && value < high && run >= curve.degree.max(1) {
3733            let along = (value - edge_start) / span;
3734            fractions.push(if forward { along } else { 1.0 - along });
3735        }
3736        index += run;
3737    }
3738    fractions.sort_by(f64::total_cmp);
3739    fractions
3740}
3741
3742/// The body of [`fit_pcurve_on_surface_range_dense`], parameterized by the
3743/// 3D station the pcurve must pass through at each coedge fraction instead of
3744/// by an edge curve and a range.
3745///
3746/// The station supplier is the whole difference between deriving a pcurve and
3747/// reading one. `fit_pcurve_on_surface_range_dense` supplies points off the
3748/// edge's own 3D curve, so the answer is "the nearest point of the carrier",
3749/// which is ambiguous exactly where a trim is interesting — a seam branch, a
3750/// near-tangential approach, a pole. The STEP importer's supplied-pcurve lane
3751/// supplies points off the VENDOR's stated trim instead, and the ambiguity is
3752/// gone because the vendor resolved it.
3753///
3754/// `stations(fraction)` must be continuous in `fraction` over `[0, 1]` and land
3755/// on (or very near) `surface`; `breaks` are the fractions at which it is not
3756/// C2 (`range_breaks`), each of which becomes a station so no kink sits
3757/// between two nodes. Everything else — inversion, branch repair, refinement
3758/// and the measurement — is shared with the derived lane by construction.
3759///
3760/// The SURFACE's knot-line crossings are deliberately not stations here,
3761/// although `blend/track_fit.rs` makes them so. Measured 2026-09-26 over the
3762/// 57-document import corpus: with each crossing bisected on the fraction and
3763/// projected seeded from the left station, 34 bodies refused (19 with a foot
3764/// that misses its global distance rejected) against 15 without the pass —
3765/// every extra refusal a fit stalled around a crossing station, on
3766/// `AssemblyExample-Assembly` and `abc_00000014` among others. The raised
3767/// pass resolves the O(h²) tail across a crossing on its own.
3768///
3769/// # What the fit is measured against, and when it stops
3770///
3771/// The stations' own standoff from the carrier is read FIRST, from the base
3772/// inversions, and the refinement target is the ask plus that standoff
3773/// ([`PcurveFitReport::on_bar`]): a station standing `g` off the surface
3774/// cannot be imaged closer than `g`, so chasing it to the ask alone spends the
3775/// whole budget for nothing (the 2026-09-18 census: 2052 imported pcurves at
3776/// the 513 cap, 1958 of them on a curve that is not on its carrier).
3777///
3778/// Every probe and the final measurement read the carrier through
3779/// `evaluate_extended`: a pcurve riding a periodic seam legitimately carries
3780/// parameters past the domain, and the clamped `evaluate` this loop used until
3781/// 2026-09-26 read every such station as a gross miss — an insert per round
3782/// until the cap, on a trim that was right.
3783///
3784/// The RETURNED curve is measured out of sample — at the quarter points of
3785/// every span between its nodes, where an interpolant is exact at the nodes
3786/// and extremal between — unless its last round probed every span and found
3787/// nothing to insert, in which case that round's maximum already is that
3788/// measurement. A fit that binds at `parameter_cap` or spends its rounds with
3789/// the bar still unmet grows ONCE to `PCURVE_RAISED_SAMPLES` (deterministic).
3790/// The report says which exit it took and what it reached; the `build_*`
3791/// wrappers refuse over the bar, this function never does.
3792#[allow(clippy::too_many_arguments)]
3793pub fn fit_pcurve_on_surface_stations(
3794    surface: &NurbsSurface,
3795    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3796    breaks: &[f64],
3797    tolerance: f64,
3798    base_samples: usize,
3799    refinement_rounds: usize,
3800    parameter_cap: usize,
3801) -> Result<PcurveFit, String> {
3802    fit_station_pcurve(
3803        surface, stations, breaks, &[], tolerance.max(PCURVE_REFINEMENT_TOLERANCE),
3804        base_samples, refinement_rounds, parameter_cap, SPAN_FLOOR,
3805    )
3806}
3807
3808/// Precision construction for stations on recognized analytic carriers. Unlike
3809/// general projection, their inverse maps reach floating point accuracy. This
3810/// is an explicit construction contract, not a change to general fit policy.
3811pub(crate) fn analytic_station_pcurve(
3812    surface: &NurbsSurface,
3813    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3814    tolerance: f64,
3815) -> Result<NurbsCurve, String> {
3816    if surface.analytic().is_none() {
3817        return Err("analytic pcurve requires an analytic carrier".into());
3818    }
3819    let mut breaks = Vec::new();
3820    for _ in 0..4 {
3821        let fit = fit_station_pcurve(surface, stations, &breaks, &[], tolerance, 64, 64, 8192, 1e-10)?;
3822        if fit.report.residual > tolerance || fit.report.off_surface > tolerance {
3823            return Err(format!(
3824                "analytic pcurve construction missed its contract: {:?}",
3825                fit.report
3826            ));
3827        }
3828        let mut failed = Vec::new();
3829        // Independent Gauss stations in every returned knot span, rather than
3830        // re-reading the interpolation nodes or the fitter's quarter stations.
3831        for pair in fit.curve.knots.windows(2) {
3832            if pair[1] <= pair[0] {
3833                continue;
3834            }
3835            for local in [
3836                0.06943184420297371,
3837                0.33000947820757187,
3838                0.6699905217924281,
3839                0.9305681557970262,
3840            ] {
3841                let t = pair[0] + (pair[1] - pair[0]) * local;
3842                let uv = fit.curve.evaluate(t)?;
3843                if surface
3844                    .evaluate_extended(uv.x, uv.y)?
3845                    .sub(stations(t)?)
3846                    .length()
3847                    > tolerance
3848                {
3849                    failed.push(t);
3850                }
3851            }
3852        }
3853        if failed.is_empty() {
3854            return Ok(fit.curve);
3855        }
3856        if breaks.len() + failed.len() > 8192 {
3857            break;
3858        }
3859        breaks.extend(failed);
3860        breaks.sort_by(f64::total_cmp);
3861        breaks.dedup();
3862    }
3863    Err("analytic pcurve failed independent knot-span witnesses".into())
3864}
3865
3866#[allow(clippy::too_many_arguments)]
3867fn fit_station_pcurve(
3868    surface: &NurbsSurface,
3869    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3870    breaks: &[f64],
3871    corners: &[f64],
3872    tolerance: f64,
3873    base_samples: usize,
3874    refinement_rounds: usize,
3875    parameter_cap: usize,
3876    span_floor: f64,
3877) -> Result<PcurveFit, String> {
3878    fit_station_pcurve_mode(surface, stations, breaks, corners, tolerance, base_samples, refinement_rounds, parameter_cap, span_floor, false, None, &[])
3879}
3880
3881/// [`fit_station_pcurve`] with an optional TRACKING mode, taken only by the
3882/// range lane's [`end_span_challenger`]; every other caller keeps the legacy
3883/// mode byte for byte. The legacy fitter probes, ranks and stops on the
3884/// image's same-parameter DEVIATION from the edge point. On an edge standing
3885/// off its carrier that deviation never falls under the ask, so every probe is
3886/// a candidate, the cap goes to the probes with the largest STANDOFF, and a
3887/// tangential slip of `d` adds only about d²/(2g) to a deviation over a
3888/// standoff `g`: the four original rows' challenger met its standoff (4.670e-6)
3889/// and kept a common tracking of 1.434e-6 (root's e24 run, 2026-10-05). In
3890/// tracking mode each probe reads its TRACKING, the image against the edge
3891/// point's foot (the nearer admitted one of the global projection and the
3892/// projection seeded at the image's uv: finite, inside the native domain, as
3893/// [`common_station_read`] admits). A probe is a candidate only over the ask,
3894/// the cap goes to the worst TRACKING first, and the one raise is taken when
3895/// the last round's tracking still misses the ask. The reported residual
3896/// stays the same-parameter deviation (standoff included). A probe with no
3897/// admitted foot is an error, which the challenger turns into the exact legacy
3898/// fit.
3899#[allow(clippy::too_many_arguments)]
3900fn fit_station_pcurve_mode(
3901    surface: &NurbsSurface,
3902    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3903    breaks: &[f64],
3904    corners: &[f64],
3905    tolerance: f64,
3906    base_samples: usize,
3907    refinement_rounds: usize,
3908    parameter_cap: usize,
3909    span_floor: f64,
3910    track_projection: bool,
3911    reference: Option<&NurbsCurve>,
3912    verify: &[f64],
3913) -> Result<PcurveFit, String> {
3914    // Read only in tracking mode: the legacy mode makes no extra call.
3915    let domains = if track_projection { Some(surface_domains(surface)?) } else { None };
3916    // The tracking reading at one fraction, by the SAME foot rule as
3917    // [`common_station_read`], the reader the challenger accepts on: the
3918    // nearest admitted foot among the global projection and the projections
3919    // seeded at this image's uv and at the reference (legacy) pcurve's uv at
3920    // the same fraction. Returns the tracking and that foot (uv, distance),
3921    // which is where a tracking insert is placed.
3922    let tracking_of = |represented: Vec3, edge_point: Vec3, uv: Vec3, fraction: f64| -> Result<(f64, [f64; 2], f64), String> {
3923        let (domain_u, domain_v) = domains.ok_or_else(|| "station tracking: legacy mode".to_string())?;
3924        let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
3925        let reference_seed = match reference {
3926            Some(curve) => curve.evaluate(fraction).ok().and_then(|seed| memo_seeded_foot(surface, edge_point, seed.x, seed.y)),
3927            None => None,
3928        };
3929        // The common reader's order (global, reference, candidate), so an
3930        // equal-distance tie takes the same foot here as there.
3931        let foot = common_foot(
3932            memo_global_foot(surface, edge_point),
3933            reference_seed,
3934            memo_seeded_foot(surface, edge_point, uv.x, uv.y),
3935            domain_u,
3936            domain_v,
3937        )
3938        .ok_or_else(|| "station tracking: no admitted foot".to_string())?;
3939        let tracking = represented.sub(foot.point).length();
3940        if !(finite(represented) && tracking.is_finite()) {
3941            return Err("station tracking: non-finite reading".into());
3942        }
3943        Ok((tracking, [foot.u, foot.v], foot.distance))
3944    };
3945    // The last round's tracking missed the ask (tracking mode only).
3946    let mut tracking_unmet = false;
3947    let evaluate_edge = stations;
3948    let base_samples = base_samples.max(1);
3949    // The general caller floors its ask: its projector places a foot
3950    // to about `LINEAR_TOLERANCE` (1e-7), so a caller asking for 1e-9 asks for
3951    // more than any station can deliver. Chased to such an ask the fit spends
3952    // its cap and reads its own noise — the direct-edit heals asked 1e-9 on
3953    // stations 9.9e-8 off their carrier and were refused by 8.5e-9
3954    // (2026-09-26). The floor is the ask's floor; the report says what was
3955    // reached against it.
3956
3957    let mut parameters = (0..=base_samples)
3958        .map(|index| index as f64 / base_samples as f64)
3959        .collect::<Vec<_>>();
3960    // A break within the span floor of a station IS that station: two nodes
3961    // closer than that make the interpolant swing between them, and over a
3962    // stretch that short the kink moves the fit by nothing a bar can read.
3963    // `abc_00000011` face #549's curve carries a triple knot 4e-7 before its
3964    // end; as a station it put the cubic 1.594e-2 off between it and the last
3965    // one (measured 2026-09-26), where the file's curve sits 1e-7 off.
3966    // A break that is a CORNER of the curve (`corners`, a subset of
3967    // `breaks`: the range lane passes its curve's knots of multiplicity >=
3968    // degree as both) is a C0 JOIN of the interpolant
3969    // (`build_interpolant_joined`): one cubic through the corner overshoots
3970    // on both sides whatever is inserted. A break that is only a station
3971    // (an analytic witness, a caller's own marker) joins nothing.
3972    let mut joins = Vec::with_capacity(corners.len());
3973    for &fraction in breaks {
3974        if !(fraction > 0.0 && fraction < 1.0) {
3975            continue;
3976        }
3977        let corner = corners.contains(&fraction);
3978        let at = parameters.partition_point(|parameter| *parameter < fraction);
3979        let near_left = at > 0 && fraction - parameters[at - 1] <= span_floor;
3980        let near_right = at < parameters.len() && parameters[at] - fraction <= span_floor;
3981        if near_left || near_right {
3982            // The break IS that station (a corner at a base station, e.g.
3983            // the midpoint of a two-piece curve at 32/64): no insert, but the
3984            // station is still the join.
3985            if corner {
3986                joins.push(if near_right { parameters[at] } else { parameters[at - 1] });
3987            }
3988            continue;
3989        }
3990        parameters.insert(at, fraction);
3991        if corner {
3992            joins.push(fraction);
3993        }
3994    }
3995    // The 3D edge point behind each raw inversion sample, kept parallel so the
3996    // continuity repair can re-seed a jumped station from its own footpoint.
3997    let mut edge_points = parameters
3998        .iter()
3999        .map(|fraction| evaluate_edge(*fraction))
4000        .collect::<Result<Vec<_>, _>>()?;
4001    // The stations' standoff from the carrier: the part of every residual no
4002    // pcurve can remove, known before a single probe is spent.
4003    let mut off_surface = 0.0_f64;
4004    let mut raw = Vec::with_capacity(edge_points.len());
4005    let mut gaps = Vec::with_capacity(edge_points.len());
4006    for point in &edge_points {
4007        let (parameter, gap) = invert_checked(surface, *point)?;
4008        off_surface = off_surface.max(gap);
4009        raw.push(parameter);
4010        gaps.push(gap);
4011    }
4012    repair_branch_jumps(surface, &edge_points, &mut raw, tolerance)?;
4013    let (mut pcurve, mut excursion, mut distance) =
4014        build_interpolant_joined(surface, &raw, &parameters, &joins)?;
4015
4016    let mut cap = parameter_cap.max(parameters.len());
4017    let mut rounds = refinement_rounds;
4018    let mut raised = false;
4019    loop {
4020        let mut exit = PcurveFitExit::RoundBudget;
4021        let mut converged_max = None;
4022        // This pass's last round probed every span (none narrow, none
4023        // truncated) and every probe tracked within the ask (tracking mode).
4024        let mut tracking_met = false;
4025        for _ in 0..rounds {
4026            if parameters.len() >= cap {
4027                exit = PcurveFitExit::SampleCeiling;
4028                break;
4029            }
4030            // The target is the ASK, bare: a station standing off the carrier
4031            // is chased to the foot it projects to, as the fitter has always
4032            // done. A target of ask + standoff (one landing, 2026-09-26) let
4033            // such a fit stop at its base stations with the interpolant
4034            // wandering between them, folded a molex wall's mesh and put a
4035            // trim of abc_00000023 2.2e-5 off its own parameter; the bar
4036            // below still reads what it reached.
4037            let target = tolerance;
4038            let mut candidates = Vec::new();
4039            let mut round_max = 0.0_f64;
4040            let mut truncated = false;
4041            let mut skipped_narrow = false;
4042            let worst_first = worst_first();
4043            'spans: for index in 0..parameters.len() - 1 {
4044                // The loop's own resolution floor: a span narrower than this
4045                // is not subdivided. Without it the
4046                // raised pass inserted into a vanishing span at a trim's end
4047                // until the cap — `abc_00000011` face #549's last stations sat
4048                // 4e-7 apart with their feet clamped at the patch edge, and the
4049                // cubic through them swung 1.594e-2 off between them (measured
4050                // 2026-09-26). A miss that survives only inside such a span is
4051                // reported as [`PcurveFitExit::SpanFloor`].
4052                if parameters[index + 1] - parameters[index] < span_floor {
4053                    skipped_narrow = true;
4054                    continue;
4055                }
4056                for local in [0.25, 0.5, 0.75] {
4057                    if !worst_first && parameters.len() + candidates.len() >= cap {
4058                        truncated = true;
4059                        break 'spans;
4060                    }
4061                    let fraction =
4062                        parameters[index] + (parameters[index + 1] - parameters[index]) * local;
4063                    let uv = pcurve.evaluate(fraction)?;
4064                    let represented = surface.evaluate_extended(uv.x, uv.y)?;
4065                    let edge_point = evaluate_edge(fraction)?;
4066                    let deviation = represented.sub(edge_point).length();
4067                    // The probe's reading: its deviation (legacy), or its
4068                    // tracking against the admitted foot (tracking mode).
4069                    let (reading, foot) = if track_projection {
4070                        let (tracking, foot_uv, foot_gap) = tracking_of(represented, edge_point, uv, fraction)?;
4071                        (tracking, Some((foot_uv, foot_gap)))
4072                    } else {
4073                        (deviation, None)
4074                    };
4075                    round_max = round_max.max(reading);
4076                    if reading <= target {
4077                        continue;
4078                    }
4079                    candidates.push((index, fraction, edge_point, uv, reading, foot));
4080                }
4081            }
4082            // Tracking mode's VERIFICATION, before it may stop: a round whose
4083            // quarter probes all track within the ask is read again at the
4084            // probes the challenger's acceptance reads, the current pcurve's
4085            // own knot spans (endpoints, quarters and 16 interior points: the
4086            // interpolant's knots are averages of three stations, not the
4087            // stations) and the caller's fixed fractions (the legacy pcurve's
4088            // spans and the edge's own). A probe over the ask becomes a
4089            // candidate at its own fraction, placed at its own foot. One
4090            // within the span floor of a station cannot be inserted: it is
4091            // counted, and the fit may not report its tracking as met. On e24
4092            // the four rows stopped on their quarter probes and read 1.144e-7 /
4093            // 1.590e-7 at the common probes (a4c84871 runtime, 2026-10-05).
4094            let mut verify_blocked = false;
4095            if track_projection && candidates.is_empty() && !truncated && !skipped_narrow {
4096                for fraction in verification_fractions(&pcurve, verify)? {
4097                    let index = parameters.partition_point(|parameter| *parameter <= fraction).saturating_sub(1).min(parameters.len() - 2);
4098                    let uv = pcurve.evaluate(fraction)?;
4099                    let represented = surface.evaluate_extended(uv.x, uv.y)?;
4100                    let edge_point = evaluate_edge(fraction)?;
4101                    let (tracking, foot_uv, foot_gap) = tracking_of(represented, edge_point, uv, fraction)?;
4102                    round_max = round_max.max(tracking);
4103                    if tracking <= target {
4104                        continue;
4105                    }
4106                    if fraction - parameters[index] <= span_floor || parameters[index + 1] - fraction <= span_floor {
4107                        verify_blocked = true;
4108                        continue;
4109                    }
4110                    // Two over-ask probes closer than the span floor in one
4111                    // span: keep the worse, so no near-duplicate stations.
4112                    if let Some(last) = candidates.last_mut() {
4113                        if last.0 == index && fraction - last.1 <= span_floor {
4114                            if tracking > last.4 {
4115                                *last = (index, fraction, edge_point, uv, tracking, Some((foot_uv, foot_gap)));
4116                            }
4117                            continue;
4118                        }
4119                    }
4120                    candidates.push((index, fraction, edge_point, uv, tracking, Some((foot_uv, foot_gap))));
4121                }
4122            }
4123            tracking_unmet = track_projection && round_max > target;
4124            // A round with more candidates than the cap has room for spends
4125            // that room on its WORST probes, kept in curve order, rather than
4126            // on the first spans in order: truncating in span order left the
4127            // late spans of an off-carrier ring at their base spacing and its
4128            // image 1.523e-6 off its feet; worst first reaches 5.84e-8 on the
4129            // same 513 samples. An even stride along the curve reached 2.87e-7
4130            // there but diluted the inserts a local miss needs and lost fits
4131            // over the corpus (a 1.3e-5 trim of `abc_00000011` fell back to its
4132            // 4.4e-4 size-ask fit), measured 2026-09-27.
4133            let room = cap.saturating_sub(parameters.len());
4134            if candidates.len() > room {
4135                truncated = true;
4136                let mut order: Vec<usize> = (0..candidates.len()).collect();
4137                order.sort_by(|&a, &b| candidates[b].4.total_cmp(&candidates[a].4).then(a.cmp(&b)));
4138                order.truncate(room);
4139                order.sort_unstable();
4140                candidates = order.into_iter().map(|index| candidates[index]).collect();
4141            }
4142            let mut inserts = Vec::with_capacity(candidates.len());
4143            for (index, fraction, edge_point, uv, _, foot) in candidates {
4144                // A tracking candidate is placed at the very foot it was read
4145                // against, so the node's image IS that foot; the legacy
4146                // inversion is unchanged.
4147                let (parameter, gap) = match foot {
4148                    Some(placed) => placed,
4149                    None => invert_near(surface, edge_point, [uv.x, uv.y], gaps[index].max(gaps[index + 1]))?,
4150                };
4151                inserts.push((index + 1, fraction, edge_point, parameter, gap));
4152            }
4153            if station_fit_tracing() {
4154                eprintln!(
4155                    "STATION-FIT round: samples={} target={target:.3e} round_max={round_max:.3e} inserts={} truncated={truncated}{}",
4156                    parameters.len(),
4157                    inserts.len(),
4158                    // Tracking mode's round_max is a TRACKING reading.
4159                    if track_projection { " mode=tracking" } else { "" }
4160                );
4161            }
4162            if inserts.is_empty() {
4163                exit = if truncated {
4164                    PcurveFitExit::SampleCeiling
4165                } else if skipped_narrow {
4166                    // Every probed span is within the target; the narrow ones
4167                    // were not probed, and the sweep below measures them.
4168                    PcurveFitExit::SpanFloor
4169                } else if track_projection {
4170                    // Every probe TRACKS within the ask, but round_max is a
4171                    // tracking reading, not the deviation the report carries.
4172                    // The exit is Stalled (no probe can be improved; the
4173                    // residual measured below is the edge's own standoff),
4174                    // and it becomes Converged below only if that measured
4175                    // deviation itself meets the floor. A verification probe
4176                    // over the ask that could not be inserted leaves the
4177                    // tracking UNMET.
4178                    tracking_met = !verify_blocked;
4179                    PcurveFitExit::Stalled
4180                } else {
4181                    converged_max = Some(round_max);
4182                    PcurveFitExit::Converged
4183                };
4184                break;
4185            }
4186            for (index, fraction, edge_point, parameter, gap) in inserts.into_iter().rev() {
4187                parameters.insert(index, fraction);
4188                edge_points.insert(index, edge_point);
4189                raw.insert(index, parameter);
4190                gaps.insert(index, gap);
4191                off_surface = off_surface.max(gap);
4192            }
4193            // Inserts are independent global inversions too — re-run the repair
4194            // so a fold-flip introduced mid-refinement cannot poison the next
4195            // round's deviation interpolant.
4196            repair_branch_jumps(surface, &edge_points, &mut raw, tolerance)?;
4197            let rebuilt = build_interpolant_joined(surface, &raw, &parameters, &joins)?;
4198            pcurve = rebuilt.0;
4199            excursion = rebuilt.1;
4200            distance = rebuilt.2;
4201            if truncated {
4202                exit = PcurveFitExit::SampleCeiling;
4203                break;
4204            }
4205        }
4206        let residual = match converged_max {
4207            Some(measured) => measured,
4208            None => {
4209                station_residual(surface, evaluate_edge, &pcurve, &parameters, tolerance, &mut off_surface)?
4210            }
4211        };
4212        if station_fit_tracing() {
4213            eprintln!(
4214                "STATION-FIT pass raised={raised} exit={exit:?} samples={} residual={residual:.3e} off_surface={off_surface:.3e}",
4215                parameters.len()
4216            );
4217            if residual > tolerance + off_surface && (exit == PcurveFitExit::Converged || raised) {
4218                // Where the miss sits, and the uv track around it: the trace a
4219                // refusal needs to be attributed to a fold, a seam or the file.
4220                let (mut worst, mut at) = (0.0f64, 0usize);
4221                for (index, span) in parameters.windows(2).enumerate() {
4222                    let fraction = 0.5 * (span[0] + span[1]);
4223                    let uv = pcurve.evaluate(fraction)?;
4224                    let deviation = surface.evaluate_extended(uv.x, uv.y)?.sub(evaluate_edge(fraction)?).length();
4225                    if deviation > worst {
4226                        worst = deviation;
4227                        at = index;
4228                    }
4229                }
4230                let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
4231                let (closed_u, closed_v) = surface_closedness(surface)?;
4232                eprintln!(
4233                    "STATION-FIT OFF BAR: worst {worst:.3e} between stations {at} and {}; surface degree {}x{} net {}x{} domain u[{u0},{u1}] v[{v0},{v1}] closed ({closed_u},{closed_v}) analytic {:?}",
4234                    at + 1,
4235                    surface.degree_u,
4236                    surface.degree_v,
4237                    surface.control_points.len(),
4238                    surface.control_points[0].len(),
4239                    surface.analytic().map(|_| "yes").unwrap_or("no")
4240                );
4241                {
4242                    let fraction = 0.5 * (parameters[at] + parameters[at + 1]);
4243                    let uv = pcurve.evaluate(fraction)?;
4244                    let image = surface.evaluate_extended(uv.x, uv.y)?;
4245                    let station = evaluate_edge(fraction)?;
4246                    let foot = project_point_to_surface(surface, station)?;
4247                    let seeded = project_point_to_surface_seeded(surface, station, raw[at][0], raw[at][1])?;
4248                    eprintln!(
4249                        "    at the worst midpoint: deviation {:.4e}, station gap {:.4e} (seeded {:.4e}), image-to-foot {:.4e} (to seeded foot {:.4e}), foot uv ({:.7}, {:.7}) seeded ({:.7}, {:.7}) image uv ({:.7}, {:.7})",
4250                        image.sub(station).length(), foot.distance, seeded.distance, image.sub(foot.point).length(), image.sub(seeded.point).length(), foot.u, foot.v, seeded.u, seeded.v, uv.x, uv.y
4251                    );
4252                }
4253                let lo = at.saturating_sub(3);
4254                let hi = (at + 4).min(parameters.len() - 1);
4255                for index in lo..=hi {
4256                    eprintln!(
4257                        "    station {index}: fraction {:.6} uv ({:.6}, {:.6}) point ({:.4}, {:.4}, {:.4})",
4258                        parameters[index], raw[index][0], raw[index][1], edge_points[index].x, edge_points[index].y, edge_points[index].z
4259                    );
4260                }
4261            }
4262        }
4263        // Legacy only: a SpanFloor exit whose measured DEVIATION is on the
4264        // bar is promoted. In tracking mode the deviation sits at the standoff
4265        // whatever the unprobed narrow spans' TRACKING is, so SpanFloor stays
4266        // SpanFloor (unread); a tracking-mode fit is Converged only when every
4267        // span was probed within the ask AND the measured deviation meets the
4268        // floor (the exit's documented meaning, never the standoff bar).
4269        if !track_projection && exit == PcurveFitExit::SpanFloor && residual <= tolerance + off_surface {
4270            exit = PcurveFitExit::Converged;
4271        }
4272        if tracking_met && residual <= tolerance {
4273            exit = PcurveFitExit::Converged;
4274        }
4275        if exit != PcurveFitExit::Converged
4276            && !raised
4277            && (residual > tolerance + off_surface || tracking_unmet)
4278            && cap < PCURVE_RAISED_SAMPLES
4279        {
4280            raised = true;
4281            cap = PCURVE_RAISED_SAMPLES;
4282            // The raised pass is bounded by SAMPLES, not rounds: a kink
4283            // converges O(h²), a round per halving, and the three rounds of
4284            // the first pass are what left the 2026-09-18 census's fits over
4285            // their ask with budget to spare (RoundBudget at 158–400 of 2000
4286            // samples, measured 2026-09-26). Forty rounds cover every halving
4287            // the cap admits; a fit that is not converging stalls out first.
4288            rounds = RAISED_ROUNDS;
4289            continue;
4290        }
4291        return Ok(PcurveFit {
4292            curve: pcurve,
4293            report: PcurveFitReport {
4294                residual,
4295                floor: tolerance,
4296                samples: parameters.len(),
4297                exit,
4298                off_surface,
4299                raised,
4300                clamped_excursion: excursion,
4301                clamped_distance: distance,
4302            },
4303        });
4304    }
4305}
4306
4307/// [`fit_pcurve_on_surface_stations`] for the callers that only need the
4308/// curve, accepted or refused on its bar (`accept_fit`).
4309pub fn build_pcurve_on_surface_stations(
4310    surface: &NurbsSurface,
4311    stations: &dyn Fn(f64) -> Result<Vec3, String>,
4312    breaks: &[f64],
4313    tolerance: f64,
4314    base_samples: usize,
4315    refinement_rounds: usize,
4316    parameter_cap: usize,
4317) -> Result<NurbsCurve, String> {
4318    accept_fit(fit_pcurve_on_surface_stations(
4319        surface,
4320        stations,
4321        breaks,
4322        tolerance,
4323        base_samples,
4324        refinement_rounds,
4325        parameter_cap,
4326    )?)
4327}
4328
4329/// The largest 3D distance between `pcurve`'s image and its stations at the
4330/// quarter points of every span of `parameters` — out of sample by
4331/// construction, since the interpolant is exact at its nodes. Unclamped
4332/// evaluations; a station read over the running bar is inverted so that
4333/// `off_surface` covers the standoff AT the stations the residual is taken at,
4334/// not only at the nodes (a curve lifted off its plane by a bump stands
4335/// further off between two nodes than at either).
4336fn station_residual(
4337    surface: &NurbsSurface,
4338    stations: &dyn Fn(f64) -> Result<Vec3, String>,
4339    pcurve: &NurbsCurve,
4340    parameters: &[f64],
4341    tolerance: f64,
4342    off_surface: &mut f64,
4343) -> Result<f64, String> {
4344    let mut worst = 0.0_f64;
4345    let mut read = |fraction: f64| -> Result<(), String> {
4346        let uv = pcurve.evaluate(fraction)?;
4347        let represented = surface.evaluate_extended(uv.x, uv.y)?;
4348        let station = stations(fraction)?;
4349        let deviation = represented.sub(station).length();
4350        worst = worst.max(deviation);
4351        if deviation > tolerance + *off_surface {
4352            *off_surface = off_surface.max(invert_checked(surface, station)?.1);
4353        }
4354        Ok(())
4355    };
4356    for span in parameters.windows(2) {
4357        for local in [0.25, 0.5, 0.75] {
4358            read(span[0] + (span[1] - span[0]) * local)?;
4359        }
4360    }
4361    Ok(worst)
4362}
4363
4364