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 = 1e-12;
8const LINEAR_TOLERANCE: f64 = 1e-7;
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: std::env::var_os("BREP_PROFILE").is_some().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            eprintln!("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 sphere/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), 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;
119impl PcurveSampleScope {
120    fn open(surface: &NurbsSurface, curve: &NurbsCurve, enabled: bool) -> Self {
121        let cache = (enabled && matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })))
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
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 std::env::var_os("BREP_PROFILE").is_some() {
134                    eprintln!("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    let key = (u.to_bits(), v.to_bits(), extended);
185    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
186        let mut stack = stack.borrow_mut();
187        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
188        if cache.surface != surface as *const _ as usize { return (false, None) }
189        cache.requests[1] += 1;
190        let hit = cache.surfaces.get(&key).copied();
191        cache.hits[1] += usize::from(hit.is_some());
192        (true, hit)
193    });
194    if let Some(hit) = hit { return Ok(hit) }
195    let point = if extended { section_extended_point(surface, u, v, PCURVE_STACK_POINT.with(|state| state.get()))? } else { surface.evaluate(u, v)? };
196    if active { PCURVE_SAMPLES.with(|stack| {
197        let mut stack = stack.borrow_mut();
198        let cache = stack.last_mut().unwrap().as_mut().unwrap();
199        if cache.surfaces.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.surfaces.insert(key, point); }
200    }); }
201    Ok(point)
202}
203fn invert_checked(surface: &NurbsSurface, point: Vec3) -> Result<([f64; 2], f64), String> {
204    let key = [point.x.to_bits(), point.y.to_bits(), point.z.to_bits()];
205    let (active, hit) = PCURVE_SAMPLES.with(|stack| {
206        let mut stack = stack.borrow_mut();
207        let Some(Some(cache)) = stack.last_mut() else { return (false, None) };
208        if cache.surface != surface as *const _ as usize { return (false, None) }
209        cache.requests[2] += 1;
210        let hit = cache.inversions.get(&key).copied();
211        cache.hits[2] += usize::from(hit.is_some());
212        (true, hit)
213    });
214    if let Some(hit) = hit { return Ok(hit) }
215    let projection = invert_checked_uncached(surface, point)?;
216    if active { PCURVE_SAMPLES.with(|stack| {
217        let mut stack = stack.borrow_mut();
218        let cache = stack.last_mut().unwrap().as_mut().unwrap();
219        if cache.inversions.len() < PCURVE_SAMPLE_CACHE_LIMIT { cache.inversions.insert(key, projection); }
220    }); }
221    Ok(projection)
222}
223
224fn invert_checked_uncached(surface: &NurbsSurface, point: Vec3) -> Result<([f64; 2], f64), String> {
225    if surface.is_affine()? {
226        let ([u0, _], [v0, _]) = surface_domains(surface)?;
227        let (origin, du, dv) = surface.deriv1(u0, v0)?;
228        let delta = point.sub(origin);
229        let uu = du.dot(du);
230        let uv = du.dot(dv);
231        let vv = dv.dot(dv);
232        let along_u = delta.dot(du);
233        let along_v = delta.dot(dv);
234        let determinant = uu * vv - uv * uv;
235        if determinant.abs() > EPSILON {
236            let parameter = [
237                u0 + (along_u * vv - along_v * uv) / determinant,
238                v0 + (along_v * uu - along_u * uv) / determinant,
239            ];
240            // The standoff is a MEASUREMENT here as on every other carrier:
241            // until 2026-09-26 this returned 0.0 for "affine, not measured",
242            // and a curve 1e-2 off its plane read as lying on it.
243            let foot = origin.add(du.scale(parameter[0] - u0)).add(dv.scale(parameter[1] - v0));
244            return Ok((parameter, point.sub(foot).length()));
245        }
246    }
247    let projection = project_point_to_surface(surface, point)?;
248    Ok(([projection.u, projection.v], projection.distance))
249}
250
251/// Whether an end station at a cone's apex takes its nearest regular
252/// station's u (`true`), as in `build_interpolant`, or the projector's
253/// arbitrary u there as before 2026-09-27. `BREP_PCURVE_CONE_APEX_U=0`
254/// restores the projector's u, for a same-binary A/B.
255fn cone_apex_u() -> bool {
256    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
257    *ON.get_or_init(|| std::env::var_os("BREP_PCURVE_CONE_APEX_U").is_none_or(|value| value != "0"))
258}
259
260/// Whether a round with more candidates than the cap has room for keeps its
261/// WORST probes (`true`), or the first in span order as before 2026-09-27.
262/// `BREP_PCURVE_WORST_FIRST=0` restores span order, for a same-binary A/B.
263fn worst_first() -> bool {
264    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
265    *ON.get_or_init(|| std::env::var_os("BREP_PCURVE_WORST_FIRST").is_none_or(|value| value != "0"))
266}
267
268/// `BREP_PCURVE_C0_JOIN=0` builds one C2 interpolant through the stations as
269/// before 2026-10-03 (the C0 joins at the curve's corners off), for a
270/// same-binary A/B. Read once per process.
271fn c0_joins() -> bool {
272    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
273    *ON.get_or_init(|| std::env::var_os("BREP_PCURVE_C0_JOIN").is_none_or(|value| value != "0"))
274}
275
276fn seeded_inserts() -> bool {
277    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
278    *ON.get_or_init(|| std::env::var_os("BREP_PCURVE_SEEDED_INSERTS").is_none_or(|value| value != "0"))
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() {
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).
964struct FootMemo {
965    surface: *const NurbsSurface,
966    global: rustc_hash::FxHashMap<[u64; 3], Option<crate::SurfaceProjection>>,
967    seeded: rustc_hash::FxHashMap<[u64; 5], Option<crate::SurfaceProjection>>,
968}
969
970/// Opens a [`FootMemo`] for `surface` on this thread until dropped. Opening
971/// one where a memo for the SAME surface is already open reuses it (an inner
972/// scope, e.g. the range challenger inside an importer coedge); a memo for
973/// another surface is set aside and restored on drop. The borrow of `surface`
974/// keeps it alive and unmodified for the scope, so the pointer key cannot be
975/// reused by another surface while the memo answers for it.
976pub(crate) struct FootMemoScope<'a> {
977    previous: Option<Option<FootMemo>>,
978    _surface: std::marker::PhantomData<&'a NurbsSurface>,
979    /// Not `Send`: the scope must close on the thread that opened it.
980    _thread_bound: std::marker::PhantomData<*const ()>,
981}
982
983impl<'a> FootMemoScope<'a> {
984    pub(crate) fn open(surface: &'a NurbsSurface) -> Self {
985        let key = surface as *const NurbsSurface;
986        let previous = FOOT_MEMO.with(|memo| {
987            let mut memo = memo.borrow_mut();
988            if memo.as_ref().is_some_and(|open| std::ptr::eq(open.surface, key)) {
989                None
990            } else {
991                Some(memo.replace(FootMemo { surface: key, global: Default::default(), seeded: Default::default() }))
992            }
993        });
994        Self { previous, _surface: std::marker::PhantomData, _thread_bound: std::marker::PhantomData }
995    }
996}
997
998impl Drop for FootMemoScope<'_> {
999    fn drop(&mut self) {
1000        if let Some(previous) = self.previous.take() {
1001            FOOT_MEMO.with(|memo| *memo.borrow_mut() = previous);
1002        }
1003    }
1004}
1005
1006fn point_bits(point: Vec3) -> [u64; 3] {
1007    [point.x.to_bits(), point.y.to_bits(), point.z.to_bits()]
1008}
1009
1010/// [`project_point_to_surface`] as `.ok()`, through the open memo for this
1011/// surface when there is one. `#[track_caller]`: the projector still sees the
1012/// reader's own call site. Under a `BREP_PROJECTION_GLOBAL_SITES`/`_EXCEPT`
1013/// filter the projector's answer depends on that site, so the memo is not
1014/// consulted then.
1015#[track_caller]
1016fn memo_global_foot(surface: &NurbsSurface, point: Vec3) -> Option<crate::SurfaceProjection> {
1017    if crate::projection::global_site_filter_active() {
1018        return project_point_to_surface(surface, point).ok();
1019    }
1020    let key = point_bits(point);
1021    let hit = FOOT_MEMO.with(|memo| {
1022        memo.borrow().as_ref().filter(|open| std::ptr::eq(open.surface, surface)).map(|open| open.global.get(&key).copied())
1023    });
1024    match hit {
1025        Some(Some(foot)) => foot,
1026        Some(None) => {
1027            let foot = project_point_to_surface(surface, point).ok();
1028            FOOT_MEMO.with(|memo| {
1029                if let Some(open) = memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)) {
1030                    open.global.insert(key, foot);
1031                }
1032            });
1033            foot
1034        }
1035        None => project_point_to_surface(surface, point).ok(),
1036    }
1037}
1038
1039/// [`project_point_to_surface_seeded`] as `.ok()`, through the open memo for
1040/// this surface when there is one.
1041fn memo_seeded_foot(surface: &NurbsSurface, point: Vec3, seed_u: f64, seed_v: f64) -> Option<crate::SurfaceProjection> {
1042    let [x, y, z] = point_bits(point);
1043    let key = [x, y, z, seed_u.to_bits(), seed_v.to_bits()];
1044    let hit = FOOT_MEMO.with(|memo| {
1045        memo.borrow().as_ref().filter(|open| std::ptr::eq(open.surface, surface)).map(|open| open.seeded.get(&key).copied())
1046    });
1047    match hit {
1048        Some(Some(foot)) => foot,
1049        Some(None) => {
1050            let foot = project_point_to_surface_seeded(surface, point, seed_u, seed_v).ok();
1051            FOOT_MEMO.with(|memo| {
1052                if let Some(open) = memo.borrow_mut().as_mut().filter(|open| std::ptr::eq(open.surface, surface)) {
1053                    open.seeded.insert(key, foot);
1054                }
1055            });
1056            foot
1057        }
1058        None => project_point_to_surface_seeded(surface, point, seed_u, seed_v).ok(),
1059    }
1060}
1061
1062thread_local! {
1063    /// The open [`PcurveFitScope`]s on this thread, innermost last.
1064    static PCURVE_FIT_SCOPES: std::cell::RefCell<Vec<PcurveFitLedger>> =
1065        const { std::cell::RefCell::new(Vec::new()) };
1066}
1067
1068/// `BREP_DEBUG_PCURVE_FIT` only: a process-wide id per [`refine_pcurve`]
1069/// call, so its first-pass and candidate `PCURVE-TRACK` lines pair up even
1070/// when fits run on several threads.
1071static PCURVE_TRACK_CALL: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
1072
1073/// An open tally of the pcurve fits made on this thread — see
1074/// [`PcurveFitLedger`]. Open it where an operation starts, [`close`] it where
1075/// the operation returns its diagnostics; a `?` that unwinds past it drops the
1076/// tally.
1077///
1078/// [`close`]: PcurveFitScope::close
1079pub struct PcurveFitScope {
1080    /// Not `Send`: the scope must close on the thread that opened it.
1081    _thread_bound: std::marker::PhantomData<*const ()>,
1082}
1083
1084impl PcurveFitScope {
1085    pub fn open() -> Self {
1086        PCURVE_FIT_SCOPES.with(|scopes| scopes.borrow_mut().push(PcurveFitLedger::default()));
1087        Self {
1088            _thread_bound: std::marker::PhantomData,
1089        }
1090    }
1091
1092    /// Take the tally, folding it into the enclosing scope if there is one.
1093    pub fn close(self) -> PcurveFitLedger {
1094        let ledger = PCURVE_FIT_SCOPES.with(|scopes| {
1095            let mut scopes = scopes.borrow_mut();
1096            let ledger = scopes.pop().unwrap_or_default();
1097            if let Some(parent) = scopes.last_mut() {
1098                parent.fold(&ledger);
1099            }
1100            ledger
1101        });
1102        std::mem::forget(self);
1103        ledger
1104    }
1105}
1106
1107impl Drop for PcurveFitScope {
1108    fn drop(&mut self) {
1109        PCURVE_FIT_SCOPES.with(|scopes| {
1110            scopes.borrow_mut().pop();
1111        });
1112    }
1113}
1114
1115pub(crate) fn record_fit(report: &PcurveFitReport) {
1116    // Per-fit trace for the convergence probes (`trim_floor_sweep_probe` and
1117    // its offset-shell sibling): one line per fit with the whole report, the
1118    // way `BREP_DEBUG_PCURVE` traces an endpoint failure.
1119    if std::env::var_os("BREP_DEBUG_PCURVE_FIT").is_some() {
1120        eprintln!("PCURVE-FIT {report:?}");
1121    }
1122    PCURVE_FIT_SCOPES.with(|scopes| {
1123        if let Some(open) = scopes.borrow_mut().last_mut() {
1124            open.record(report);
1125        }
1126    });
1127}
1128
1129/// Largest 3D distance between `pcurve`'s image and `curve` at the
1130/// quarter-points of every span of `parameters` — the stations refinement
1131/// probes, over EVERY span. Evaluations only; nothing is inverted. The sweep
1132/// measures, it does not decide.
1133fn probe_residual(
1134    surface: &NurbsSurface,
1135    curve: &NurbsCurve,
1136    pcurve: &NurbsCurve,
1137    parameters: &[f64],
1138    domain: [f64; 2],
1139    _u_domain: [f64; 2],
1140    _v_domain: [f64; 2],
1141) -> Result<f64, String> {
1142    probe_residual_at(surface, curve, pcurve, parameters, domain, &[0.25, 0.5, 0.75])
1143}
1144
1145/// Extra interior points per sample span, at `j/17` for `j = 1..=16`, that
1146/// [`tracking_acceptance_residual`] reads IN ADDITION to [`probe_residual`]'s
1147/// quarter, mid and three-quarter points (nineteen fractions per span in
1148/// all), so it can never read below the three-point maximum on the same
1149/// curve. The three quarter-points under-read the sixteen-point maximum by
1150/// 3.3–6.5 % on the constructed-cylinder union's imprint pcurves, and sixteen
1151/// sit within 0.4 % of sixty-four there (2026-10-04); the Converged path keeps
1152/// its own read.
1153const TRACKING_ACCEPTANCE_POINTS: usize = 16;
1154
1155/// The same-parameter image-vs-edge distance of `pcurve` at `locals` (span
1156/// fractions) inside every span of `parameters`: the largest, or an error if
1157/// any is not finite.
1158fn probe_residual_at(
1159    surface: &NurbsSurface,
1160    curve: &NurbsCurve,
1161    pcurve: &NurbsCurve,
1162    parameters: &[f64],
1163    [t0, t1]: [f64; 2],
1164    locals: &[f64],
1165) -> Result<f64, String> {
1166    let mut worst = 0.0_f64;
1167    for span in parameters.windows(2) {
1168        for &local in locals {
1169            let fraction = span[0] + (span[1] - span[0]) * local;
1170            let parameter = pcurve.evaluate(fraction)?;
1171            let on_surface =
1172                section_surface_point(surface, parameter.x, parameter.y, true)?;
1173            let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1174            // `f64::max` drops a NaN operand, so a non-finite distance would
1175            // leave `worst` reading the finite stations only. A residual that
1176            // can accept a curve must have measured every station: fail
1177            // closed instead.
1178            let distance = on_surface.sub(on_curve).length();
1179            if !distance.is_finite() {
1180                return Err(format!(
1181                    "probe_residual: non-finite image distance {distance} at fraction {fraction}"
1182                ));
1183            }
1184            worst = worst.max(distance);
1185        }
1186    }
1187    Ok(worst)
1188}
1189
1190/// The probe fractions a native read takes for the given pcurves: both
1191/// domain ENDPOINTS, and the quarter points plus 16 interior points of every
1192/// span between each curve's OWN distinct knots (the installed interpolant's
1193/// spans, not the construction stations). Merged over all the curves, sorted
1194/// and deduplicated, so a standing fit and a candidate are read at the SAME
1195/// fractions.
1196pub(crate) fn native_probe_fractions(curves: &[&NurbsCurve]) -> Result<Vec<f64>, String> {
1197    let locals: Vec<f64> = [0.25, 0.5, 0.75]
1198        .into_iter()
1199        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
1200        .collect();
1201    let mut fractions = Vec::new();
1202    for curve in curves {
1203        let [q0, q1] = curve.domain()?;
1204        fractions.push(q0);
1205        fractions.push(q1);
1206        let mut knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k >= q0 && *k <= q1).collect();
1207        knots.dedup();
1208        for span in knots.windows(2).filter(|w| w[1] > w[0]) {
1209            for &local in &locals {
1210                fractions.push(span[0] + (span[1] - span[0]) * local);
1211            }
1212        }
1213    }
1214    fractions.sort_by(f64::total_cmp);
1215    fractions.dedup();
1216    Ok(fractions)
1217}
1218
1219/// One pcurve read at given probe fractions against the edge curve (whose
1220/// parameter is t0 + (t1 - t0) x fraction): the image's distance from the
1221/// edge point's FOOT on the carrier (its TRACKING, the part a pcurve can
1222/// improve; the foot is seeded at the pcurve's own uv, closed form on an
1223/// analytic carrier), the image's distance from the edge point itself (the
1224/// same-parameter DEVIATION), and the edge point's distance from the carrier
1225/// (its INHERITED STANDOFF). Maxima over the probes; fails closed on any
1226/// non-finite point or distance.
1227#[derive(Clone, Copy, Debug, PartialEq)]
1228struct NativeRead {
1229    tracking: f64,
1230    deviation: f64,
1231    standoff: f64,
1232}
1233
1234fn native_read(surface: &NurbsSurface, curve: &NurbsCurve, pcurve: &NurbsCurve, [t0, t1]: [f64; 2], fractions: &[f64]) -> Result<NativeRead, String> {
1235    let mut read = NativeRead { tracking: 0.0, deviation: 0.0, standoff: 0.0 };
1236    for &fraction in fractions {
1237        let parameter = pcurve.evaluate(fraction)?;
1238        let image = section_surface_point(surface, parameter.x, parameter.y, true)?;
1239        let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1240        let foot = crate::projection::project_point_to_surface_from_seed(surface, on_curve, [parameter.x, parameter.y])?;
1241        let tracking = image.sub(foot.point).length();
1242        let deviation = image.sub(on_curve).length();
1243        if !(tracking.is_finite() && deviation.is_finite() && foot.distance.is_finite()) {
1244            return Err(format!("native read: non-finite reading at fraction {fraction}"));
1245        }
1246        read.tracking = read.tracking.max(tracking);
1247        read.deviation = read.deviation.max(deviation);
1248        read.standoff = read.standoff.max(foot.distance);
1249    }
1250    Ok(read)
1251}
1252
1253/// Whether an off-carrier tracking candidate replaces the standing fit, both
1254/// read at the SAME probes ([`native_probe_fractions`] of both curves): its
1255/// tracking finite, within the unchanged floor and strictly lower, AND its
1256/// same-parameter deviation no worse (the reported total, inherited standoff
1257/// included, must not grow), AND its own refinement fields finite.
1258fn standoff_candidate_accepted(standing: NativeRead, candidate: NativeRead, candidate_fields_finite: bool, floor: f64) -> bool {
1259    candidate_fields_finite
1260        && candidate.tracking.is_finite()
1261        && candidate.deviation.is_finite()
1262        && candidate.tracking <= floor
1263        && candidate.tracking < standing.tracking
1264        && candidate.deviation <= standing.deviation
1265}
1266
1267/// [`probe_residual_at`] at [`probe_residual`]'s three quarter-points plus
1268/// [`TRACKING_ACCEPTANCE_POINTS`] evenly spaced interior points of every span
1269/// (nineteen per span): the maximum of the old three-point reading and the
1270/// sixteen-point one. It is the reading a budget-exit tracking candidate is
1271/// accepted on, and the residual it is then reported with.
1272fn tracking_acceptance_residual(
1273    surface: &NurbsSurface,
1274    curve: &NurbsCurve,
1275    pcurve: &NurbsCurve,
1276    parameters: &[f64],
1277    domain: [f64; 2],
1278) -> Result<f64, String> {
1279    let locals: Vec<f64> = [0.25, 0.5, 0.75]
1280        .into_iter()
1281        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
1282        .collect();
1283    probe_residual_at(surface, curve, pcurve, parameters, domain, &locals)
1284}
1285
1286/// Whether a projection-tracking candidate replaces the fit standing in
1287/// [`refine_pcurve`], given the `reading` it is judged on (see
1288/// [`judge_tracking_candidate`]). `standing_dense` says the standing fit's
1289/// reading is itself a nineteen-point one: a budget-exit candidate was taken.
1290///
1291/// While the standing reading is the fitter's own, a `Converged` candidate is
1292/// taken exactly as before (within the floor, better). A BUDGET exit
1293/// (`SampleCeiling`, `RoundBudget`, `Stalled`, `SpanFloor`) is taken only to
1294/// repair a standing fit that MISSES the floor, and only when its
1295/// nineteen-point reading is finite, within the unchanged floor and strictly
1296/// better. Once the standing reading is a nineteen-point one, every later
1297/// candidate is compared nineteen against nineteen: a Converged one must read
1298/// finite, within the floor and strictly better on the same stencil, and a
1299/// budget exit is never taken (the standing fit is then within the floor).
1300/// The exit label says how the loop stopped, not whether the curve is good: on
1301/// the 15° constructed-cylinder union all six imprint pcurves that shipped
1302/// 1.3e-7..7.0e-6 off had a tracking candidate reading 1.4e-8..9.95e-8 at
1303/// three points per span, discarded for its label (2026-10-04). A standing
1304/// fit already within the floor is never replaced by a budget exit, so every
1305/// in-floor fit is unchanged; a taken candidate keeps its own exit, samples
1306/// and raise, and reports the reading it was taken on.
1307fn tracking_candidate_accepted(standing: f64, standing_dense: bool, floor: f64, exit: PcurveFitExit, reading: f64) -> bool {
1308    if exit == PcurveFitExit::Converged && !standing_dense {
1309        return reading <= floor && reading < standing;
1310    }
1311    if exit != PcurveFitExit::Converged && !(standing > floor) {
1312        return false;
1313    }
1314    reading.is_finite() && reading <= floor && reading < standing
1315}
1316
1317/// The reading a tracking candidate is judged on, and whether it replaces the
1318/// standing fit: `own` (the candidate's own residual) for a Converged
1319/// candidate while the standing reading is the fitter's own; otherwise
1320/// `dense` ([`tracking_acceptance_residual`]'s nineteen points per span), read
1321/// only when the candidate could be taken. An error from `dense` declines.
1322/// [`refine_pcurve`] decides and traces through this one function.
1323fn judge_tracking_candidate(
1324    standing: f64,
1325    standing_dense: bool,
1326    floor: f64,
1327    exit: PcurveFitExit,
1328    own: f64,
1329    dense: impl FnOnce() -> Result<f64, String>,
1330) -> (Result<Option<f64>, String>, bool) {
1331    judge_tracking_candidate_with_bounds(standing, standing_dense, floor, exit, own, dense, false)
1332}
1333
1334fn judge_tracking_candidate_with_bounds(
1335    standing: f64,
1336    standing_dense: bool,
1337    floor: f64,
1338    exit: PcurveFitExit,
1339    own: f64,
1340    dense: impl FnOnce() -> Result<f64, String>,
1341    bounds: bool,
1342) -> (Result<Option<f64>, String>, bool) {
1343    // A budget exit's own residual probes the quarter points of every
1344    // returned span. They are a subset of the nineteen-point stencil, so its
1345    // maximum cannot fall below this already over-floor lower bound.
1346    if bounds && exit != PcurveFitExit::Converged && own > floor {
1347        if std::env::var_os("BREP_PROFILE").is_some() { eprintln!("pcurve.reject_bound kind=quarter_residual"); }
1348        return (Ok(Some(own)), false);
1349    }
1350    let reading = if exit == PcurveFitExit::Converged && !standing_dense {
1351        Ok(Some(own))
1352    } else if exit == PcurveFitExit::Converged || standing > floor {
1353        dense().map(Some)
1354    } else {
1355        Ok(None)
1356    };
1357    let accepted = matches!(
1358        reading,
1359        Ok(Some(value)) if tracking_candidate_accepted(standing, standing_dense, floor, exit, value)
1360    );
1361    (reading, accepted)
1362}
1363
1364/// What one call to [`refine_pcurve`] achieved, beside the curve it left in
1365/// place.
1366struct Refinement {
1367    exit: PcurveFitExit,
1368    residual: f64,
1369    off_surface: f64,
1370    raised: bool,
1371    /// [`PcurveFitReport::clamped_excursion`] and
1372    /// [`PcurveFitReport::clamped_distance`] of the curve left in place.
1373    clamped: [f64; 2],
1374}
1375
1376/// Adaptive 3D-residual refinement of an interpolant, with the PER-TRIM sample
1377/// budget. Shared by [`fit_pcurve_on_surface`] (global inversion) and
1378/// [`fit_pcurve_on_surface_marched`] (seeded projection); `insert` is the one
1379/// step that differs — given a probe station's fraction, the current pcurve's
1380/// parameter there and the edge point, it returns the surface parameter to
1381/// interpolate through (or `None` to decline the station) and the distance
1382/// from the edge point to the surface at that station, its GAP.
1383///
1384/// **First pass.** Four rounds at [`MAX_PCURVE_SAMPLES`], each probing the
1385/// quarter-points of every span wider than 1e-3 of the parameter range and
1386/// inserting the stations over `floor`. Byte-for-byte the pre-2026-09-12
1387/// loop; every exit is classified ([`PcurveFitExit`]) and the residual is
1388/// measured on the RETURNED curve — over every span, unless the final round
1389/// probed every span, in which case that round's maximum already is.
1390///
1391/// **The raise.** A [`PcurveFitExit::SampleCeiling`] exit re-enters the four
1392/// rounds ONCE with [`PCURVE_RAISED_SAMPLES`], continuing from the samples it
1393/// has, when the residual exceeds `off_surface` by more than the floor — the
1394/// returned curve is worse than the edge curve's own distance from the
1395/// surface, so more samples CAN improve it. Measured on `25_cube_pierce_solid`
1396/// (2026-09-12): the edge curves there sit off their surfaces by up to 1.9e-4,
1397/// four of the eight ceiling exits already read their gap to four digits, and
1398/// raising those spent 900 inversions each for no change in the swept
1399/// residual. The raised pass therefore inserts only where the pcurve's surface
1400/// point is further than the floor from the PROJECTION of the edge point — its
1401/// tracking error, which the inversion just computed: it stops when the pcurve
1402/// tracks the surface's nearest point to the floor, which is the best any
1403/// pcurve can do, and reports [`PcurveFitExit::Stalled`] with the deviation it
1404/// actually reached when that is still over the floor. The limit of that pass
1405/// as the floor tightens is the projected edge curve itself, so a volume built
1406/// on it can be shown to converge; the deviation test alone cannot say that on
1407/// off-surface input. Grow-once, capped, deterministic.
1408#[allow(clippy::too_many_arguments)]
1409fn refine_pcurve(
1410    surface: &NurbsSurface,
1411    curve: &NurbsCurve,
1412    domain: [f64; 2],
1413    u_domain: [f64; 2],
1414    v_domain: [f64; 2],
1415    floor: f64,
1416    joins: &[f64],
1417    parameters: &mut Vec<f64>,
1418    raw: &mut Vec<[f64; 2]>,
1419    pcurve: &mut NurbsCurve,
1420    off_surface: f64,
1421    clamped: [f64; 2],
1422    mut insert: impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1423) -> Result<Refinement, String> {
1424    // Trace only (`BREP_DEBUG_PCURVE_FIT`): reads values the passes already
1425    // computed and decides nothing.
1426    let trace = std::env::var_os("BREP_DEBUG_PCURVE_FIT").is_some();
1427    let call = if trace {
1428        PCURVE_TRACK_CALL.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + 1
1429    } else {
1430        0
1431    };
1432    let reject_bounds = PCURVE_REJECT_BOUNDS.with(|state| state.get());
1433    let mut best = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain,
1434        floor, joins, parameters, raw, pcurve, off_surface, clamped, false, 1.0, false, &mut insert, false)?;
1435    if trace {
1436        eprintln!(
1437            "PCURVE-TRACK call={call} first-pass exit={:?} residual={:e} floor={floor:e} off_surface={:e} samples={} raised={} tracking={}",
1438            best.exit,
1439            best.residual,
1440            best.off_surface,
1441            parameters.len(),
1442            best.raised,
1443            if best.off_surface <= floor { "eligible" } else { "standoff-tracking" }
1444        );
1445    }
1446    if best.off_surface > floor {
1447        // The edge curve itself stands off the carrier by more than the floor
1448        // (its INHERITED standoff), so no pcurve can bring the image within the
1449        // floor of the edge point. What a pcurve CAN improve is its tracking
1450        // error: the image's distance from the edge point's foot. Measured
1451        // 2026-10-04 (a2b401d4d, 15-degree crossing, turn 295): a first pass
1452        // ended RoundBudget at 6.726e-6 over a 1.316e-7 standoff and every
1453        // tracking pass was skipped. No candidate refinement when the ACTUAL
1454        // tracking request is met: the first pass's own tracking, read on its
1455        // native spans and endpoints (a diagnostic read; it adds no station),
1456        // within the floor ([`standoff_tracking_rungs`]). A total residual
1457        // under standoff + floor does not prove that: a tangential slip t over
1458        // a standoff g reads sqrt(g^2 + t^2) < g + t.
1459        // `BREP_PCURVE_STANDOFF_TRACKING=0`: diagnostic A/B hatch, not a
1460        // policy. It restores the pre-lane answer (35c8610a1's parent: an
1461        // off-carrier first pass is returned as it stands) for a same-binary
1462        // attribution of a volume or census delta to this lane. Default (unset
1463        // or any other value) is unchanged. It does not touch the in-floor
1464        // tracking rungs or their raise rule, nor the range lane's end-span
1465        // challenger.
1466        if !standoff_tracking_enabled() {
1467            return Ok(best);
1468        }
1469        return standoff_tracking_rungs(surface, curve, domain, u_domain, v_domain, floor, joins,
1470            parameters, raw, pcurve, best, trace, call, &mut insert);
1471    }
1472    // Each target starts from the same baseline station set: retaining the
1473    // coarser target's inserts can exhaust the cap before the finer target
1474    // places its own error-directed stations. Keep the best rung
1475    // [`tracking_candidate_accepted`] takes.
1476    let baseline_parameters = parameters.clone();
1477    let baseline_raw = raw.clone();
1478    let baseline_curve = pcurve.clone();
1479    let baseline_off_surface = best.off_surface;
1480    let baseline_clamped = best.clamped;
1481    // Whether the first pass MISSED the floor: only then may a tracking
1482    // candidate that reaches the sample ceiling still missing its request take
1483    // the existing one-time raise (2026-10-04, 20-degree crossing, turn 295:
1484    // a 1.964e-6 first pass, a candidate at 600 samples reading 1.068e-7,
1485    // declined; the raise needed residual > off_surface + floor). A first pass
1486    // within the floor keeps exactly the work it did before.
1487    // (On this path the edge stands within the floor of the carrier, so a
1488    // first pass over the floor is a tracking miss, not inherited standoff.)
1489    let standing_misses = best.residual > floor;
1490    Ok(tracking_rungs(
1491        best,
1492        floor,
1493        trace,
1494        call,
1495        true,
1496        |fraction| {
1497            let mut refined_parameters = baseline_parameters.clone();
1498            let mut refined_raw = baseline_raw.clone();
1499            let mut refined_curve = baseline_curve.clone();
1500            let candidate = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain,
1501                floor, joins, &mut refined_parameters, &mut refined_raw, &mut refined_curve,
1502                baseline_off_surface, baseline_clamped, true, fraction, standing_misses, &mut insert, reject_bounds && !standing_misses);
1503            (candidate, (refined_parameters, refined_raw, refined_curve))
1504        },
1505        |state: &RungState| tracking_acceptance_residual(surface, curve, &state.2, &state.0, domain),
1506        |state: &RungState| state.0.len(),
1507        |(refined_parameters, refined_raw, refined_curve): RungState| {
1508            *parameters = refined_parameters;
1509            *raw = refined_raw;
1510            *pcurve = refined_curve;
1511        },
1512    ))
1513}
1514
1515/// A tracking candidate's station parameters, raw surface parameters and
1516/// pcurve, as [`refine_pcurve`] hands them to [`tracking_rungs`].
1517type RungState = (Vec<f64>, Vec<[f64; 2]>, NurbsCurve);
1518
1519/// The tracking rungs of [`refine_pcurve`] after an eligible first pass: for
1520/// each tracking fraction, skip it if the standing fit is already that far
1521/// inside the floor, otherwise run the candidate pass (`run_pass`), judge it
1522/// ([`judge_tracking_candidate`], reading `dense` only when needed), trace
1523/// it, and either take it (`adopt` its state; it becomes the standing fit) or
1524/// stop. `samples` is the candidate's station count, for the trace. Separated
1525/// so the accepted-budget state can be driven with scripted passes;
1526/// `thread_dense` is `true` in production and `false` only to show, in a
1527/// test, what dropping the nineteen-point standing flag would take.
1528#[allow(clippy::too_many_arguments)]
1529fn tracking_rungs<S>(
1530    mut best: Refinement,
1531    floor: f64,
1532    trace: bool,
1533    call: u64,
1534    thread_dense: bool,
1535    mut run_pass: impl FnMut(f64) -> (Result<Refinement, String>, S),
1536    mut dense: impl FnMut(&S) -> Result<f64, String>,
1537    samples: impl Fn(&S) -> usize,
1538    mut adopt: impl FnMut(S),
1539) -> Refinement {
1540    // Whether the standing reading is a nineteen-point one (a budget-exit
1541    // candidate was taken); every later candidate is then judged on it.
1542    let mut standing_dense = false;
1543    let reject_bounds = PCURVE_REJECT_BOUNDS.with(|state| state.get());
1544    for fraction in [0.1, 0.01] {
1545        if best.residual <= floor * fraction {
1546            if trace {
1547                eprintln!(
1548                    "PCURVE-TRACK call={call} candidate fraction={fraction} skipped best_residual={:e} <= {:e}",
1549                    best.residual,
1550                    floor * fraction
1551                );
1552            }
1553            continue;
1554        }
1555        let (candidate, state) = run_pass(fraction);
1556        // The reading the candidate is judged on and the decision (see
1557        // judge_tracking_candidate); an unreadable read declines like a
1558        // failed pass.
1559        let judged_dense = matches!(&candidate, Ok(seen) if seen.exit != PcurveFitExit::Converged || standing_dense);
1560        let (effective, accepted) = match &candidate {
1561            Ok(seen) => judge_tracking_candidate_with_bounds(best.residual, standing_dense, floor, seen.exit, seen.residual, || {
1562                dense(&state)
1563            }, reject_bounds),
1564            Err(_) => (Ok(None), false),
1565        };
1566        if trace {
1567            let judged_on = match &effective {
1568                Ok(Some(reading)) => format!("{reading:e}"),
1569                Ok(None) => "-".to_string(),
1570                Err(message) => format!("error:{message:?}"),
1571            };
1572            match &candidate {
1573                Ok(seen) => eprintln!(
1574                    "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={}",
1575                    seen.exit,
1576                    seen.residual,
1577                    seen.off_surface,
1578                    samples(&state),
1579                    seen.raised,
1580                    seen.residual <= floor,
1581                    if accepted { "accept" } else { "decline-stop" }
1582                ),
1583                Err(message) => eprintln!(
1584                    "PCURVE-TRACK call={call} candidate fraction={fraction} error={message:?} decision=decline-stop"
1585                ),
1586            }
1587        }
1588        match candidate {
1589            Ok(mut candidate) if accepted => {
1590                // Report the reading it was taken on (its own, if Converged).
1591                if let Ok(Some(reading)) = effective {
1592                    candidate.residual = reading;
1593                }
1594                // From here on the standing reading is a nineteen-point one.
1595                if thread_dense {
1596                    standing_dense |= judged_dense;
1597                }
1598                adopt(state);
1599                best = candidate;
1600            }
1601            _ => break,
1602        }
1603    }
1604    best
1605}
1606
1607/// Whether [`refine_pcurve`] takes [`standoff_tracking_rungs`] for an
1608/// off-carrier first pass: true unless `BREP_PCURVE_STANDOFF_TRACKING=0`
1609/// (diagnostic A/B hatch, read once per process).
1610fn standoff_tracking_enabled() -> bool {
1611    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
1612    *ON.get_or_init(|| std::env::var_os("BREP_PCURVE_STANDOFF_TRACKING").is_none_or(|value| value != "0"))
1613}
1614
1615/// The tracking rungs for an edge curve that stands OFF its carrier by more
1616/// than the floor ([`refine_pcurve`]). The first pass is read natively
1617/// ([`native_read`] on its own knot spans and endpoints); when its tracking is
1618/// within the floor, or the read fails, nothing more is done. Otherwise each
1619/// candidate pass (fractions 0.1 then 0.01 of the floor, from the same
1620/// baseline stations, taking the one-time raise when its own tracking target
1621/// is cut short by the ceiling) is read with the standing fit at the SAME
1622/// probes (both curves' native spans and endpoints) and taken only per
1623/// [`standoff_candidate_accepted`]: tracking finite, within the unchanged
1624/// floor and strictly lower, same-parameter deviation no worse, refinement
1625/// fields finite. A taken fit is REPORTED with its same-probe deviation
1626/// (inherited standoff included, so still over the floor) and with an
1627/// `off_surface` that is the larger of its station reading and the probes'
1628/// standoff. Any error, or a candidate that does not qualify, stops the loop
1629/// and keeps the standing curve and report.
1630#[allow(clippy::too_many_arguments)]
1631fn standoff_tracking_rungs(
1632    surface: &NurbsSurface,
1633    curve: &NurbsCurve,
1634    domain: [f64; 2],
1635    u_domain: [f64; 2],
1636    v_domain: [f64; 2],
1637    floor: f64,
1638    joins: &[f64],
1639    parameters: &mut Vec<f64>,
1640    raw: &mut Vec<[f64; 2]>,
1641    pcurve: &mut NurbsCurve,
1642    mut best: Refinement,
1643    trace: bool,
1644    call: u64,
1645    insert: &mut impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1646) -> Result<Refinement, String> {
1647    let first = native_probe_fractions(&[&*pcurve]).and_then(|probes| native_read(surface, curve, pcurve, domain, &probes));
1648    if trace {
1649        eprintln!("PCURVE-TRACK call={call} standoff-tracking first-pass native={first:?} floor={floor:e}");
1650    }
1651    let Ok(first) = first else { return Ok(best) };
1652    if first.tracking <= floor {
1653        return Ok(best);
1654    }
1655    let baseline_parameters = parameters.clone();
1656    let baseline_raw = raw.clone();
1657    let baseline_curve = pcurve.clone();
1658    for fraction in [0.1, 0.01] {
1659        let mut refined_parameters = baseline_parameters.clone();
1660        let mut refined_raw = baseline_raw.clone();
1661        let mut refined_curve = baseline_curve.clone();
1662        let candidate = refine_pcurve_pass(surface, curve, domain, u_domain, v_domain, floor, joins,
1663            &mut refined_parameters, &mut refined_raw, &mut refined_curve, best.off_surface, best.clamped,
1664            true, fraction, true, &mut *insert, false);
1665        let reads = candidate.as_ref().ok().map(|_| {
1666            native_probe_fractions(&[&*pcurve, &refined_curve]).and_then(|probes| {
1667                Ok((native_read(surface, curve, pcurve, domain, &probes)?, native_read(surface, curve, &refined_curve, domain, &probes)?))
1668            })
1669        });
1670        let fields_finite = matches!(&candidate, Ok(seen) if seen.residual.is_finite() && seen.off_surface.is_finite());
1671        let decision = match &reads {
1672            Some(Ok((standing, read))) => standoff_rung_decision(*standing, *read, fields_finite, floor),
1673            _ => RungDecision::Stop,
1674        };
1675        if trace {
1676            eprintln!(
1677                "PCURVE-TRACK call={call} standoff-tracking fraction={fraction} candidate={} reads={reads:?} decision={}",
1678                match &candidate { Ok(seen) => format!("{:?}/{:e}/raised={}", seen.exit, seen.residual, seen.raised), Err(message) => format!("error:{message:?}") },
1679                match decision { RungDecision::Accept => "accept", RungDecision::Continue => "decline-continue", RungDecision::Stop => "decline-stop" }
1680            );
1681        }
1682        let (Ok(mut taken), Some(Ok((_, read))), RungDecision::Accept) = (candidate, reads, decision) else {
1683            if decision == RungDecision::Continue {
1684                continue;
1685            }
1686            break;
1687        };
1688        taken.residual = read.deviation;
1689        taken.off_surface = taken.off_surface.max(read.standoff);
1690        *parameters = refined_parameters;
1691        *raw = refined_raw;
1692        *pcurve = refined_curve;
1693        best = taken;
1694        if read.tracking <= floor * 0.01 {
1695            break;
1696        }
1697    }
1698    Ok(best)
1699}
1700
1701/// What one off-carrier tracking rung does with its candidate
1702/// ([`standoff_tracking_rungs`]).
1703#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1704enum RungDecision {
1705    /// Taken ([`standoff_candidate_accepted`]).
1706    Accept,
1707    /// Not taken, but it read finite and LOWER tracking than the standing fit
1708    /// while over the floor: the finer fraction is still tried from the same
1709    /// baseline (fixture 25 on e90c30c94: one use read 2.33e-7 at 0.1 and
1710    /// stopped while its partner was taken at 9.0e-9).
1711    Continue,
1712    /// Not taken and not improving (or unreadable): the rungs end.
1713    Stop,
1714}
1715
1716fn standoff_rung_decision(standing: NativeRead, candidate: NativeRead, fields_finite: bool, floor: f64) -> RungDecision {
1717    if standoff_candidate_accepted(standing, candidate, fields_finite, floor) {
1718        RungDecision::Accept
1719    } else if candidate.tracking.is_finite() && candidate.tracking < standing.tracking {
1720        RungDecision::Continue
1721    } else {
1722        RungDecision::Stop
1723    }
1724}
1725
1726/// The one-time raise decision of [`refine_pcurve_pass`]: a ceiling exit not
1727/// yet raised, when the returned curve is worse than the edge's own gap by
1728/// more than the floor (the original rule), or when a tracking pass for an
1729/// unmet first pass returned a curve whose own tracking still misses the
1730/// pass's target (`unmet_tracking`, read on the returned curve). Nothing else
1731/// raises.
1732fn takes_raise(exit: PcurveFitExit, raised: bool, residual: f64, off_surface: f64, floor: f64, unmet_tracking: bool) -> bool {
1733    exit == PcurveFitExit::SampleCeiling && !raised && (residual > off_surface + floor || unmet_tracking)
1734}
1735
1736fn refine_pcurve_pass(
1737    surface: &NurbsSurface,
1738    curve: &NurbsCurve,
1739    [t0, t1]: [f64; 2],
1740    [u0, u1]: [f64; 2],
1741    [v0, v1]: [f64; 2],
1742    floor: f64,
1743    joins: &[f64],
1744    parameters: &mut Vec<f64>,
1745    raw: &mut Vec<[f64; 2]>,
1746    pcurve: &mut NurbsCurve,
1747    mut off_surface: f64,
1748    mut clamped: [f64; 2],
1749    track_projection: bool,
1750    tracking_fraction: f64,
1751    raise_unmet_tracking: bool,
1752    mut insert: impl FnMut(f64, Vec3, Vec3) -> Result<(Option<[f64; 2]>, f64), String>,
1753    reject_budget: bool,
1754) -> Result<Refinement, String> {
1755    let _clock = PcurvePhaseClock::new("refinement", parameters.len(), track_projection);
1756    let tracking_floor = if track_projection { floor * tracking_fraction } else { floor };
1757    let mut max_samples = MAX_PCURVE_SAMPLES;
1758    let mut raised = false;
1759    loop {
1760        // Every way out of this loop is CLASSIFIED (`PcurveFitExit`); a budget
1761        // exit returns the curve it built, but says so. Falling off the end
1762        // after a fourth round of inserts is the round-budget exit.
1763        let mut exit = PcurveFitExit::RoundBudget;
1764        let mut residual = None;
1765        for round in 0..4 {
1766            if parameters.len() >= max_samples {
1767                exit = PcurveFitExit::SampleCeiling;
1768                break;
1769            }
1770            let mut inserts = Vec::new();
1771            let mut round_max = 0.0_f64;
1772            let mut truncated = false;
1773            let mut skipped_narrow = false;
1774            for index in 0..parameters.len() - 1 {
1775                if parameters.len() + inserts.len() >= max_samples {
1776                    truncated = true;
1777                    break;
1778                }
1779                let start = parameters[index];
1780                let end = parameters[index + 1];
1781                // Keep construction's existing first-pass policy. Extended
1782                // residual probes must not silently change its station ladder;
1783                // projection tracking retains its established finer floor.
1784                if end - start < if track_projection { SPAN_FLOOR } else { 1e-3 } {
1785                    skipped_narrow = true;
1786                    continue;
1787                }
1788                for local_fraction in [0.25, 0.5, 0.75] {
1789                    if parameters.len() + inserts.len() >= max_samples {
1790                        truncated = true;
1791                        break;
1792                    }
1793                    let fraction = start + (end - start) * local_fraction;
1794                    let parameter = pcurve.evaluate(fraction)?;
1795                    let on_surface =
1796                        section_surface_point(surface, parameter.x, parameter.y, true)?;
1797                    let on_curve = section_curve_point(curve, t0 + (t1 - t0) * fraction)?;
1798                    let deviation = on_surface.sub(on_curve).length();
1799                    // A non-finite distance must not reach `f64::max` (which
1800                    // drops NaN) or the classification below, where a round
1801                    // with an unreadable station could still exit Converged on
1802                    // its readable ones. Fail closed: a first pass's error
1803                    // goes to its caller, a tracking candidate's declines it.
1804                    if !deviation.is_finite() {
1805                        return Err(format!(
1806                            "refine_pcurve_pass: non-finite station distance {deviation} at fraction {fraction}"
1807                        ));
1808                    }
1809                    round_max = round_max.max(deviation);
1810                    if deviation <= tracking_floor {
1811                        continue;
1812                    }
1813                    let (surface_parameter, gap) = insert(fraction, parameter, on_curve)?;
1814                    off_surface = off_surface.max(gap);
1815                    if let Some(surface_parameter) = surface_parameter {
1816                        // The raised pass stops where the pcurve TRACKS the
1817                        // edge curve's projection to the floor — the best any
1818                        // pcurve can do at this station. Not `deviation - gap`:
1819                        // a surface point at tangential distance d from the
1820                        // projection of a point g off the surface is only
1821                        // d^2/(2g) further from it, so the deviation test is
1822                        // quadratically blind to sideways error on off-surface
1823                        // input (6e-6 of slop at g = 1.9e-4, floor 1e-7).
1824                        if raised || track_projection {
1825                            let projected =
1826                                section_surface_point(surface, surface_parameter[0], surface_parameter[1], false)?;
1827                            if on_surface.sub(projected).length() <= tracking_floor {
1828                                continue;
1829                            }
1830                        }
1831                        inserts.push((index + 1, fraction, surface_parameter));
1832                    }
1833                }
1834            }
1835            if inserts.is_empty() {
1836                // Nothing to insert: every probed station is within the floor
1837                // (converged — unless a narrow span was skipped, in which case
1838                // the sweep below decides), or the ones over it could not be
1839                // improved (stalled — the edge curve is off the surface there).
1840                exit = if truncated {
1841                    PcurveFitExit::SampleCeiling
1842                } else if round_max > floor {
1843                    PcurveFitExit::Stalled
1844                } else if skipped_narrow {
1845                    PcurveFitExit::SpanFloor
1846                } else {
1847                    residual = Some(round_max);
1848                    PcurveFitExit::Converged
1849                };
1850                break;
1851            }
1852            // With inserts still needed after the fourth non-truncated
1853            // round, this exit is RoundBudget. An in-floor standing fit
1854            // never adopts any budget exit; rebuilding and probing this
1855            // discarded candidate cannot affect its curve or report.
1856            if reject_budget && round == 3 && !truncated {
1857                if std::env::var_os("BREP_PROFILE").is_some() { eprintln!("pcurve.reject_bound kind=fifth_round"); }
1858                return Err("pcurve tracking candidate requires a fifth round".into());
1859            }
1860            for (at, fraction, surface_parameter) in inserts.into_iter().rev() {
1861                parameters.insert(at, fraction);
1862                raw.insert(at, surface_parameter);
1863            }
1864            let (rebuilt, excursion, distance) = build_interpolant_joined(surface, raw, parameters, joins)?;
1865            *pcurve = rebuilt;
1866            clamped = [excursion, distance];
1867            if truncated {
1868                exit = PcurveFitExit::SampleCeiling;
1869                break;
1870            }
1871        }
1872        let residual = match residual {
1873            Some(measured) => measured,
1874            // A budget exit never re-checked the curve it is returning, and a
1875            // converged round that skipped narrow spans never checked those:
1876            // measure every span.
1877            None => probe_residual(
1878                surface,
1879                curve,
1880                pcurve,
1881                parameters,
1882                [t0, t1],
1883                [u0, u1],
1884                [v0, v1],
1885            )?,
1886        };
1887        if exit == PcurveFitExit::SpanFloor && residual <= floor {
1888            exit = PcurveFitExit::Converged;
1889        }
1890        // The per-trim budget decision. Deterministic, grow-once, capped (I3):
1891        // the ceiling bound and the returned curve is worse than the edge
1892        // curve's own gap from the surface by more than the floor, so samples
1893        // can still buy accuracy. A curve already at its gap stops here —
1894        // reported, not retried.
1895        // A TRACKING pass for a standing fit that missed the floor (and only
1896        // then) also takes the same one-time raise when it hits the ceiling
1897        // still over the floor: its request is the projection's tracking, and
1898        // the ceiling cut it short. The raised maximum itself is unchanged.
1899        // The added raise serves a TRACKING pass for an unmet first pass whose
1900        // RETURNED curve still misses the pass's own target: its tracking (the
1901        // image against the projected foot, read natively on its own knot spans
1902        // and endpoints) over the tracking floor (floor x fraction). Reaching
1903        // the ceiling alone is exhaustion, not a miss, and the inherited
1904        // standoff never triggers it. Read only at a ceiling exit not yet
1905        // raised; an unreadable read does not raise.
1906        let unmet_tracking = track_projection
1907            && raise_unmet_tracking
1908            && exit == PcurveFitExit::SampleCeiling
1909            && !raised
1910            && native_probe_fractions(&[&*pcurve])
1911                .and_then(|probes| native_read(surface, curve, pcurve, [t0, t1], &probes))
1912                .is_ok_and(|read| read.tracking > tracking_floor);
1913        if takes_raise(exit, raised, residual, off_surface, floor, unmet_tracking) {
1914            raised = true;
1915            max_samples = PCURVE_RAISED_SAMPLES;
1916            continue;
1917        }
1918        return Ok(Refinement {
1919            exit,
1920            residual,
1921            off_surface,
1922            raised,
1923            clamped,
1924        });
1925    }
1926}
1927
1928/// The exact inverse of an affine carrier's parameterization.
1929///
1930/// An affine patch (2x2 net, degree 1 both ways, equal weights) maps `uv` to 3D
1931/// by an affine map, so the inverse — a 3D point to the `uv` of its orthogonal
1932/// projection — is affine too. An affine map commutes with the rational basis:
1933/// sending a curve's control points through it and keeping the weights
1934/// produces the EXACT image of that curve in parameter space, not a fit of it.
1935struct AffineInversion {
1936    origin: Vec3,
1937    du: Vec3,
1938    dv: Vec3,
1939    u0: f64,
1940    v0: f64,
1941    uu: f64,
1942    uv: f64,
1943    vv: f64,
1944    determinant: f64,
1945}
1946
1947impl AffineInversion {
1948    /// `None` when `surface` is not affine, or when its two directions are
1949    /// parallel enough that the inverse is not determined. The caller decides
1950    /// what that means: a refusal on the whole-curve lane, the sampled lane on
1951    /// the range lane.
1952    fn of(surface: &NurbsSurface) -> Result<Option<Self>, String> {
1953        if !surface.is_affine()? {
1954            return Ok(None);
1955        }
1956        let ([u0, _], [v0, _]) = surface_domains(surface)?;
1957        let (origin, du, dv) = surface.deriv1(u0, v0)?;
1958        let uu = du.dot(du);
1959        let uv = du.dot(dv);
1960        let vv = dv.dot(dv);
1961        let determinant = uu * vv - uv * uv;
1962        if determinant.abs() <= 1e-18 {
1963            return Ok(None);
1964        }
1965        Ok(Some(Self {
1966            origin,
1967            du,
1968            dv,
1969            u0,
1970            v0,
1971            uu,
1972            uv,
1973            vv,
1974            determinant,
1975        }))
1976    }
1977
1978    fn uv_of(&self, point: Vec3) -> [f64; 2] {
1979        let delta = point.sub(self.origin);
1980        let along_u = delta.dot(self.du);
1981        let along_v = delta.dot(self.dv);
1982        [
1983            self.u0 + (along_u * self.vv - along_v * self.uv) / self.determinant,
1984            self.v0 + (along_v * self.uu - along_u * self.uv) / self.determinant,
1985        ]
1986    }
1987
1988    /// The exact image of `curve` in this carrier's parameter space, with the
1989    /// curve's own degree, knots and weights.
1990    fn image_of(&self, curve: &NurbsCurve) -> Result<NurbsCurve, String> {
1991        let control_points = curve
1992            .control_points
1993            .iter()
1994            .map(|control| {
1995                let [u, v] = self.uv_of(control.point()?);
1996                Ok(Vec4::from_point(Vec3::new(u, v, 0.0), control.w))
1997            })
1998            .collect::<Result<Vec<_>, String>>()?;
1999        NurbsCurve::new(curve.degree, curve.knots.clone(), control_points)
2000    }
2001}
2002
2003/// Build a parameter-space curve for a 3D curve lying on a surface, and say
2004/// what the fit achieved.
2005///
2006/// This mirrors the reference imprint implementation: affine patches map
2007/// homogeneous control points exactly; general patches use sampled inversion,
2008/// periodic seam unwrapping, and adaptive 3D residual refinement. The report
2009/// beside the curve carries the residual the RETURNED curve reaches and why
2010/// refinement stopped ([`PcurveFitReport`]); the curve itself is what
2011/// [`build_pcurve_on_surface`] has always returned.
2012pub fn fit_pcurve_on_surface(
2013    surface: &NurbsSurface,
2014    curve: &NurbsCurve,
2015) -> Result<PcurveFit, String> {
2016    let mode = std::env::var("BREP_PCURVE_EVAL_CACHE").unwrap_or_default();
2017    let bounds = std::env::var("BREP_PCURVE_REJECT_BOUNDS").unwrap_or_else(|_| "on".into());
2018    let stack = std::env::var("BREP_PCURVE_STACK_POINT").unwrap_or_else(|_| "on".into());
2019    if mode == "check" || bounds == "check" || stack == "check" {
2020        let old = fit_pcurve_on_surface_cached(surface, curve, false, false, false)?;
2021        if matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })) {
2022            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");
2023            let identical = candidate.as_ref().is_ok_and(|new| {
2024                old.curve.degree == new.curve.degree
2025                    && old.curve.knots.len() == new.curve.knots.len()
2026                    && old.curve.knots.iter().zip(&new.curve.knots).all(|(a, b)| a.to_bits() == b.to_bits())
2027                    && old.curve.control_points.len() == new.curve.control_points.len()
2028                    && old.curve.control_points.iter().zip(&new.curve.control_points).all(|(a, b)| {
2029                        [a.x.to_bits(), a.y.to_bits(), a.z.to_bits(), a.w.to_bits()]
2030                            == [b.x.to_bits(), b.y.to_bits(), b.z.to_bits(), b.w.to_bits()]
2031                    }) && old.report == new.report
2032            });
2033            if let Ok(path) = std::env::var("BREP_PCURVE_EVAL_CENSUS") {
2034                use std::io::Write;
2035                if let Ok(mut file) = std::fs::OpenOptions::new().create(true).append(true).open(path) {
2036                    let _ = writeln!(file, "pcurve.eval_census identical={identical} controls={} samples={}", old.curve.control_points.len(), old.report.samples);
2037                }
2038            }
2039        }
2040        return Ok(old);
2041    }
2042    fit_pcurve_on_surface_cached(surface, curve, mode == "1" || mode == "on", bounds == "1" || bounds == "on", stack == "1" || stack == "on")
2043}
2044
2045fn fit_pcurve_on_surface_cached(surface: &NurbsSurface, curve: &NurbsCurve, enabled: bool, bounds: bool, stack: bool) -> Result<PcurveFit, String> {
2046    let _stack = PcurveStackPointScope::open(stack && matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })));
2047    let _samples = PcurveSampleScope::open(surface, curve, enabled);
2048    let _bounds = PcurveRejectScope::open(bounds && matches!(surface.analytic(), Some(AnalyticSurface::Sphere { .. })));
2049    let [t0, t1] = curve.domain()?;
2050    if surface.is_affine()? {
2051        let Some(inversion) = AffineInversion::of(surface)? else {
2052            return Err("build_pcurve_on_surface: singular affine parameterization".into());
2053        };
2054        let pcurve = inversion.image_of(curve)?;
2055        return Ok(PcurveFit {
2056            report: PcurveFitReport {
2057                residual: 0.0,
2058                floor: PCURVE_REFINEMENT_TOLERANCE,
2059                samples: pcurve.control_points.len(),
2060                exit: PcurveFitExit::Converged,
2061                off_surface: 0.0,
2062                raised: false,
2063                clamped_excursion: 0.0,
2064                clamped_distance: 0.0,
2065            },
2066            curve: pcurve,
2067        });
2068    }
2069
2070    let scale = 1.0 + curve.evaluate((t0 + t1) / 2.0)?.length();
2071    let drop_tolerance = 1e-4 * scale;
2072    let endpoint_tolerance = 1e-3 * scale;
2073    let refinement_tolerance = PCURVE_REFINEMENT_TOLERANCE;
2074    let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2075    let invert =
2076        |fraction: f64| invert_checked(surface, section_curve_point(curve, t0 + (t1 - t0) * fraction)?);
2077
2078    let mut parameters = Vec::with_capacity(25);
2079    let mut raw_surface_parameters = Vec::with_capacity(25);
2080    // The edge curve's own distance from the surface at every station inverted,
2081    // accepted or not: the floor below which no pcurve can bring the residual.
2082    let mut off_surface = 0.0_f64;
2083    // The edge's own C0 knots must remain corners of its parameter image.
2084    // Plant those stations before inversion; refinement retains their joins.
2085    let corners = range_breaks(curve, t0, t1, true);
2086    let mut stations: Vec<f64> = (0..=24).map(|index| index as f64 / 24.0).collect();
2087    // Replace nearby uniform seeds, never the native corner itself. Keep
2088    // endpoints and other native corners even when their spans are short.
2089    stations.retain(|station| {
2090        *station == 0.0 || *station == 1.0 || corners.contains(station)
2091            || !corners.iter().any(|corner| (*station - corner).abs() <= SPAN_FLOOR)
2092    });
2093    for &corner in &corners {
2094        let at = stations.partition_point(|value| *value < corner);
2095        if stations.get(at) != Some(&corner) {
2096            stations.insert(at, corner);
2097        }
2098    }
2099    let joins = corners;
2100    for (index, &fraction) in stations.iter().enumerate() {
2101        let (parameter, distance) = invert(fraction)?;
2102        off_surface = off_surface.max(distance);
2103        if distance > drop_tolerance && index != 0 && index != stations.len() - 1 {
2104            continue;
2105        }
2106        if distance > endpoint_tolerance {
2107            if std::env::var("BREP_DEBUG_PCURVE").is_ok() {
2108                let p3 = curve.evaluate(t0 + (t1 - t0) * fraction).ok();
2109                let p0 = curve.evaluate(t0).ok();
2110                let p1 = curve.evaluate(t1).ok();
2111                eprintln!(
2112                    "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={:?}",
2113                    surface.evaluate(parameter[0], parameter[1]).ok()
2114                );
2115            }
2116            return Err(format!(
2117                "build_pcurve_on_surface: endpoint projection failed (distance={distance})"
2118            ));
2119        }
2120        parameters.push(fraction);
2121        raw_surface_parameters.push(parameter);
2122    }
2123
2124    let (mut pcurve, excursion, distance) =
2125        build_interpolant_joined(surface, &raw_surface_parameters, &parameters, &joins)?;
2126    let refinement = refine_pcurve(
2127        surface,
2128        curve,
2129        [t0, t1],
2130        [u0, u1],
2131        [v0, v1],
2132        refinement_tolerance,
2133        &joins,
2134        &mut parameters,
2135        &mut raw_surface_parameters,
2136        &mut pcurve,
2137        off_surface,
2138        [excursion, distance],
2139        |fraction, _parameter, _on_curve| {
2140            let (surface_parameter, distance) = invert(fraction)?;
2141            Ok((
2142                (distance <= drop_tolerance).then_some(surface_parameter),
2143                distance,
2144            ))
2145        },
2146    )?;
2147    Ok(PcurveFit {
2148        curve: pcurve,
2149        report: PcurveFitReport {
2150            residual: refinement.residual,
2151            floor: refinement_tolerance,
2152            samples: parameters.len(),
2153            exit: refinement.exit,
2154            off_surface: refinement.off_surface,
2155            raised: refinement.raised,
2156            clamped_excursion: refinement.clamped[0],
2157            clamped_distance: refinement.clamped[1],
2158        },
2159    })
2160}
2161
2162/// [`fit_pcurve_on_surface`] for the callers that only need the curve. The
2163/// report is not dropped: it is tallied on the open [`PcurveFitScope`], if any,
2164/// so the operation that owns this fit can say in its diagnostics whether every
2165/// trim reached the floor.
2166pub fn build_pcurve_on_surface(
2167    surface: &NurbsSurface,
2168    curve: &NurbsCurve,
2169) -> Result<NurbsCurve, String> {
2170    let fit = fit_pcurve_on_surface(surface, curve)?;
2171    record_fit(&fit.report);
2172    Ok(fit.curve)
2173}
2174
2175/// Optional section-fit clock; records every early fallback without changing it.
2176struct SectionFitClock {
2177    started: Option<web_time::Instant>,
2178    global: std::time::Duration,
2179    seeded: bool,
2180}
2181impl SectionFitClock {
2182    fn new() -> Self {
2183        Self { started: std::env::var_os("BREP_PROFILE").is_some().then(web_time::Instant::now),
2184            global: std::time::Duration::ZERO, seeded: false }
2185    }
2186}
2187impl Drop for SectionFitClock {
2188    fn drop(&mut self) {
2189        if let Some(started) = self.started {
2190            eprintln!("pcurve.section_time global={:.3} seeded={:.3} result={}",
2191                self.global.as_secs_f64() * 1000.0,
2192                started.elapsed().saturating_sub(self.global).as_secs_f64() * 1000.0,
2193                if self.seeded { "seeded" } else { "global" });
2194        }
2195    }
2196}
2197
2198/// SECTION-PCURVE SEEDED MARCH (t222: cone × ABC 00000327, non-integral genus).
2199///
2200/// `build_pcurve_on_surface` inverts every sample by GLOBAL closest point. Where
2201/// the carrier surface is COMPRESSED / self-overlapping along the row the
2202/// section rides, the global search aliases interior samples onto a DISTANT
2203/// preimage sheet, folding the pcurve out past the trim boundary and re-crossing
2204/// it. The arrangement then splits the shared section at that phantom crossing,
2205/// while the mate face (whose carrier is not folded there) keeps the section
2206/// whole — so the two operands' fragments disagree and the section strands
2207/// one-use (non-integral genus). Ground truth for t222: 00000327 face 496's
2208/// v≈0.7875 row maps u∈[0.55,0.81] into a ~0.18mm neighbourhood of the section
2209/// endpoint A; the global pcurve for piece 9 folded out to u=0.806 and back,
2210/// re-crossing trim edge 349 at v≈0.784, 0.003 below the corner vertex A.
2211///
2212/// This marches the interior inversions with each seeded from the PREVIOUS
2213/// accepted parameters, so a marched sample
2214/// adopts the nearby branch instead of the momentarily-closest distant sheet.
2215/// The two ENDPOINT samples keep the deterministic global inversion (they are
2216/// the piece's shared junction vertices — same reasoning as
2217/// `repair_branch_jumps`). Additive + fail-soft: the marched chain is used ONLY
2218/// when it CLOSES onto the global far endpoint (its last interior sample is
2219/// parameter-adjacent to it, measured against the chain's own median step);
2220/// otherwise the plain global build is returned byte-for-byte. A single-preimage
2221/// carrier (the cone side of the same section) marches to the same samples the
2222/// global search already had. Use the analytic-aware seeded projector for both
2223/// the march and inserted stations: raw Newton stops at 1e-7 even on an exact
2224/// cylinder, introducing avoidable trim error. General folded carriers retain
2225/// their local seeded Newton path; analytic carriers take their closed form.
2226///
2227/// Escape hatch: `BREP_SECTION_PCURVE_MARCH=0`.
2228pub fn fit_pcurve_on_surface_marched(
2229    surface: &NurbsSurface,
2230    curve: &NurbsCurve,
2231) -> Result<PcurveFit, String> {
2232    fn run(surface: &NurbsSurface, curve: &NurbsCurve, eager: bool) -> Result<PcurveFit, String> {
2233        let mut clock = SectionFitClock::new();
2234        // The global builder owns only scoped sample caches. Its fit/report is
2235        // discarded on a successful seeded route; do that work on fallback only.
2236        // Profile phase/sample lines for the discarded global fit disappear ON.
2237        let mut fallback = || {
2238            let started = clock.started.map(|_| web_time::Instant::now());
2239            let fit = fit_pcurve_on_surface(surface, curve);
2240            if let Some(started) = started { clock.global += started.elapsed(); }
2241            fit
2242        };
2243        let global = if eager { Some(fallback()?) } else { None };
2244        // The global builder's first fallible geometry read validates the
2245        // curve domain. Preserve that error priority before the affine probe
2246        // when the unused global fit is deferred (both inputs may be invalid).
2247        if !eager { curve.domain()?; }
2248        if std::env::var("BREP_SECTION_PCURVE_MARCH").as_deref() == Ok("0") || surface.is_affine()? {
2249            return global.map_or_else(&mut fallback, Ok);
2250        }
2251        let [t0, t1] = curve.domain()?;
2252        // A closed (ring) section has no distinct endpoints to anchor the march;
2253        // leave it to the existing path (closed rings are handled elsewhere).
2254        if curve.evaluate(t0)?.sub(curve.evaluate(t1)?).length() <= 1e-6 {
2255            return global.map_or_else(&mut fallback, Ok);
2256        }
2257        const SAMPLES: usize = 24;
2258        let fractions: Vec<f64> = (0..=SAMPLES).map(|i| i as f64 / SAMPLES as f64).collect();
2259        let edge: Vec<Vec3> = fractions
2260            .iter()
2261            .map(|fraction| curve.evaluate(t0 + (t1 - t0) * fraction))
2262            .collect::<Result<Vec<_>, _>>()?;
2263        let scale = 1.0 + curve.evaluate((t0 + t1) / 2.0)?.length();
2264        let endpoint_tolerance = 1e-3 * scale;
2265        let (first, first_distance) = invert_checked(surface, edge[0])?;
2266        let (last, last_distance) = invert_checked(surface, edge[SAMPLES])?;
2267        if first_distance > endpoint_tolerance || last_distance > endpoint_tolerance {
2268            return global.map_or_else(&mut fallback, Ok);
2269        }
2270        // The edge curve's distance from the surface at every station this chain
2271        // inverts — on the MARCHED branch, which is the one being fitted.
2272        let mut off_surface = first_distance.max(last_distance);
2273        let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2274        let u_span = (u1 - u0).abs().max(EPSILON);
2275        let v_span = (v1 - v0).abs().max(EPSILON);
2276        let (closed_u, closed_v) = surface_closedness(surface)?;
2277        let norm_step = |a: [f64; 2], b: [f64; 2]| -> f64 {
2278            let mut du = a[0] - b[0];
2279            if closed_u {
2280                while du > 0.5 * u_span {
2281                    du -= u_span;
2282                }
2283                while du < -0.5 * u_span {
2284                    du += u_span;
2285                }
2286            }
2287            let mut dv = a[1] - b[1];
2288            if closed_v {
2289                while dv > 0.5 * v_span {
2290                    dv -= v_span;
2291                }
2292                while dv < -0.5 * v_span {
2293                    dv += v_span;
2294                }
2295            }
2296            ((du / u_span).powi(2) + (dv / v_span).powi(2)).sqrt()
2297        };
2298        // Forward seeded march over the interior samples.
2299        let mut raw = vec![first];
2300        let mut previous = first;
2301        for index in 1..SAMPLES {
2302            let seeded =
2303                crate::projection::project_point_to_surface_from_seed(surface, edge[index], previous)?;
2304            let (_, global_distance) = invert_checked(surface, edge[index])?;
2305            // The seeded footpoint must still sit on the surface — as tight as the
2306            // fit band or the global answer already had it. If it fell off (the
2307            // seed led Newton into a valley), abandon the march and keep global.
2308            if seeded.distance > 4.0 * global_distance + endpoint_tolerance {
2309                return global.map_or_else(&mut fallback, Ok);
2310            }
2311            off_surface = off_surface.max(seeded.distance);
2312            previous = [seeded.u, seeded.v];
2313            raw.push(previous);
2314        }
2315        raw.push(last);
2316        // CLOSURE GATE: the last marched interior sample must be parameter-adjacent
2317        // to the global far endpoint — the march stayed on ONE branch the whole way.
2318        // Measure the endpoint gap against the chain's OWN median step so a genuine
2319        // long edge is not rejected while a sheet-hop (which leaves a big gap to the
2320        // endpoint) is.
2321        let mut steps: Vec<f64> = (1..raw.len())
2322            .map(|i| norm_step(raw[i], raw[i - 1]))
2323            .collect();
2324        let endpoint_gap = steps.pop().unwrap_or(0.0);
2325        steps.sort_by(f64::total_cmp);
2326        let median = steps
2327            .get(steps.len() / 2)
2328            .copied()
2329            .unwrap_or(0.0)
2330            .max(EPSILON);
2331        if endpoint_gap > (4.0 * median).max(0.05) {
2332            return global.map_or_else(&mut fallback, Ok);
2333        }
2334        // Build the interpolant from the marched samples, then refine — re-projecting
2335        // each insert SEEDED from the interpolant (already on the marched branch), so
2336        // a mid-refinement global inversion cannot re-alias onto the far sheet.
2337        let mut parameters = fractions;
2338        let (mut pcurve, excursion, distance) = build_interpolant(surface, &raw, &parameters)?;
2339        let refinement_tolerance = PCURVE_REFINEMENT_TOLERANCE;
2340        // Same classified exits and budget ladder as `fit_pcurve_on_surface`. A
2341        // seeded insert always lands, so this loop cannot stall.
2342        let refinement = refine_pcurve(
2343            surface,
2344            curve,
2345            [t0, t1],
2346            [u0, u1],
2347            [v0, v1],
2348            refinement_tolerance,
2349            &[],
2350            &mut parameters,
2351            &mut raw,
2352            &mut pcurve,
2353            off_surface,
2354            [excursion, distance],
2355            |_fraction, seed, on_curve| {
2356                let seeded = crate::projection::project_point_to_surface_from_seed(surface, on_curve, [seed.x, seed.y])?;
2357                Ok((Some([seeded.u, seeded.v]), seeded.distance))
2358            },
2359        )?;
2360        clock.seeded = true;
2361        Ok(PcurveFit {
2362            curve: pcurve,
2363            report: PcurveFitReport {
2364                residual: refinement.residual,
2365                floor: refinement_tolerance,
2366                samples: parameters.len(),
2367                exit: refinement.exit,
2368                off_surface: refinement.off_surface,
2369                raised: refinement.raised,
2370                clamped_excursion: refinement.clamped[0],
2371                clamped_distance: refinement.clamped[1],
2372            },
2373        })
2374    }
2375
2376    let mode = match std::env::var("BREP_PCURVE_LAZY_GLOBAL") {
2377        Ok(mode) => mode,
2378        Err(std::env::VarError::NotPresent) => "on".to_owned(),
2379        Err(std::env::VarError::NotUnicode(_)) => String::new(),
2380    };
2381    if mode != "check" {
2382        return run(surface, curve, !matches!(mode.as_str(), "1" | "on"));
2383    }
2384    // Clone BEFORE eager evaluation: lazy must start with the same carrier
2385    // cache state, rather than benefiting from eager's recognition/projection.
2386    let lazy_surface = surface.clone();
2387    let lazy_curve = curve.clone();
2388    let eager = run(surface, curve, true);
2389    let lazy = run(&lazy_surface, &lazy_curve, false);
2390    let identical = match (&eager, &lazy) {
2391        (Ok(a), Ok(b)) => {
2392            a.curve.degree == b.curve.degree
2393                && a.curve.knots.len() == b.curve.knots.len()
2394                && a.curve.knots.iter().zip(&b.curve.knots).all(|(a,b)| a.to_bits() == b.to_bits())
2395                && a.curve.control_points.len() == b.curve.control_points.len()
2396                && a.curve.control_points.iter().zip(&b.curve.control_points).all(|(a,b)| {
2397                    [a.x.to_bits(),a.y.to_bits(),a.z.to_bits(),a.w.to_bits()]
2398                        == [b.x.to_bits(),b.y.to_bits(),b.z.to_bits(),b.w.to_bits()]
2399                })
2400                && a.report == b.report
2401                && [a.report.residual, a.report.floor, a.report.off_surface,
2402                    a.report.clamped_excursion, a.report.clamped_distance].map(f64::to_bits)
2403                    == [b.report.residual, b.report.floor, b.report.off_surface,
2404                        b.report.clamped_excursion, b.report.clamped_distance].map(f64::to_bits)
2405        }
2406        (Err(a), Err(b)) => a == b,
2407        _ => false,
2408    };
2409    if let Ok(path) = std::env::var("BREP_PCURVE_LAZY_GLOBAL_CENSUS") {
2410        use std::io::Write;
2411        let mut file = std::fs::OpenOptions::new().create(true).append(true).open(path)
2412            .expect("open lazy-global differential ledger");
2413        writeln!(file, "pcurve.lazy_global identical={identical} eager_ok={} lazy_ok={} degree={} controls={}",
2414            eager.is_ok(), lazy.is_ok(), curve.degree, curve.control_points.len())
2415            .expect("append lazy-global differential ledger");
2416    }
2417    assert!(identical, "lazy global pcurve fallback changed the curve, report or error");
2418    eager
2419}
2420
2421/// [`fit_pcurve_on_surface_marched`] for the callers that only need the curve;
2422/// the report is tallied on the open [`PcurveFitScope`] exactly as
2423/// [`build_pcurve_on_surface`] does.
2424pub fn build_pcurve_on_surface_marched(
2425    surface: &NurbsSurface,
2426    curve: &NurbsCurve,
2427) -> Result<NurbsCurve, String> {
2428    let fit = fit_pcurve_on_surface_marched(surface, curve)?;
2429    record_fit(&fit.report);
2430    Ok(fit.curve)
2431}
2432
2433/// Build a pcurve for a represented subrange of a larger edge curve.
2434///
2435/// On an affine carrier the answer is exact and is taken as such
2436/// (`affine_pcurve_on_range`). Otherwise this samples only the represented
2437/// interval, which is essential when off-interval control points do not lie on
2438/// the target carrier — the exact lane restricts the net by knot insertion
2439/// first, so those control points are removed rather than ignored.
2440pub fn fit_pcurve_on_surface_range(
2441    surface: &NurbsSurface,
2442    curve: &NurbsCurve,
2443    edge_start: f64,
2444    edge_end: f64,
2445    forward: bool,
2446    tolerance: f64,
2447) -> Result<PcurveFit, String> {
2448    if let Some(exact) =
2449        affine_pcurve_on_range(surface, curve, edge_start, edge_end, forward, tolerance)?
2450    {
2451        return Ok(exact);
2452    }
2453    fit_pcurve_on_surface_range_dense(
2454        surface, curve, edge_start, edge_end, forward, tolerance, 64, 3, 513,
2455    )
2456}
2457
2458/// [`fit_pcurve_on_surface_range`] for the callers that only need the curve:
2459/// the fit is ACCEPTED or REFUSED on its bar (`accept_fit`), never returned
2460/// off it.
2461pub fn build_pcurve_on_surface_range(
2462    surface: &NurbsSurface,
2463    curve: &NurbsCurve,
2464    edge_start: f64,
2465    edge_end: f64,
2466    forward: bool,
2467    tolerance: f64,
2468) -> Result<NurbsCurve, String> {
2469    accept_fit(fit_pcurve_on_surface_range(
2470        surface, curve, edge_start, edge_end, forward, tolerance,
2471    )?)
2472}
2473
2474/// `BREP_DEBUG_STATION_FIT`: trace every station fit round by round, and the
2475/// stations around the worst span of a fit off its bar. Read once per process.
2476fn station_fit_tracing() -> bool {
2477    static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
2478    *ON.get_or_init(|| std::env::var_os("BREP_DEBUG_STATION_FIT").is_some())
2479}
2480
2481/// Narrowest span, as a fraction of the parameter range, that
2482/// [`fit_pcurve_on_surface_stations`] subdivides. `refine_pcurve` floors at
2483/// 1e-3 from 25 base samples; this fitter starts from 64 and quarters, so a
2484/// floor of 1e-3 bound on its first pass and refused 67 of the 57-document
2485/// corpus's bodies (measured 2026-09-26). 1e-6 admits every halving a real
2486/// trim needs and stops the runaway that fits stations 4e-7 apart.
2487const SPAN_FLOOR: f64 = 1e-6;
2488
2489/// Rounds the raised pass of [`fit_pcurve_on_surface_stations`] may spend:
2490/// enough halvings for any span the sample cap can resolve.
2491const RAISED_ROUNDS: usize = 40;
2492
2493/// The refusal every station builder returns for a fit off its bar.
2494pub const PCURVE_OFF_BAR: &str = "pcurve fit refused: the trim misses its stations by";
2495
2496/// The one acceptance decision behind [`build_pcurve_on_surface_range`],
2497/// [`build_pcurve_on_surface_range_dense`] and
2498/// [`build_pcurve_on_surface_stations`]: a fit on its bar
2499/// ([`PcurveFitReport::on_bar`]) is the curve, a fit off it is a refusal that
2500/// names the residual, the bar, what was asked, how far the stations stand off
2501/// the carrier and why refinement stopped.
2502///
2503/// Until 2026-09-26 these builders returned whatever their last round built
2504/// without measuring it (the 2026-09-18 census: 4564 of 54556 imported pcurves
2505/// over the ask they were built to, 2072 of them at a station the refinement
2506/// itself had tested and given up on). Nothing here widens a band: the bar is
2507/// the caller's own ask plus what the input makes unreachable.
2508fn accept_fit(fit: PcurveFit) -> Result<NurbsCurve, String> {
2509    let report = fit.report;
2510    if report.on_bar() {
2511        return Ok(fit.curve);
2512    }
2513    Err(off_bar_message(&report))
2514}
2515
2516fn off_bar_message(report: &PcurveFitReport) -> String {
2517    format!(
2518        "{PCURVE_OFF_BAR} {:.3e} out of sample against a bar of {:.3e} (asked {:.1e}, the \
2519         stations stand {:.3e} off the carrier; {:?} at {} samples{}{})",
2520        report.residual,
2521        report.floor + report.off_surface,
2522        report.floor,
2523        report.off_surface,
2524        report.exit,
2525        report.samples,
2526        if report.raised { ", after the raise" } else { "" },
2527        if report.clamped_excursion > 0.0 {
2528            format!(
2529                "; clamped into the chart by {:.3e} in parameter, {:.3e} in 3D",
2530                report.clamped_excursion, report.clamped_distance
2531            )
2532        } else {
2533            String::new()
2534        },
2535    )
2536}
2537
2538/// The class slug of a pcurve fit refused off its bar
2539/// ([`crate::RefusalClass::NonConvergence`]): minted by
2540/// [`build_pcurve_on_surface_range_classed`] and read by
2541/// [`is_pcurve_off_bar`], so a dispatcher decides on the class, never on the
2542/// message text.
2543pub(crate) const PCURVE_OFF_BAR_WHAT: &str = "pcurve_fit_off_bar";
2544
2545/// Whether `refusal` is a pcurve fit that could not reach its bar.
2546pub(crate) fn is_pcurve_off_bar(refusal: &crate::KernelRefusal) -> bool {
2547    matches!(&refusal.class, crate::RefusalClass::NonConvergence { what } if what == PCURVE_OFF_BAR_WHAT)
2548}
2549
2550/// [`build_pcurve_on_surface_range`] with a typed refusal: a fit off its bar
2551/// is `NonConvergence { what: PCURVE_OFF_BAR_WHAT }` at `stage`, with the same
2552/// message; any other failure of the fit is `Internal` under `what`.
2553pub(crate) fn build_pcurve_on_surface_range_classed(
2554    surface: &NurbsSurface,
2555    curve: &NurbsCurve,
2556    edge_start: f64,
2557    edge_end: f64,
2558    forward: bool,
2559    tolerance: f64,
2560    stage: KernelStage,
2561    what: &'static str,
2562) -> Result<NurbsCurve, crate::KernelRefusal> {
2563    use crate::OrRefuse;
2564    let fit = fit_pcurve_on_surface_range(surface, curve, edge_start, edge_end, forward, tolerance)
2565        .or_refuse(stage, what)?;
2566    accept_fit_classed(fit, stage)
2567}
2568
2569/// [`accept_fit`] with the refusal typed: `NonConvergence { what:
2570/// PCURVE_OFF_BAR_WHAT }` at `stage`, the message unchanged.
2571pub(crate) fn accept_fit_classed(fit: PcurveFit, stage: KernelStage) -> Result<NurbsCurve, crate::KernelRefusal> {
2572    if fit.report.on_bar() {
2573        return Ok(fit.curve);
2574    }
2575    Err(crate::KernelRefusal {
2576        class: crate::RefusalClass::NonConvergence { what: PCURVE_OFF_BAR_WHAT.into() },
2577        stage,
2578        message: off_bar_message(&fit.report),
2579    })
2580}
2581
2582/// The EXACT pcurve for a coedge's subrange of `curve` on an affine carrier,
2583/// or `None` when there is no such answer and the sampled lane must run.
2584///
2585/// [`fit_pcurve_on_surface`] has always mapped a WHOLE curve's control net
2586/// exactly on an affine carrier. A coedge's trim is that same curve restricted
2587/// to `[edge_start, edge_end]` and oriented by `forward`, and both operations
2588/// are exact on a NURBS: [`NurbsCurve::split`] subdivides by knot insertion,
2589/// [`NurbsCurve::reversed`] mirrors the net, and rescaling the knots to
2590/// `[0, 1]` is affine in the edge's own parameter — which is precisely the
2591/// fraction convention the sampled lane uses, so the pcurve's correspondence
2592/// with the edge is the same one either lane produces.
2593///
2594/// Sampling where an exact answer exists leaves a real error: measured
2595/// 2026-09-17, a booleaned band rim's two planar trims sat 2.379e-4 and
2596/// 2.395e-4 off their edges, where this lane lands 1.4e-13 off.
2597///
2598/// The image is verified against the caller's own `tolerance` before it is
2599/// returned. The exact image of a curve that does NOT lie on this carrier is
2600/// its orthogonal projection, which is not that coedge's trim, so every such
2601/// case falls through to the sampled lane and keeps the refusals that lane
2602/// makes today.
2603fn affine_pcurve_on_range(
2604    surface: &NurbsSurface,
2605    curve: &NurbsCurve,
2606    edge_start: f64,
2607    edge_end: f64,
2608    forward: bool,
2609    tolerance: f64,
2610) -> Result<Option<PcurveFit>, String> {
2611    // Opt-out for A/B bisection of this lane against the sampled one, in the
2612    // shape of the two hatches beside it (`BREP_NO_PCURVE_REPAIR`,
2613    // `BREP_SECTION_PCURVE_MARCH`). It is what showed that the boolean's
2614    // planar residuals do NOT come through here: the same binary with this set
2615    // and unset read identically to every digit on 21_band_rim.
2616    if std::env::var("BREP_AFFINE_RANGE_PCURVE").as_deref() == Ok("0") {
2617        return Ok(None);
2618    }
2619    let Some(inversion) = AffineInversion::of(surface)? else {
2620        return Ok(None);
2621    };
2622    if !(edge_start.is_finite() && edge_end.is_finite() && edge_start < edge_end) {
2623        // The sampled lane owns this refusal; it is not this lane's to reword.
2624        return Ok(None);
2625    }
2626    let [t0, t1] = curve.domain()?;
2627    let start = edge_start.max(t0);
2628    let end = edge_end.min(t1);
2629    // A range narrower than the knot identity tolerance cannot be split onto
2630    // its own endpoints at all.
2631    if end - start <= 2.0 * KNOT_IDENTITY_TOL {
2632        return Ok(None);
2633    }
2634    let mut restricted = curve.clone();
2635    if end < t1 - KNOT_IDENTITY_TOL {
2636        restricted = restricted.split(end)?.0;
2637    }
2638    if start > t0 + KNOT_IDENTITY_TOL {
2639        restricted = restricted.split(start)?.1;
2640    }
2641    let mut pcurve = inversion.image_of(&restricted)?;
2642    if !forward {
2643        pcurve = pcurve.reversed()?;
2644    }
2645    let first = pcurve.knots[0];
2646    let last = pcurve.knots[pcurve.knots.len() - 1];
2647    if !(last - first > 0.0) {
2648        return Ok(None);
2649    }
2650    let knots = pcurve
2651        .knots
2652        .iter()
2653        .map(|knot| (knot - first) / (last - first))
2654        .collect::<Vec<_>>();
2655    let pcurve = NurbsCurve::new(pcurve.degree, knots, pcurve.control_points.clone())?;
2656
2657    // Verify against the range the CALLER asked for, not the one the
2658    // restriction produced: `split` snaps onto a nearby knot, so a snap that
2659    // moved the correspondence reads here as a deviation. Sampling at
2660    // fractions that are not the stations any lane interpolates through keeps
2661    // this a check on the whole trim rather than on its endpoints.
2662    let scale = 1.0 + curve.evaluate((start + end) / 2.0)?.length();
2663    let bar = tolerance.max(1e-11 * scale);
2664    let mut residual = 0.0_f64;
2665    for index in 0..=32 {
2666        let fraction = index as f64 / 32.0;
2667        let uv = pcurve.evaluate(fraction)?;
2668        // `evaluate` CLAMPS out-of-domain uv. A planar carrier's domain is a
2669        // bounding rectangle that a booleaned trim can leave, and an affine
2670        // patch's extension is the same plane, so read it unclamped.
2671        let on_carrier = surface.evaluate_extended(uv.x, uv.y)?;
2672        let edge_fraction = if forward { fraction } else { 1.0 - fraction };
2673        let on_edge = curve.evaluate(start + (end - start) * edge_fraction)?;
2674        residual = residual.max(on_carrier.sub(on_edge).length());
2675        if residual > bar {
2676            return Ok(None);
2677        }
2678    }
2679    let samples = pcurve.control_points.len();
2680    Ok(Some(PcurveFit {
2681        curve: pcurve,
2682        report: PcurveFitReport {
2683            residual,
2684            // The floor this lane VERIFIED against: the caller's ask, or the
2685            // floating-point floor of an exact map on a part this size. An
2686            // exact image is on its bar by construction; a caller asking for
2687            // less than the map's own precision is not refused for it.
2688            floor: bar,
2689            samples,
2690            exit: PcurveFitExit::Converged,
2691            off_surface: 0.0,
2692            raised: false,
2693            clamped_excursion: 0.0,
2694            clamped_distance: 0.0,
2695        },
2696    }))
2697}
2698
2699fn align_collapsed_endpoints(surface: &NurbsSurface, raw: &mut [[f64; 2]]) -> Result<(), String> {
2700    let anchor = surface.control_points[0][0].point()?;
2701    let mut extent = 0.0_f64;
2702    for control in surface.control_points.iter().flatten() {
2703        extent = extent.max(control.point()?.sub(anchor).length());
2704    }
2705    // This is a geometric identity check, independent of the fitting allowance
2706    // and of world position. Positive rational weights keep the whole iso-curve
2707    // inside the convex hull of its Euclidean controls. Cap the size coupling
2708    // at the linear tolerance so a large patch cannot erase a thin finite row.
2709    let pole_band = (1e-10 * (1.0 + extent)).min(LINEAR_TOLERANCE);
2710    for (endpoint, neighbor) in [(0, 1), (raw.len() - 1, raw.len() - 2)] {
2711        let point = surface.evaluate(raw[endpoint][0], raw[endpoint][1])?;
2712        for axis in 0..2 {
2713            let mut candidate = raw[endpoint];
2714            candidate[axis] = raw[neighbor][axis];
2715            if candidate == raw[endpoint]
2716                || surface
2717                    .evaluate(candidate[0], candidate[1])?
2718                    .sub(point)
2719                    .length()
2720                    > pole_band
2721            {
2722                continue;
2723            }
2724            let row = if axis == 0 {
2725                surface.iso_curve_v(raw[endpoint][1])?
2726            } else {
2727                surface.iso_curve_u(raw[endpoint][0])?
2728            };
2729            let mut collapsed = true;
2730            for control in &row.control_points {
2731                if control.point()?.sub(point).length() > pole_band {
2732                    collapsed = false;
2733                    break;
2734                }
2735            }
2736            if collapsed {
2737                raw[endpoint] = candidate;
2738            }
2739        }
2740    }
2741    Ok(())
2742}
2743
2744/// Re-seat any raw inversion sample that BRANCH-JUMPED — snapped to a distant
2745/// fold of a self-overlapping general carrier — back onto the branch traced by
2746/// its neighbours.
2747///
2748/// Each entry in `raw` is an INDEPENDENT global closest-point inversion of the
2749/// corresponding 3D edge sample. Every one is geometrically valid (on the
2750/// surface, at the edge), but they need not be CONTIGUOUS: where a rational
2751/// B-spline surface folds back over the small trimmed patch it carries, the
2752/// momentarily-closest fold flips from one sample to the next, so the raw
2753/// polygon zig-zags across the whole domain and self-crosses — and the region
2754/// its interpolant bounds no longer covers the true face (its surface flux can
2755/// exceed its own area). We anchor on the LONGEST run of mutually-continuous
2756/// samples — the fold the trimmed patch actually lies on, since a small face
2757/// lives on ONE fold and the jumped samples are the minority the global search
2758/// snapped elsewhere — then walk outward in both directions, re-seeding Newton
2759/// from the last good parameters and adopting the continuous footpoint whenever
2760/// it is geometrically as valid as the global one. Anchoring on consensus (not
2761/// blindly on sample 0, which can itself be an outlier that would drag the
2762/// whole edge onto the wrong branch and tear the loop open at its endpoint)
2763/// leaves continuous nonsingular fits unchanged. Certified collapsed endpoint
2764/// rows first adopt their neighbour's branch; a bad seed in the subsequent
2765/// jump repair cannot make a sample worse than the global search already had it.
2766fn repair_branch_jumps(
2767    surface: &NurbsSurface,
2768    edge_points: &[Vec3],
2769    raw: &mut [[f64; 2]],
2770    tolerance: f64,
2771) -> Result<(), String> {
2772    if raw.len() < 3 {
2773        return Ok(());
2774    }
2775    // Affine carriers invert linearly and exactly — no folds, nothing to chase.
2776    // Checked first so the common planar/affine face never touches the env.
2777    if surface.is_affine()? {
2778        return Ok(());
2779    }
2780    // Opt-out for A/B bisection of a STEP-import regression against this repair.
2781    if std::env::var("BREP_NO_PCURVE_REPAIR").is_ok() {
2782        return Ok(());
2783    }
2784    // A pole has no unique coordinate along its collapsed row. Continuing the
2785    // adjacent sample's branch is safe only when the ENTIRE row is collapsed;
2786    // coincident points across an ordinary seam or fold are not enough.
2787    align_collapsed_endpoints(surface, raw)?;
2788    let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
2789    let u_span = (u1 - u0).abs().max(EPSILON);
2790    let v_span = (v1 - v0).abs().max(EPSILON);
2791    let (closed_u, closed_v) = surface_closedness(surface)?;
2792    // Normalised, seam-aware step between two parameter samples. Wrapping the
2793    // closed directions keeps a legitimate seam crossing SMALL, so the seam /
2794    // periodic-unwrap machinery elsewhere is never disturbed by this repair.
2795    let norm_step = |a: [f64; 2], b: [f64; 2]| -> f64 {
2796        let mut du = a[0] - b[0];
2797        if closed_u {
2798            while du > 0.5 * u_span {
2799                du -= u_span;
2800            }
2801            while du < -0.5 * u_span {
2802                du += u_span;
2803            }
2804        }
2805        let mut dv = a[1] - b[1];
2806        if closed_v {
2807            while dv > 0.5 * v_span {
2808                dv -= v_span;
2809            }
2810            while dv < -0.5 * v_span {
2811                dv += v_span;
2812            }
2813        }
2814        ((du / u_span).powi(2) + (dv / v_span).powi(2)).sqrt()
2815    };
2816    // A jump crosses a large fraction of the WHOLE domain — orders above the
2817    // per-sample motion of any real (even domain-spanning) edge, which advances
2818    // ~1/N of its traversal between consecutive stations.
2819    const JUMP_THRESHOLD: f64 = 0.2;
2820    let count = raw.len();
2821
2822    // Locate the longest maximal run of consecutive continuous samples — the
2823    // branch to anchor on. If nothing jumps, this spans [0, count-1] and both
2824    // re-seat passes below are empty, leaving `raw` untouched.
2825    let (mut best_start, mut best_len, mut run_start) = (0usize, 1usize, 0usize);
2826    for index in 1..count {
2827        if norm_step(raw[index], raw[index - 1]) > JUMP_THRESHOLD {
2828            if index - run_start > best_len {
2829                best_len = index - run_start;
2830                best_start = run_start;
2831            }
2832            run_start = index;
2833        }
2834    }
2835    if count - run_start > best_len {
2836        best_len = count - run_start;
2837        best_start = run_start;
2838    }
2839    let (spine_lo, spine_hi) = (best_start, best_start + best_len - 1);
2840
2841    // Adopt the continuous footpoint only when it (a) still sits on the surface
2842    // — as tight as the fit band or the global answer — and (b) genuinely
2843    // closes the jump rather than trading it for another. Returns the parameter
2844    // to carry forward as the next seed (the repaired one, or the untouched
2845    // global when no repair applies).
2846    let reseat = |edge_point: Vec3,
2847                  previous: [f64; 2],
2848                  global: [f64; 2]|
2849     -> Result<[f64; 2], String> {
2850        let global_step = norm_step(global, previous);
2851        if global_step <= JUMP_THRESHOLD {
2852            return Ok(global);
2853        }
2854        let seeded =
2855            project_point_to_surface_seeded(surface, edge_point, previous[0], previous[1])?;
2856        let candidate = [seeded.u, seeded.v];
2857        let global_residual = surface
2858            .evaluate(global[0], global[1])?
2859            .sub(edge_point)
2860            .length();
2861        let on_surface = seeded.distance <= 4.0 * global_residual + tolerance.max(1e-12);
2862        if on_surface && norm_step(candidate, previous) < 0.5 * global_step {
2863            if std::env::var("BREP_DEBUG_PCURVE").is_ok() {
2864                eprintln!(
2865                    "pcurve repair: jump {global_step:.4} ({global:?}) -> {:.4} ({candidate:?}) res {:.2e}->{:.2e}",
2866                    norm_step(candidate, previous),
2867                    global_residual,
2868                    seeded.distance
2869                );
2870            }
2871            Ok(candidate)
2872        } else {
2873            Ok(global)
2874        }
2875    };
2876
2877    // Walk forward off the spine's high end, then backward off its low end,
2878    // chaining each repaired sample as the next seed so continuity propagates.
2879    //
2880    // Apart from the certified collapsed rows above, the two ENDPOINT samples
2881    // (fraction 0 and 1) are NEVER moved: they are the
2882    // edge's shared loop vertices. The global inversion is deterministic, so the
2883    // two coedges meeting at a vertex land it at the SAME parameters even when
2884    // that vertex sits on a fold reachable from two branches — moving one side
2885    // to a different branch tears the loop open there (`synthesize_pole_edge`
2886    // then rejects the non-collapsed gap). A vertex's genuine fold transition
2887    // (an edge whose interior rides u≈0.08 but whose endpoint must meet its
2888    // neighbour at u≈0.95) is exactly this case and must be preserved, not
2889    // "continuity-repaired" back onto the interior branch.
2890    let mut previous = raw[spine_hi];
2891    for index in (spine_hi + 1)..count.saturating_sub(1) {
2892        raw[index] = reseat(edge_points[index], previous, raw[index])?;
2893        previous = raw[index];
2894    }
2895    let mut previous = raw[spine_lo];
2896    for index in (1..spine_lo).rev() {
2897        raw[index] = reseat(edge_points[index], previous, raw[index])?;
2898        previous = raw[index];
2899    }
2900    Ok(())
2901}
2902
2903/// Range fitter with explicit sampling knobs, reporting what the fit achieved.
2904/// [`fit_pcurve_on_surface_range`] keeps the long-standing (base 64, 3
2905/// refinement rounds, 513 cap) budget; a fit that binds at that cap with the
2906/// bar unmet grows once to `PCURVE_RAISED_SAMPLES`
2907/// ([`fit_pcurve_on_surface_stations`]).
2908///
2909/// NOTE (2026-09-03): this comment used to say "STEP import retries failed fits
2910/// with a denser budget". No caller passes these knobs any more — that retry
2911/// was removed and the sentence outlived it. The knobs are kept because they
2912/// are the honest way to ASK whether a fit had headroom left, which is what
2913/// `examples/pcurve_residual_probe.rs` uses them for: on every ABC corpus
2914/// coedge that failed `validate`'s pcurve check, budgets up to (512, 8, 8193)
2915/// with a 1000x tighter target reproduced the coarse fit's deviation to six
2916/// decimals, because that deviation is the edge-vs-surface closest-point
2917/// residual and a curve ON the surface cannot beat it.
2918#[allow(clippy::too_many_arguments)]
2919pub fn fit_pcurve_on_surface_range_dense(
2920    surface: &NurbsSurface,
2921    curve: &NurbsCurve,
2922    edge_start: f64,
2923    edge_end: f64,
2924    forward: bool,
2925    tolerance: f64,
2926    base_samples: usize,
2927    refinement_rounds: usize,
2928    parameter_cap: usize,
2929) -> Result<PcurveFit, String> {
2930    if !(edge_start.is_finite() && edge_end.is_finite() && edge_start < edge_end) {
2931        return Err("build_pcurve_on_surface_range: invalid edge interval".into());
2932    }
2933    let evaluate_edge = |fraction: f64| {
2934        let edge_fraction = if forward { fraction } else { 1.0 - fraction };
2935        curve.evaluate(edge_start + (edge_end - edge_start) * edge_fraction)
2936    };
2937    let breaks = range_breaks(curve, edge_start, edge_end, forward);
2938    let ask = tolerance.max(PCURVE_REFINEMENT_TOLERANCE);
2939    let fit = fit_station_pcurve(
2940        surface,
2941        &evaluate_edge,
2942        &breaks,
2943        &breaks,
2944        ask,
2945        base_samples,
2946        refinement_rounds,
2947        parameter_cap,
2948        SPAN_FLOOR,
2949    )?;
2950    end_span_challenger(surface, curve, &evaluate_edge, edge_start, edge_end, forward, &breaks, ask, base_samples, refinement_rounds, parameter_cap, fit)
2951}
2952
2953/// The edge curve's OWN distinct interior knots inside `[edge_start,
2954/// edge_end]`, mapped through the trim's range and sense to coedge
2955/// fractions, that fall inside `pcurve`'s FIRST or LAST span (between the
2956/// domain end and its nearest interior knot), sorted.
2957fn native_end_knot_fractions(curve: &NurbsCurve, edge_start: f64, edge_end: f64, forward: bool, pcurve: &NurbsCurve) -> Result<Vec<f64>, String> {
2958    let [q0, q1] = pcurve.domain()?;
2959    let mut interior: Vec<f64> = pcurve.knots.iter().copied().filter(|k| *k > q0 && *k < q1).collect();
2960    interior.dedup();
2961    let (Some(&first), Some(&last)) = (interior.first(), interior.last()) else { return Ok(Vec::new()) };
2962    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
2963    let span = edge_end - edge_start;
2964    let mut fractions: Vec<f64> = curve
2965        .knots
2966        .iter()
2967        .copied()
2968        .filter(|k| *k > low && *k < high)
2969        .map(|k| {
2970            let along = (k - edge_start) / span;
2971            if forward { along } else { 1.0 - along }
2972        })
2973        .filter(|f| f.is_finite() && ((*f > q0 && *f < first) || (*f > last && *f < q1)))
2974        .collect();
2975    fractions.sort_by(f64::total_cmp);
2976    fractions.dedup();
2977    Ok(fractions)
2978}
2979
2980/// The admission rule for a foot read against an edge point: finite distance,
2981/// finite point, finite (u, v) inside the native domain. Shared by
2982/// [`common_station_read`] and the station fitter's tracking mode.
2983fn foot_admitted(foot: &crate::SurfaceProjection, [u0, u1]: [f64; 2], [v0, v1]: [f64; 2]) -> bool {
2984    let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
2985    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)
2986}
2987
2988/// The tracking mode's verification probes: the current pcurve's native probes
2989/// ([`native_probe_fractions`]: endpoints, quarters and 16 interior points of
2990/// each knot span), its EXACT knots (the final common read includes them, and
2991/// the native probes do not), and the caller's fixed fractions; finite, in
2992/// [0, 1], sorted, deduplicated.
2993fn verification_fractions(pcurve: &NurbsCurve, verify: &[f64]) -> Result<Vec<f64>, String> {
2994    let mut fractions = native_probe_fractions(&[pcurve])?;
2995    fractions.extend(pcurve.knots.iter().copied());
2996    fractions.extend(verify.iter().copied());
2997    fractions.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
2998    fractions.sort_by(f64::total_cmp);
2999    fractions.dedup();
3000    Ok(fractions)
3001}
3002
3003/// The off-carrier candidate admission, at the same probes and shared feet
3004/// (`[tracking, deviation, excess]` per curve, [`common_station_read_with_excess`]):
3005/// every reading finite, the candidate's tracking strictly lower, and EITHER
3006/// its maximum deviation no worse than the legacy's (the original rule) OR the
3007/// candidate meeting the ORIGINAL floors outright, tracking and excess both
3008/// within `PCURVE_REFINEMENT_TOLERANCE` (1e-7).
3009///
3010/// Why the second branch: for fits whose images follow the shared admitted
3011/// feet, the maximum deviation can be dominated by the edge's standoff.
3012/// Their measured maxima can then differ by rounding while tracking improves.
3013/// This does not assert that the admitted foot is a certified global nearest
3014/// point or that an arbitrary pcurve has the same maximum deviation.
3015/// next5 fixture 25 (BREP_DEBUG_STATION_FIT): every tracking candidate reached
3016/// the floor (9.52e-8 .. 9.94e-8 tracking) and was declined on a deviation
3017/// 1.2e-14 .. 6.7e-13 above the legacy's at 2.1e-5 .. 9.0e-4 standoffs, while
3018/// the legacy kept 5.9e-7 .. 8.5e-5 tracking. A candidate within the original
3019/// floors on both readings is what those controls require; it is not a
3020/// standoff allowance and no bar moves.
3021pub(crate) fn floor_admits(old: [f64; 3], new: [f64; 3]) -> bool {
3022    let floor = PCURVE_REFINEMENT_TOLERANCE;
3023    old.iter().chain(new.iter()).all(|v| v.is_finite())
3024        && new[0] < old[0]
3025        && (new[1] <= old[1] || (new[0] <= floor && new[2] <= floor))
3026}
3027
3028/// The common reader's foot: the NEAREST admitted ([`foot_admitted`]) of the
3029/// global projection, the projection seeded at the reference (legacy) uv and
3030/// the one seeded at the candidate (image) uv, in THAT order, so that between
3031/// admitted feet at equal distance the first in this order is taken
3032/// (`min_by` keeps the first minimum). [`common_station_read`] and the station
3033/// fitter's tracking mode both take their foot here, so an equal-distance tie
3034/// resolves to the same foot in both.
3035fn common_foot(
3036    global: Option<crate::SurfaceProjection>,
3037    reference: Option<crate::SurfaceProjection>,
3038    candidate: Option<crate::SurfaceProjection>,
3039    domain_u: [f64; 2],
3040    domain_v: [f64; 2],
3041) -> Option<crate::SurfaceProjection> {
3042    [global, reference, candidate]
3043        .into_iter()
3044        .flatten()
3045        .filter(|f| foot_admitted(f, domain_u, domain_v))
3046        .min_by(|a, b| a.distance.total_cmp(&b.distance))
3047}
3048
3049/// The probes a RANGE trim is read at by the common reader: `curves`'
3050/// native spans (endpoints, quarters and 16 interior points of each knot
3051/// span) and exact knots, plus the edge curve's own knots CLIPPED to
3052/// `[t0, t1]` (with the range ends) and the same 19 points on every clipped
3053/// span, mapped through the coedge's sense to fractions; finite, in [0, 1],
3054/// sorted, deduplicated.
3055pub(crate) fn range_use_probes(curves: &[&NurbsCurve], edge_curve: &NurbsCurve, t0: f64, t1: f64, forward: bool) -> Result<Vec<f64>, String> {
3056    let mut probes = native_probe_fractions(curves)?;
3057    for curve in curves {
3058        probes.extend(curve.knots.iter().copied());
3059    }
3060    let span = t1 - t0;
3061    if span.is_finite() && span != 0.0 {
3062        let (low, high) = (t0.min(t1), t0.max(t1));
3063        let mut knots: Vec<f64> = edge_curve.knots.iter().copied().filter(|k| *k >= low && *k <= high).collect();
3064        knots.push(low);
3065        knots.push(high);
3066        knots.sort_by(f64::total_cmp);
3067        knots.dedup();
3068        let locals: Vec<f64> = [0.25, 0.5, 0.75]
3069            .into_iter()
3070            .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
3071            .collect();
3072        let mut ts = knots.clone();
3073        for pair in knots.windows(2).filter(|w| w[1] > w[0]) {
3074            for &local in &locals {
3075                ts.push(pair[0] + (pair[1] - pair[0]) * local);
3076            }
3077        }
3078        for t in ts {
3079            let along = (t - t0) / span;
3080            probes.push(if forward { along } else { 1.0 - along });
3081        }
3082    }
3083    probes.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3084    probes.sort_by(f64::total_cmp);
3085    probes.dedup();
3086    Ok(probes)
3087}
3088
3089/// [`common_station_read`] for two RANGE trims of one coedge (`old`, `new`,
3090/// both on the coedge fraction domain [0, 1]) against the edge curve over
3091/// `[t0, t1]` in the coedge's sense, at [`range_use_probes`] of both: the same
3092/// probes and one shared admitted foot per probe, finite or an error. A trim
3093/// not on [0, 1] is an error.
3094// Unused by the import lane since the tracking trigger and keep were withdrawn
3095// for this merge; kept, with its controls, for their re-proposal.
3096#[cfg_attr(not(test), allow(dead_code))]
3097pub(crate) fn range_common_read(
3098    surface: &NurbsSurface,
3099    edge_curve: &NurbsCurve,
3100    t0: f64,
3101    t1: f64,
3102    forward: bool,
3103    old: &NurbsCurve,
3104    new: &NurbsCurve,
3105) -> Result<((f64, f64), (f64, f64)), String> {
3106    let (o, n) = range_common_read_with_excess(surface, edge_curve, t0, t1, forward, old, new)?;
3107    Ok(((o[0], o[1]), (n[0], n[1])))
3108}
3109
3110/// [`range_common_read`] with each trim's maximum pointwise excess over the
3111/// shared admitted foot's own distance: `[tracking, deviation, excess]` per
3112/// trim ([`common_station_read_with_excess`]).
3113// Unused by the import lane since the tracking trigger and keep were withdrawn
3114// for this merge; kept, with its controls, for their re-proposal.
3115#[cfg_attr(not(test), allow(dead_code))]
3116pub(crate) fn range_common_read_with_excess(
3117    surface: &NurbsSurface,
3118    edge_curve: &NurbsCurve,
3119    t0: f64,
3120    t1: f64,
3121    forward: bool,
3122    old: &NurbsCurve,
3123    new: &NurbsCurve,
3124) -> Result<([f64; 3], [f64; 3]), String> {
3125    for curve in [old, new] {
3126        if !matches!(curve.domain(), Ok([a, b]) if a == 0.0 && b == 1.0) {
3127            return Err("range common read: a trim not on [0, 1]".into());
3128        }
3129    }
3130    let probes = range_use_probes(&[old, new], edge_curve, t0, t1, forward)?;
3131    let evaluate = |fraction: f64| -> Result<Vec3, String> {
3132        let along = if forward { fraction } else { 1.0 - fraction };
3133        edge_curve.evaluate(t0 + (t1 - t0) * along)
3134    };
3135    common_station_read_with_excess(surface, &evaluate, old, new, &probes)
3136}
3137
3138/// The legacy and candidate pcurves read against the edge at the SAME probes
3139/// and against the SAME foot per probe: at each fraction, the edge point's
3140/// foot is the NEAREST admitted one among the global projection and the
3141/// projections seeded at the legacy and the candidate image's (u, v). A foot
3142/// is admitted with a finite distance and point and a finite (u, v) inside the
3143/// native domain. Both images are then measured against that one shared foot
3144/// (TRACKING) and against the edge point (same-parameter DEVIATION). The
3145/// shared foot is the nearest of these three, not a certified global nearest.
3146/// Any non-finite image, point or distance, or a probe with no admitted foot,
3147/// is an error (the caller keeps the legacy fit). Returns
3148/// ((legacy tracking, legacy deviation), (candidate tracking, candidate
3149/// deviation)), maxima over the probes.
3150pub(crate) fn common_station_read(
3151    surface: &NurbsSurface,
3152    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3153    legacy: &NurbsCurve,
3154    candidate: &NurbsCurve,
3155    probes: &[f64],
3156) -> Result<((f64, f64), (f64, f64)), String> {
3157    let (old, new) = common_station_read_with_excess(surface, evaluate_edge, legacy, candidate, probes)?;
3158    Ok(((old[0], old[1]), (new[0], new[1])))
3159}
3160
3161/// [`common_station_read`] that also returns, per curve, the maximum
3162/// pointwise EXCESS: the same-parameter deviation minus the shared admitted
3163/// foot's own distance at that probe (the part over the edge's standoff
3164/// there, which the every-use controls bar at the original 1e-7). Returns
3165/// `[tracking, deviation, excess]` for the legacy and the candidate.
3166pub(crate) fn common_station_read_with_excess(
3167    surface: &NurbsSurface,
3168    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3169    legacy: &NurbsCurve,
3170    candidate: &NurbsCurve,
3171    probes: &[f64],
3172) -> Result<([f64; 3], [f64; 3]), String> {
3173    let (domain_u, domain_v) = surface_domains(surface)?;
3174    let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
3175    // [tracking, deviation, excess] per curve; the excess (deviation minus
3176    // the shared foot's distance, per probe) starts at -inf, so a read with no
3177    // probe is not finite and admits nothing.
3178    let mut read = ([0.0_f64, 0.0, f64::NEG_INFINITY], [0.0_f64, 0.0, f64::NEG_INFINITY]);
3179    for &fraction in probes {
3180        let point = evaluate_edge(fraction)?;
3181        let (old_uv, new_uv) = (legacy.evaluate(fraction)?, candidate.evaluate(fraction)?);
3182        let (old_image, new_image) = (surface.evaluate_extended(old_uv.x, old_uv.y)?, surface.evaluate_extended(new_uv.x, new_uv.y)?);
3183        if !(finite(point) && finite(old_image) && finite(new_image)) {
3184            return Err(format!("common station read: non-finite point at fraction {fraction}"));
3185        }
3186        // Reading ONE curve against itself (`legacy` and `candidate` the same
3187        // object, as a trigger's read is): the candidate-seeded projection is
3188        // the reference-seeded one on identical inputs, so it is computed once
3189        // (same result, same tie order).
3190        let reference_foot = memo_seeded_foot(surface, point, old_uv.x, old_uv.y);
3191        let candidate_foot = if std::ptr::eq(legacy, candidate) {
3192            reference_foot
3193        } else {
3194            memo_seeded_foot(surface, point, new_uv.x, new_uv.y)
3195        };
3196        let foot = common_foot(
3197            memo_global_foot(surface, point),
3198            reference_foot,
3199            candidate_foot,
3200            domain_u,
3201            domain_v,
3202        )
3203        .ok_or_else(|| format!("common station read: no admitted foot at fraction {fraction}"))?;
3204        let values = [
3205            old_image.sub(foot.point).length(),
3206            old_image.sub(point).length(),
3207            new_image.sub(foot.point).length(),
3208            new_image.sub(point).length(),
3209        ];
3210        if values.iter().any(|v| !v.is_finite()) {
3211            return Err(format!("common station read: non-finite distance at fraction {fraction}"));
3212        }
3213        if !foot.distance.is_finite() {
3214            return Err(format!("common station read: non-finite foot distance at fraction {fraction}"));
3215        }
3216        read.0[0] = read.0[0].max(values[0]);
3217        read.0[1] = read.0[1].max(values[1]);
3218        read.0[2] = read.0[2].max(values[1] - foot.distance);
3219        read.1[0] = read.1[0].max(values[2]);
3220        read.1[1] = read.1[1].max(values[3]);
3221        read.1[2] = read.1[2].max(values[3] - foot.distance);
3222    }
3223    Ok(read)
3224}
3225
3226/// The interior probe fractions of the edge curve's own FIRST and LAST native
3227/// knot spans inside `[edge_start, edge_end]` (quarter points and 16 interior
3228/// points of each), mapped through the trim's range and sense to coedge
3229/// fractions in [0, 1].
3230fn edge_end_span_fractions(curve: &NurbsCurve, edge_start: f64, edge_end: f64, forward: bool) -> Vec<f64> {
3231    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3232    let mut knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k > low && *k < high).collect();
3233    knots.dedup();
3234    let spans = match (knots.first(), knots.last()) {
3235        (Some(&first), Some(&last)) => vec![(low, first), (last, high)],
3236        _ => vec![(low, high)],
3237    };
3238    let span = edge_end - edge_start;
3239    let mut out = Vec::new();
3240    for (a, b) in spans {
3241        if !(b > a) {
3242            continue;
3243        }
3244        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)) {
3245            let along = (a + (b - a) * local - edge_start) / span;
3246            let fraction = if forward { along } else { 1.0 - along };
3247            if fraction.is_finite() && (0.0..=1.0).contains(&fraction) {
3248                out.push(fraction);
3249            }
3250        }
3251    }
3252    out.sort_by(f64::total_cmp);
3253    out.dedup();
3254    out
3255}
3256
3257/// At most this many of the legacy pcurve's worst spans are seeded.
3258const WORST_SPANS: usize = 4;
3259/// Interior stations seeded in each of them.
3260const WORST_SPAN_SEEDS: usize = 7;
3261
3262/// The seed fractions of [`end_span_challenger`]'s worst-span source: the
3263/// legacy pcurve's own spans (between its distinct knots) whose same-parameter
3264/// deviation, read at the quarter points and 16 interior points, and at any of
3265/// `extra_probes` (the edge's own end-span interior points mapped to coedge
3266/// fractions) that fall inside the span, exceeds
3267/// `bar`, worst first, at most [`WORST_SPANS`] of them, each seeded with
3268/// [`WORST_SPAN_SEEDS`] evenly spaced interior fractions. Fails closed on any
3269/// non-finite reading.
3270fn legacy_worst_span_seeds(
3271    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3272    surface: &NurbsSurface,
3273    pcurve: &NurbsCurve,
3274    bar: f64,
3275    extra_probes: &[f64],
3276) -> Result<Vec<f64>, String> {
3277    let [q0, q1] = pcurve.domain()?;
3278    let mut knots: Vec<f64> = pcurve.knots.iter().copied().filter(|k| *k >= q0 && *k <= q1).collect();
3279    knots.dedup();
3280    let locals: Vec<f64> = [0.25, 0.5, 0.75]
3281        .into_iter()
3282        .chain((1..=TRACKING_ACCEPTANCE_POINTS).map(|index| index as f64 / (TRACKING_ACCEPTANCE_POINTS + 1) as f64))
3283        .collect();
3284    let mut over: Vec<(f64, f64, f64)> = Vec::new();
3285    for span in knots.windows(2).filter(|w| w[1] > w[0]) {
3286        let mut worst = 0.0_f64;
3287        let inside = extra_probes.iter().copied().filter(|f| *f > span[0] && *f < span[1]);
3288        for fraction in locals.iter().map(|local| span[0] + (span[1] - span[0]) * local).chain(inside) {
3289            let uv = pcurve.evaluate(fraction)?;
3290            let deviation = surface.evaluate_extended(uv.x, uv.y)?.sub(evaluate_edge(fraction)?).length();
3291            if !deviation.is_finite() {
3292                return Err(format!("worst-span read: non-finite deviation at fraction {fraction}"));
3293            }
3294            worst = worst.max(deviation);
3295        }
3296        if worst > bar {
3297            over.push((worst, span[0], span[1]));
3298        }
3299    }
3300    over.sort_by(|a, b| b.0.total_cmp(&a.0).then(a.1.total_cmp(&b.1)));
3301    over.truncate(WORST_SPANS);
3302    Ok(over
3303        .into_iter()
3304        .flat_map(|(_, lo, hi)| (1..=WORST_SPAN_SEEDS).map(move |index| lo + (hi - lo) * index as f64 / (WORST_SPAN_SEEDS + 1) as f64))
3305        .collect())
3306}
3307
3308/// Why the range lane's [`end_span_challenger`] runs.
3309#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3310enum ChallengerTrigger {
3311    /// The legacy residual misses `ask + standoff` (the original trigger).
3312    Deviation,
3313    /// The legacy residual is within `ask + standoff`, the edge stands off its
3314    /// carrier by more than the ask, and the legacy fit's COMMON tracking
3315    /// (`common_station_read` at the fixed probes) misses the ask.
3316    Tracking,
3317}
3318
3319/// The challenger's trigger. The original rule reads the same-parameter
3320/// DEVIATION against `ask + standoff`; over a standoff `g` a tangential slip
3321/// `d` adds only about d²/(2g) to it, so a slip up to sqrt(ask² + 2·ask·g)
3322/// never triggers (about 1.3e-5 at g = 9e-4, the fixture-25 inherited edges).
3323/// When the deviation rule does not fire and the edge stands off its carrier
3324/// by more than the ask (the same gate `refine_pcurve` takes its
3325/// standoff-tracking lane on), the legacy fit's common tracking is read
3326/// (`tracking`, called only then): over the ask, the challenger runs on
3327/// tracking. An unread tracking (None or non-finite) never triggers.
3328fn challenger_trigger(residual: f64, off_surface: f64, ask: f64, tracking: impl FnOnce() -> Option<f64>) -> Option<ChallengerTrigger> {
3329    if residual > ask + off_surface {
3330        return Some(ChallengerTrigger::Deviation);
3331    }
3332    if !(off_surface > ask) {
3333        return None;
3334    }
3335    match tracking() {
3336        Some(value) if value.is_finite() && value > ask => Some(ChallengerTrigger::Tracking),
3337        _ => None,
3338    }
3339}
3340
3341/// The END-SPAN CHALLENGER of the range lane (2026-10-05, the four original
3342/// fitter rows of `abc_00000011/12` edges 7 and 243). On e90c30c94 their worst
3343/// excess (4.58e-6 and 5.14e-6) sat in the installed pcurve's LAST span, at the
3344/// edge's start, where the edge curve's own first knot span is only 4.5e-6
3345/// (e7) and 1.2e-4 (e243) wide while the fitter's end span was 1.4e-4 wide at
3346/// its cap. It runs when [`challenger_trigger`] fires: the legacy fit misses
3347/// its bar (residual over the ask plus its standoff), or, on an edge standing
3348/// off its carrier by more than the ask, its common tracking misses the ask.
3349/// It refits with the edge's own interior knots that
3350/// fall inside the legacy pcurve's first or last span as additional stations
3351/// (not joins; corners stay the legacy ones), through the same fitter with the
3352/// unchanged ask, SPAN_FLOOR, cap and rounds. The candidate replaces the legacy
3353/// fit only when both, read at COMMON probes (both pcurves' own knot spans,
3354/// knots and endpoints, plus the edge's own knots and knot spans mapped to
3355/// fractions) against one SHARED foot per probe ([`common_station_read`]),
3356/// read finite, the candidate's tracking is strictly lower and its
3357/// same-parameter deviation no worse. Otherwise, or on any error or unreadable read, the legacy fit
3358/// stands exactly.
3359#[allow(clippy::too_many_arguments)]
3360fn end_span_challenger(
3361    surface: &NurbsSurface,
3362    curve: &NurbsCurve,
3363    evaluate_edge: &dyn Fn(f64) -> Result<Vec3, String>,
3364    edge_start: f64,
3365    edge_end: f64,
3366    forward: bool,
3367    breaks: &[f64],
3368    ask: f64,
3369    base_samples: usize,
3370    refinement_rounds: usize,
3371    parameter_cap: usize,
3372    legacy: PcurveFit,
3373) -> Result<PcurveFit, String> {
3374    // On the bar by deviation: nothing is read (the original zero-work
3375    // path). The TRACKING trigger (538dd700c: an off-carrier edge on its
3376    // deviation bar challenged on its common tracking) is withdrawn from this
3377    // merge (Claude master's ruling, 2026-10-05): bisected as the first commit
3378    // that moved step_import's a_trim_off_its_bar_is_accepted_and_named, and
3379    // the four original fitter rows do not need it (they enter on the
3380    // deviation trigger).
3381    if !(legacy.report.residual > ask + legacy.report.off_surface) {
3382        return Ok(legacy);
3383    }
3384    // The trigger read, the candidate's tracking verification and the final
3385    // read project the same edge points again: memoized, same answers.
3386    let _feet = FootMemoScope::open(surface);
3387    let Ok(end_knots) = native_end_knot_fractions(curve, edge_start, edge_end, forward, &legacy.curve) else { return Ok(legacy) };
3388    // The legacy fit's own WORST native spans (2026-10-05, root's boundary
3389    // audit of the four rows): the e90 witnesses read a 4.58e-6 / 5.14e-6
3390    // pointwise excess at q 0.99996 inside the closed native domain, in the
3391    // legacy pcurve's last span, where no edge knot falls. Each span between the
3392    // legacy pcurve's own distinct knots is read at its 19 probes; the spans
3393    // whose same-parameter deviation exceeds the ask plus the legacy standoff,
3394    // worst first and at most WORST_SPANS of them, each get WORST_SPAN_SEEDS
3395    // evenly spaced interior stations. Unreadable reads decline.
3396    // The edge's OWN first and last native knot spans, read at their quarter
3397    // points and 16 interior points, mapped through the trim's range and sense
3398    // to coedge fractions (e7's first edge span [0, 4.496e-6] of a
3399    // 0.018661-long trim maps reversed to q in [0.99976, 1], overlapping the
3400    // legacy pcurve's last span [0.99986, 1]).
3401    let edge_end_probes = edge_end_span_fractions(curve, edge_start, edge_end, forward);
3402    // The FIXED part of the common probe set, known before the candidate is
3403    // fitted: the legacy pcurve's own spans, endpoints and knots, and the
3404    // edge's own end-span probes, knot-span quarters and knots (every probe
3405    // that could have TRIGGERED the challenger among them). The candidate fit
3406    // verifies against these as well as its own spans, so it stops on the
3407    // reader that judges it.
3408    let Ok(mut fixed) = native_probe_fractions(&[&legacy.curve]) else { return Ok(legacy) };
3409    fixed.extend(edge_end_probes.iter().copied());
3410    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3411    let mut edge_knots: Vec<f64> = curve.knots.iter().copied().filter(|k| *k >= low && *k <= high).collect();
3412    edge_knots.push(low);
3413    edge_knots.push(high);
3414    edge_knots.sort_by(f64::total_cmp);
3415    edge_knots.dedup();
3416    let to_fraction = |t: f64| {
3417        let along = (t - edge_start) / (edge_end - edge_start);
3418        if forward { along } else { 1.0 - along }
3419    };
3420    for span in edge_knots.windows(2).filter(|w| w[1] > w[0]) {
3421        for local in [0.25, 0.5, 0.75] {
3422            fixed.push(to_fraction(span[0] + (span[1] - span[0]) * local));
3423        }
3424    }
3425    fixed.extend(edge_knots.iter().map(|&t| to_fraction(t)));
3426    fixed.extend(end_knots.iter().copied());
3427    fixed.extend(legacy.curve.knots.iter().copied());
3428    fixed.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3429    fixed.sort_by(f64::total_cmp);
3430    fixed.dedup();
3431    let trigger = challenger_trigger(legacy.report.residual, legacy.report.off_surface, ask, || {
3432        common_station_read(surface, evaluate_edge, &legacy.curve, &legacy.curve, &fixed).ok().map(|((tracking, _), _)| tracking)
3433    });
3434    let Some(trigger) = trigger else { return Ok(legacy) };
3435    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) };
3436    // The original guard holds for the deviation trigger only: a tracking
3437    // trigger needs no added station (the tracking mode and its verification
3438    // read the fixed probes).
3439    if trigger == ChallengerTrigger::Deviation && end_knots.is_empty() && worst_seeds.is_empty() {
3440        return Ok(legacy);
3441    }
3442    let mut stations: Vec<f64> = breaks.iter().copied().chain(end_knots.iter().copied()).chain(worst_seeds.iter().copied()).collect();
3443    stations.sort_by(f64::total_cmp);
3444    stations.dedup();
3445    // The fitter's cap is max(requested cap, initial station count): the added
3446    // stations must not raise it. Decline when the merged initial count
3447    // (base stations plus every break and end knot) could exceed the
3448    // requested cap.
3449    let initial = base_samples.max(1).checked_add(1).and_then(|count| count.checked_add(stations.len()));
3450    if initial.is_none_or(|count| count > parameter_cap) {
3451        return Ok(legacy);
3452    }
3453    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 {
3454        return Ok(legacy);
3455    };
3456    if !(candidate.report.residual.is_finite() && candidate.report.off_surface.is_finite() && candidate.report.clamped_excursion.is_finite() && candidate.report.clamped_distance.is_finite()) {
3457        return Ok(legacy);
3458    }
3459    // Common probes: the fixed set plus the candidate's own knot spans,
3460    // endpoints and knots (the same set as both curves' native probes plus
3461    // the edge's, as before).
3462    let Ok(mut probes) = native_probe_fractions(&[&candidate.curve]) else { return Ok(legacy) };
3463    probes.extend(fixed.iter().copied());
3464    probes.extend(candidate.curve.knots.iter().copied());
3465    probes.retain(|f| f.is_finite() && (0.0..=1.0).contains(f));
3466    probes.sort_by(f64::total_cmp);
3467    probes.dedup();
3468    let readings = common_station_read_with_excess(surface, evaluate_edge, &legacy.curve, &candidate.curve, &probes);
3469    let accepted = matches!(&readings, Ok((old, new)) if floor_admits(*old, *new));
3470    if station_fit_tracing() {
3471        eprintln!(
3472            "STATION-FIT end-span challenger: trigger={trigger:?} end_knots={} worst_span_seeds={} edge_end_probes={} legacy={:?}/{:e} candidate={:?}/{:e} common={readings:?} decision={}",
3473            end_knots.len(), worst_seeds.len(), edge_end_probes.len(), legacy.report.exit, legacy.report.residual, candidate.report.exit, candidate.report.residual,
3474            if accepted { "candidate" } else { "legacy" }
3475        );
3476    }
3477    Ok(if accepted { candidate } else { legacy })
3478}
3479
3480
3481/// [`fit_pcurve_on_surface_range_dense`] for the callers that only need the
3482/// curve, accepted or refused on its bar (`accept_fit`).
3483#[allow(clippy::too_many_arguments)]
3484pub fn build_pcurve_on_surface_range_dense(
3485    surface: &NurbsSurface,
3486    curve: &NurbsCurve,
3487    edge_start: f64,
3488    edge_end: f64,
3489    forward: bool,
3490    tolerance: f64,
3491    base_samples: usize,
3492    refinement_rounds: usize,
3493    parameter_cap: usize,
3494) -> Result<NurbsCurve, String> {
3495    accept_fit(fit_pcurve_on_surface_range_dense(
3496        surface,
3497        curve,
3498        edge_start,
3499        edge_end,
3500        forward,
3501        tolerance,
3502        base_samples,
3503        refinement_rounds,
3504        parameter_cap,
3505    )?)
3506}
3507
3508/// The fractions of `[edge_start, edge_end]`, walked in the coedge's sense, at
3509/// which `curve` is not C2: interior knots of multiplicity at least its
3510/// degree. A rational-quadratic arc past a quarter turn is two segments joined
3511/// at a double knot, and an interpolant through uniform samples across that
3512/// joint cannot represent the second-derivative jump: on the 2026-09-18 import
3513/// census 1511 of the 2979 arc trims blamed on the fitter had their worst
3514/// miss at fraction 0.49–0.51, the mid double knot, exactly as the fillet's
3515/// corner patch had measured (`blend/track_fit.rs::curve_breaks`, which this
3516/// mirrors for a range).
3517pub(crate) fn range_breaks(
3518    curve: &NurbsCurve,
3519    edge_start: f64,
3520    edge_end: f64,
3521    forward: bool,
3522) -> Vec<f64> {
3523    let mut fractions = Vec::new();
3524    let span = edge_end - edge_start;
3525    if !(span.abs() > 0.0) {
3526        return fractions;
3527    }
3528    let (low, high) = (edge_start.min(edge_end), edge_start.max(edge_end));
3529    let mut index = 0;
3530    while index < curve.knots.len() {
3531        let value = curve.knots[index];
3532        let run = curve.knots[index..]
3533            .iter()
3534            .take_while(|knot| **knot == value)
3535            .count();
3536        if value > low && value < high && run >= curve.degree.max(1) {
3537            let along = (value - edge_start) / span;
3538            fractions.push(if forward { along } else { 1.0 - along });
3539        }
3540        index += run;
3541    }
3542    fractions.sort_by(f64::total_cmp);
3543    fractions
3544}
3545
3546/// The body of [`fit_pcurve_on_surface_range_dense`], parameterized by the
3547/// 3D station the pcurve must pass through at each coedge fraction instead of
3548/// by an edge curve and a range.
3549///
3550/// The station supplier is the whole difference between deriving a pcurve and
3551/// reading one. `fit_pcurve_on_surface_range_dense` supplies points off the
3552/// edge's own 3D curve, so the answer is "the nearest point of the carrier",
3553/// which is ambiguous exactly where a trim is interesting — a seam branch, a
3554/// near-tangential approach, a pole. The STEP importer's supplied-pcurve lane
3555/// supplies points off the VENDOR's stated trim instead, and the ambiguity is
3556/// gone because the vendor resolved it.
3557///
3558/// `stations(fraction)` must be continuous in `fraction` over `[0, 1]` and land
3559/// on (or very near) `surface`; `breaks` are the fractions at which it is not
3560/// C2 (`range_breaks`), each of which becomes a station so no kink sits
3561/// between two nodes. Everything else — inversion, branch repair, refinement
3562/// and the measurement — is shared with the derived lane by construction.
3563///
3564/// The SURFACE's knot-line crossings are deliberately not stations here,
3565/// although `blend/track_fit.rs` makes them so. Measured 2026-09-26 over the
3566/// 57-document import corpus: with each crossing bisected on the fraction and
3567/// projected seeded from the left station, 34 bodies refused (19 with a foot
3568/// that misses its global distance rejected) against 15 without the pass —
3569/// every extra refusal a fit stalled around a crossing station, on
3570/// `AssemblyExample-Assembly` and `abc_00000014` among others. The raised
3571/// pass resolves the O(h²) tail across a crossing on its own.
3572///
3573/// # What the fit is measured against, and when it stops
3574///
3575/// The stations' own standoff from the carrier is read FIRST, from the base
3576/// inversions, and the refinement target is the ask plus that standoff
3577/// ([`PcurveFitReport::on_bar`]): a station standing `g` off the surface
3578/// cannot be imaged closer than `g`, so chasing it to the ask alone spends the
3579/// whole budget for nothing (the 2026-09-18 census: 2052 imported pcurves at
3580/// the 513 cap, 1958 of them on a curve that is not on its carrier).
3581///
3582/// Every probe and the final measurement read the carrier through
3583/// `evaluate_extended`: a pcurve riding a periodic seam legitimately carries
3584/// parameters past the domain, and the clamped `evaluate` this loop used until
3585/// 2026-09-26 read every such station as a gross miss — an insert per round
3586/// until the cap, on a trim that was right.
3587///
3588/// The RETURNED curve is measured out of sample — at the quarter points of
3589/// every span between its nodes, where an interpolant is exact at the nodes
3590/// and extremal between — unless its last round probed every span and found
3591/// nothing to insert, in which case that round's maximum already is that
3592/// measurement. A fit that binds at `parameter_cap` or spends its rounds with
3593/// the bar still unmet grows ONCE to `PCURVE_RAISED_SAMPLES` (deterministic).
3594/// The report says which exit it took and what it reached; the `build_*`
3595/// wrappers refuse over the bar, this function never does.
3596#[allow(clippy::too_many_arguments)]
3597pub fn fit_pcurve_on_surface_stations(
3598    surface: &NurbsSurface,
3599    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3600    breaks: &[f64],
3601    tolerance: f64,
3602    base_samples: usize,
3603    refinement_rounds: usize,
3604    parameter_cap: usize,
3605) -> Result<PcurveFit, String> {
3606    fit_station_pcurve(
3607        surface, stations, breaks, &[], tolerance.max(PCURVE_REFINEMENT_TOLERANCE),
3608        base_samples, refinement_rounds, parameter_cap, SPAN_FLOOR,
3609    )
3610}
3611
3612/// Precision construction for stations on recognized analytic carriers. Unlike
3613/// general projection, their inverse maps reach floating point accuracy. This
3614/// is an explicit construction contract, not a change to general fit policy.
3615pub(crate) fn analytic_station_pcurve(
3616    surface: &NurbsSurface,
3617    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3618    tolerance: f64,
3619) -> Result<NurbsCurve, String> {
3620    if surface.analytic().is_none() {
3621        return Err("analytic pcurve requires an analytic carrier".into());
3622    }
3623    let mut breaks = Vec::new();
3624    for _ in 0..4 {
3625        let fit = fit_station_pcurve(surface, stations, &breaks, &[], tolerance, 64, 64, 8192, 1e-10)?;
3626        if fit.report.residual > tolerance || fit.report.off_surface > tolerance {
3627            return Err(format!(
3628                "analytic pcurve construction missed its contract: {:?}",
3629                fit.report
3630            ));
3631        }
3632        let mut failed = Vec::new();
3633        // Independent Gauss stations in every returned knot span, rather than
3634        // re-reading the interpolation nodes or the fitter's quarter stations.
3635        for pair in fit.curve.knots.windows(2) {
3636            if pair[1] <= pair[0] {
3637                continue;
3638            }
3639            for local in [
3640                0.06943184420297371,
3641                0.33000947820757187,
3642                0.6699905217924281,
3643                0.9305681557970262,
3644            ] {
3645                let t = pair[0] + (pair[1] - pair[0]) * local;
3646                let uv = fit.curve.evaluate(t)?;
3647                if surface
3648                    .evaluate_extended(uv.x, uv.y)?
3649                    .sub(stations(t)?)
3650                    .length()
3651                    > tolerance
3652                {
3653                    failed.push(t);
3654                }
3655            }
3656        }
3657        if failed.is_empty() {
3658            return Ok(fit.curve);
3659        }
3660        if breaks.len() + failed.len() > 8192 {
3661            break;
3662        }
3663        breaks.extend(failed);
3664        breaks.sort_by(f64::total_cmp);
3665        breaks.dedup();
3666    }
3667    Err("analytic pcurve failed independent knot-span witnesses".into())
3668}
3669
3670#[allow(clippy::too_many_arguments)]
3671fn fit_station_pcurve(
3672    surface: &NurbsSurface,
3673    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3674    breaks: &[f64],
3675    corners: &[f64],
3676    tolerance: f64,
3677    base_samples: usize,
3678    refinement_rounds: usize,
3679    parameter_cap: usize,
3680    span_floor: f64,
3681) -> Result<PcurveFit, String> {
3682    fit_station_pcurve_mode(surface, stations, breaks, corners, tolerance, base_samples, refinement_rounds, parameter_cap, span_floor, false, None, &[])
3683}
3684
3685/// [`fit_station_pcurve`] with an optional TRACKING mode, taken only by the
3686/// range lane's [`end_span_challenger`]; every other caller keeps the legacy
3687/// mode byte for byte. The legacy fitter probes, ranks and stops on the
3688/// image's same-parameter DEVIATION from the edge point. On an edge standing
3689/// off its carrier that deviation never falls under the ask, so every probe is
3690/// a candidate, the cap goes to the probes with the largest STANDOFF, and a
3691/// tangential slip of `d` adds only about d²/(2g) to a deviation over a
3692/// standoff `g`: the four original rows' challenger met its standoff (4.670e-6)
3693/// and kept a common tracking of 1.434e-6 (root's e24 run, 2026-10-05). In
3694/// tracking mode each probe reads its TRACKING, the image against the edge
3695/// point's foot (the nearer admitted one of the global projection and the
3696/// projection seeded at the image's uv: finite, inside the native domain, as
3697/// [`common_station_read`] admits). A probe is a candidate only over the ask,
3698/// the cap goes to the worst TRACKING first, and the one raise is taken when
3699/// the last round's tracking still misses the ask. The reported residual
3700/// stays the same-parameter deviation (standoff included). A probe with no
3701/// admitted foot is an error, which the challenger turns into the exact legacy
3702/// fit.
3703#[allow(clippy::too_many_arguments)]
3704fn fit_station_pcurve_mode(
3705    surface: &NurbsSurface,
3706    stations: &dyn Fn(f64) -> Result<Vec3, String>,
3707    breaks: &[f64],
3708    corners: &[f64],
3709    tolerance: f64,
3710    base_samples: usize,
3711    refinement_rounds: usize,
3712    parameter_cap: usize,
3713    span_floor: f64,
3714    track_projection: bool,
3715    reference: Option<&NurbsCurve>,
3716    verify: &[f64],
3717) -> Result<PcurveFit, String> {
3718    // Read only in tracking mode: the legacy mode makes no extra call.
3719    let domains = if track_projection { Some(surface_domains(surface)?) } else { None };
3720    // The tracking reading at one fraction, by the SAME foot rule as
3721    // [`common_station_read`], the reader the challenger accepts on: the
3722    // nearest admitted foot among the global projection and the projections
3723    // seeded at this image's uv and at the reference (legacy) pcurve's uv at
3724    // the same fraction. Returns the tracking and that foot (uv, distance),
3725    // which is where a tracking insert is placed.
3726    let tracking_of = |represented: Vec3, edge_point: Vec3, uv: Vec3, fraction: f64| -> Result<(f64, [f64; 2], f64), String> {
3727        let (domain_u, domain_v) = domains.ok_or_else(|| "station tracking: legacy mode".to_string())?;
3728        let finite = |p: Vec3| p.x.is_finite() && p.y.is_finite() && p.z.is_finite();
3729        let reference_seed = match reference {
3730            Some(curve) => curve.evaluate(fraction).ok().and_then(|seed| memo_seeded_foot(surface, edge_point, seed.x, seed.y)),
3731            None => None,
3732        };
3733        // The common reader's order (global, reference, candidate), so an
3734        // equal-distance tie takes the same foot here as there.
3735        let foot = common_foot(
3736            memo_global_foot(surface, edge_point),
3737            reference_seed,
3738            memo_seeded_foot(surface, edge_point, uv.x, uv.y),
3739            domain_u,
3740            domain_v,
3741        )
3742        .ok_or_else(|| "station tracking: no admitted foot".to_string())?;
3743        let tracking = represented.sub(foot.point).length();
3744        if !(finite(represented) && tracking.is_finite()) {
3745            return Err("station tracking: non-finite reading".into());
3746        }
3747        Ok((tracking, [foot.u, foot.v], foot.distance))
3748    };
3749    // The last round's tracking missed the ask (tracking mode only).
3750    let mut tracking_unmet = false;
3751    let evaluate_edge = stations;
3752    let base_samples = base_samples.max(1);
3753    // The general caller floors its ask: its projector places a foot
3754    // to about `LINEAR_TOLERANCE` (1e-7), so a caller asking for 1e-9 asks for
3755    // more than any station can deliver. Chased to such an ask the fit spends
3756    // its cap and reads its own noise — the direct-edit heals asked 1e-9 on
3757    // stations 9.9e-8 off their carrier and were refused by 8.5e-9
3758    // (2026-09-26). The floor is the ask's floor; the report says what was
3759    // reached against it.
3760
3761    let mut parameters = (0..=base_samples)
3762        .map(|index| index as f64 / base_samples as f64)
3763        .collect::<Vec<_>>();
3764    // A break within the span floor of a station IS that station: two nodes
3765    // closer than that make the interpolant swing between them, and over a
3766    // stretch that short the kink moves the fit by nothing a bar can read.
3767    // `abc_00000011` face #549's curve carries a triple knot 4e-7 before its
3768    // end; as a station it put the cubic 1.594e-2 off between it and the last
3769    // one (measured 2026-09-26), where the file's curve sits 1e-7 off.
3770    // A break that is a CORNER of the curve (`corners`, a subset of
3771    // `breaks`: the range lane passes its curve's knots of multiplicity >=
3772    // degree as both) is a C0 JOIN of the interpolant
3773    // (`build_interpolant_joined`): one cubic through the corner overshoots
3774    // on both sides whatever is inserted. A break that is only a station
3775    // (an analytic witness, a caller's own marker) joins nothing.
3776    let mut joins = Vec::with_capacity(corners.len());
3777    for &fraction in breaks {
3778        if !(fraction > 0.0 && fraction < 1.0) {
3779            continue;
3780        }
3781        let corner = corners.contains(&fraction);
3782        let at = parameters.partition_point(|parameter| *parameter < fraction);
3783        let near_left = at > 0 && fraction - parameters[at - 1] <= span_floor;
3784        let near_right = at < parameters.len() && parameters[at] - fraction <= span_floor;
3785        if near_left || near_right {
3786            // The break IS that station (a corner at a base station, e.g.
3787            // the midpoint of a two-piece curve at 32/64): no insert, but the
3788            // station is still the join.
3789            if corner {
3790                joins.push(if near_right { parameters[at] } else { parameters[at - 1] });
3791            }
3792            continue;
3793        }
3794        parameters.insert(at, fraction);
3795        if corner {
3796            joins.push(fraction);
3797        }
3798    }
3799    // The 3D edge point behind each raw inversion sample, kept parallel so the
3800    // continuity repair can re-seed a jumped station from its own footpoint.
3801    let mut edge_points = parameters
3802        .iter()
3803        .map(|fraction| evaluate_edge(*fraction))
3804        .collect::<Result<Vec<_>, _>>()?;
3805    // The stations' standoff from the carrier: the part of every residual no
3806    // pcurve can remove, known before a single probe is spent.
3807    let mut off_surface = 0.0_f64;
3808    let mut raw = Vec::with_capacity(edge_points.len());
3809    let mut gaps = Vec::with_capacity(edge_points.len());
3810    for point in &edge_points {
3811        let (parameter, gap) = invert_checked(surface, *point)?;
3812        off_surface = off_surface.max(gap);
3813        raw.push(parameter);
3814        gaps.push(gap);
3815    }
3816    repair_branch_jumps(surface, &edge_points, &mut raw, tolerance)?;
3817    let (mut pcurve, mut excursion, mut distance) =
3818        build_interpolant_joined(surface, &raw, &parameters, &joins)?;
3819
3820    let mut cap = parameter_cap.max(parameters.len());
3821    let mut rounds = refinement_rounds;
3822    let mut raised = false;
3823    loop {
3824        let mut exit = PcurveFitExit::RoundBudget;
3825        let mut converged_max = None;
3826        // This pass's last round probed every span (none narrow, none
3827        // truncated) and every probe tracked within the ask (tracking mode).
3828        let mut tracking_met = false;
3829        for _ in 0..rounds {
3830            if parameters.len() >= cap {
3831                exit = PcurveFitExit::SampleCeiling;
3832                break;
3833            }
3834            // The target is the ASK, bare: a station standing off the carrier
3835            // is chased to the foot it projects to, as the fitter has always
3836            // done. A target of ask + standoff (one landing, 2026-09-26) let
3837            // such a fit stop at its base stations with the interpolant
3838            // wandering between them, folded a molex wall's mesh and put a
3839            // trim of abc_00000023 2.2e-5 off its own parameter; the bar
3840            // below still reads what it reached.
3841            let target = tolerance;
3842            let mut candidates = Vec::new();
3843            let mut round_max = 0.0_f64;
3844            let mut truncated = false;
3845            let mut skipped_narrow = false;
3846            let worst_first = worst_first();
3847            'spans: for index in 0..parameters.len() - 1 {
3848                // The loop's own resolution floor: a span narrower than this
3849                // is not subdivided. Without it the
3850                // raised pass inserted into a vanishing span at a trim's end
3851                // until the cap — `abc_00000011` face #549's last stations sat
3852                // 4e-7 apart with their feet clamped at the patch edge, and the
3853                // cubic through them swung 1.594e-2 off between them (measured
3854                // 2026-09-26). A miss that survives only inside such a span is
3855                // reported as [`PcurveFitExit::SpanFloor`].
3856                if parameters[index + 1] - parameters[index] < span_floor {
3857                    skipped_narrow = true;
3858                    continue;
3859                }
3860                for local in [0.25, 0.5, 0.75] {
3861                    if !worst_first && parameters.len() + candidates.len() >= cap {
3862                        truncated = true;
3863                        break 'spans;
3864                    }
3865                    let fraction =
3866                        parameters[index] + (parameters[index + 1] - parameters[index]) * local;
3867                    let uv = pcurve.evaluate(fraction)?;
3868                    let represented = surface.evaluate_extended(uv.x, uv.y)?;
3869                    let edge_point = evaluate_edge(fraction)?;
3870                    let deviation = represented.sub(edge_point).length();
3871                    // The probe's reading: its deviation (legacy), or its
3872                    // tracking against the admitted foot (tracking mode).
3873                    let (reading, foot) = if track_projection {
3874                        let (tracking, foot_uv, foot_gap) = tracking_of(represented, edge_point, uv, fraction)?;
3875                        (tracking, Some((foot_uv, foot_gap)))
3876                    } else {
3877                        (deviation, None)
3878                    };
3879                    round_max = round_max.max(reading);
3880                    if reading <= target {
3881                        continue;
3882                    }
3883                    candidates.push((index, fraction, edge_point, uv, reading, foot));
3884                }
3885            }
3886            // Tracking mode's VERIFICATION, before it may stop: a round whose
3887            // quarter probes all track within the ask is read again at the
3888            // probes the challenger's acceptance reads, the current pcurve's
3889            // own knot spans (endpoints, quarters and 16 interior points: the
3890            // interpolant's knots are averages of three stations, not the
3891            // stations) and the caller's fixed fractions (the legacy pcurve's
3892            // spans and the edge's own). A probe over the ask becomes a
3893            // candidate at its own fraction, placed at its own foot. One
3894            // within the span floor of a station cannot be inserted: it is
3895            // counted, and the fit may not report its tracking as met. On e24
3896            // the four rows stopped on their quarter probes and read 1.144e-7 /
3897            // 1.590e-7 at the common probes (a4c84871 runtime, 2026-10-05).
3898            let mut verify_blocked = false;
3899            if track_projection && candidates.is_empty() && !truncated && !skipped_narrow {
3900                for fraction in verification_fractions(&pcurve, verify)? {
3901                    let index = parameters.partition_point(|parameter| *parameter <= fraction).saturating_sub(1).min(parameters.len() - 2);
3902                    let uv = pcurve.evaluate(fraction)?;
3903                    let represented = surface.evaluate_extended(uv.x, uv.y)?;
3904                    let edge_point = evaluate_edge(fraction)?;
3905                    let (tracking, foot_uv, foot_gap) = tracking_of(represented, edge_point, uv, fraction)?;
3906                    round_max = round_max.max(tracking);
3907                    if tracking <= target {
3908                        continue;
3909                    }
3910                    if fraction - parameters[index] <= span_floor || parameters[index + 1] - fraction <= span_floor {
3911                        verify_blocked = true;
3912                        continue;
3913                    }
3914                    // Two over-ask probes closer than the span floor in one
3915                    // span: keep the worse, so no near-duplicate stations.
3916                    if let Some(last) = candidates.last_mut() {
3917                        if last.0 == index && fraction - last.1 <= span_floor {
3918                            if tracking > last.4 {
3919                                *last = (index, fraction, edge_point, uv, tracking, Some((foot_uv, foot_gap)));
3920                            }
3921                            continue;
3922                        }
3923                    }
3924                    candidates.push((index, fraction, edge_point, uv, tracking, Some((foot_uv, foot_gap))));
3925                }
3926            }
3927            tracking_unmet = track_projection && round_max > target;
3928            // A round with more candidates than the cap has room for spends
3929            // that room on its WORST probes, kept in curve order, rather than
3930            // on the first spans in order: truncating in span order left the
3931            // late spans of an off-carrier ring at their base spacing and its
3932            // image 1.523e-6 off its feet; worst first reaches 5.84e-8 on the
3933            // same 513 samples. An even stride along the curve reached 2.87e-7
3934            // there but diluted the inserts a local miss needs and lost fits
3935            // over the corpus (a 1.3e-5 trim of `abc_00000011` fell back to its
3936            // 4.4e-4 size-ask fit), measured 2026-09-27.
3937            let room = cap.saturating_sub(parameters.len());
3938            if candidates.len() > room {
3939                truncated = true;
3940                let mut order: Vec<usize> = (0..candidates.len()).collect();
3941                order.sort_by(|&a, &b| candidates[b].4.total_cmp(&candidates[a].4).then(a.cmp(&b)));
3942                order.truncate(room);
3943                order.sort_unstable();
3944                candidates = order.into_iter().map(|index| candidates[index]).collect();
3945            }
3946            let mut inserts = Vec::with_capacity(candidates.len());
3947            for (index, fraction, edge_point, uv, _, foot) in candidates {
3948                // A tracking candidate is placed at the very foot it was read
3949                // against, so the node's image IS that foot; the legacy
3950                // inversion is unchanged.
3951                let (parameter, gap) = match foot {
3952                    Some(placed) => placed,
3953                    None => invert_near(surface, edge_point, [uv.x, uv.y], gaps[index].max(gaps[index + 1]))?,
3954                };
3955                inserts.push((index + 1, fraction, edge_point, parameter, gap));
3956            }
3957            if station_fit_tracing() {
3958                eprintln!(
3959                    "STATION-FIT round: samples={} target={target:.3e} round_max={round_max:.3e} inserts={} truncated={truncated}{}",
3960                    parameters.len(),
3961                    inserts.len(),
3962                    // Tracking mode's round_max is a TRACKING reading.
3963                    if track_projection { " mode=tracking" } else { "" }
3964                );
3965            }
3966            if inserts.is_empty() {
3967                exit = if truncated {
3968                    PcurveFitExit::SampleCeiling
3969                } else if skipped_narrow {
3970                    // Every probed span is within the target; the narrow ones
3971                    // were not probed, and the sweep below measures them.
3972                    PcurveFitExit::SpanFloor
3973                } else if track_projection {
3974                    // Every probe TRACKS within the ask, but round_max is a
3975                    // tracking reading, not the deviation the report carries.
3976                    // The exit is Stalled (no probe can be improved; the
3977                    // residual measured below is the edge's own standoff),
3978                    // and it becomes Converged below only if that measured
3979                    // deviation itself meets the floor. A verification probe
3980                    // over the ask that could not be inserted leaves the
3981                    // tracking UNMET.
3982                    tracking_met = !verify_blocked;
3983                    PcurveFitExit::Stalled
3984                } else {
3985                    converged_max = Some(round_max);
3986                    PcurveFitExit::Converged
3987                };
3988                break;
3989            }
3990            for (index, fraction, edge_point, parameter, gap) in inserts.into_iter().rev() {
3991                parameters.insert(index, fraction);
3992                edge_points.insert(index, edge_point);
3993                raw.insert(index, parameter);
3994                gaps.insert(index, gap);
3995                off_surface = off_surface.max(gap);
3996            }
3997            // Inserts are independent global inversions too — re-run the repair
3998            // so a fold-flip introduced mid-refinement cannot poison the next
3999            // round's deviation interpolant.
4000            repair_branch_jumps(surface, &edge_points, &mut raw, tolerance)?;
4001            let rebuilt = build_interpolant_joined(surface, &raw, &parameters, &joins)?;
4002            pcurve = rebuilt.0;
4003            excursion = rebuilt.1;
4004            distance = rebuilt.2;
4005            if truncated {
4006                exit = PcurveFitExit::SampleCeiling;
4007                break;
4008            }
4009        }
4010        let residual = match converged_max {
4011            Some(measured) => measured,
4012            None => {
4013                station_residual(surface, evaluate_edge, &pcurve, &parameters, tolerance, &mut off_surface)?
4014            }
4015        };
4016        if station_fit_tracing() {
4017            eprintln!(
4018                "STATION-FIT pass raised={raised} exit={exit:?} samples={} residual={residual:.3e} off_surface={off_surface:.3e}",
4019                parameters.len()
4020            );
4021            if residual > tolerance + off_surface && (exit == PcurveFitExit::Converged || raised) {
4022                // Where the miss sits, and the uv track around it: the trace a
4023                // refusal needs to be attributed to a fold, a seam or the file.
4024                let (mut worst, mut at) = (0.0f64, 0usize);
4025                for (index, span) in parameters.windows(2).enumerate() {
4026                    let fraction = 0.5 * (span[0] + span[1]);
4027                    let uv = pcurve.evaluate(fraction)?;
4028                    let deviation = surface.evaluate_extended(uv.x, uv.y)?.sub(evaluate_edge(fraction)?).length();
4029                    if deviation > worst {
4030                        worst = deviation;
4031                        at = index;
4032                    }
4033                }
4034                let ([u0, u1], [v0, v1]) = surface_domains(surface)?;
4035                let (closed_u, closed_v) = surface_closedness(surface)?;
4036                eprintln!(
4037                    "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 {:?}",
4038                    at + 1,
4039                    surface.degree_u,
4040                    surface.degree_v,
4041                    surface.control_points.len(),
4042                    surface.control_points[0].len(),
4043                    surface.analytic().map(|_| "yes").unwrap_or("no")
4044                );
4045                {
4046                    let fraction = 0.5 * (parameters[at] + parameters[at + 1]);
4047                    let uv = pcurve.evaluate(fraction)?;
4048                    let image = surface.evaluate_extended(uv.x, uv.y)?;
4049                    let station = evaluate_edge(fraction)?;
4050                    let foot = project_point_to_surface(surface, station)?;
4051                    let seeded = project_point_to_surface_seeded(surface, station, raw[at][0], raw[at][1])?;
4052                    eprintln!(
4053                        "    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})",
4054                        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
4055                    );
4056                }
4057                let lo = at.saturating_sub(3);
4058                let hi = (at + 4).min(parameters.len() - 1);
4059                for index in lo..=hi {
4060                    eprintln!(
4061                        "    station {index}: fraction {:.6} uv ({:.6}, {:.6}) point ({:.4}, {:.4}, {:.4})",
4062                        parameters[index], raw[index][0], raw[index][1], edge_points[index].x, edge_points[index].y, edge_points[index].z
4063                    );
4064                }
4065            }
4066        }
4067        // Legacy only: a SpanFloor exit whose measured DEVIATION is on the
4068        // bar is promoted. In tracking mode the deviation sits at the standoff
4069        // whatever the unprobed narrow spans' TRACKING is, so SpanFloor stays
4070        // SpanFloor (unread); a tracking-mode fit is Converged only when every
4071        // span was probed within the ask AND the measured deviation meets the
4072        // floor (the exit's documented meaning, never the standoff bar).
4073        if !track_projection && exit == PcurveFitExit::SpanFloor && residual <= tolerance + off_surface {
4074            exit = PcurveFitExit::Converged;
4075        }
4076        if tracking_met && residual <= tolerance {
4077            exit = PcurveFitExit::Converged;
4078        }
4079        if exit != PcurveFitExit::Converged
4080            && !raised
4081            && (residual > tolerance + off_surface || tracking_unmet)
4082            && cap < PCURVE_RAISED_SAMPLES
4083        {
4084            raised = true;
4085            cap = PCURVE_RAISED_SAMPLES;
4086            // The raised pass is bounded by SAMPLES, not rounds: a kink
4087            // converges O(h²), a round per halving, and the three rounds of
4088            // the first pass are what left the 2026-09-18 census's fits over
4089            // their ask with budget to spare (RoundBudget at 158–400 of 2000
4090            // samples, measured 2026-09-26). Forty rounds cover every halving
4091            // the cap admits; a fit that is not converging stalls out first.
4092            rounds = RAISED_ROUNDS;
4093            continue;
4094        }
4095        return Ok(PcurveFit {
4096            curve: pcurve,
4097            report: PcurveFitReport {
4098                residual,
4099                floor: tolerance,
4100                samples: parameters.len(),
4101                exit,
4102                off_surface,
4103                raised,
4104                clamped_excursion: excursion,
4105                clamped_distance: distance,
4106            },
4107        });
4108    }
4109}
4110
4111/// [`fit_pcurve_on_surface_stations`] for the callers that only need the
4112/// curve, accepted or refused on its bar (`accept_fit`).
4113pub fn build_pcurve_on_surface_stations(
4114    surface: &NurbsSurface,
4115    stations: &dyn Fn(f64) -> Result<Vec3, String>,
4116    breaks: &[f64],
4117    tolerance: f64,
4118    base_samples: usize,
4119    refinement_rounds: usize,
4120    parameter_cap: usize,
4121) -> Result<NurbsCurve, String> {
4122    accept_fit(fit_pcurve_on_surface_stations(
4123        surface,
4124        stations,
4125        breaks,
4126        tolerance,
4127        base_samples,
4128        refinement_rounds,
4129        parameter_cap,
4130    )?)
4131}
4132
4133/// The largest 3D distance between `pcurve`'s image and its stations at the
4134/// quarter points of every span of `parameters` — out of sample by
4135/// construction, since the interpolant is exact at its nodes. Unclamped
4136/// evaluations; a station read over the running bar is inverted so that
4137/// `off_surface` covers the standoff AT the stations the residual is taken at,
4138/// not only at the nodes (a curve lifted off its plane by a bump stands
4139/// further off between two nodes than at either).
4140fn station_residual(
4141    surface: &NurbsSurface,
4142    stations: &dyn Fn(f64) -> Result<Vec3, String>,
4143    pcurve: &NurbsCurve,
4144    parameters: &[f64],
4145    tolerance: f64,
4146    off_surface: &mut f64,
4147) -> Result<f64, String> {
4148    let mut worst = 0.0_f64;
4149    let mut read = |fraction: f64| -> Result<(), String> {
4150        let uv = pcurve.evaluate(fraction)?;
4151        let represented = surface.evaluate_extended(uv.x, uv.y)?;
4152        let station = stations(fraction)?;
4153        let deviation = represented.sub(station).length();
4154        worst = worst.max(deviation);
4155        if deviation > tolerance + *off_surface {
4156            *off_surface = off_surface.max(invert_checked(surface, station)?.1);
4157        }
4158        Ok(())
4159    };
4160    for span in parameters.windows(2) {
4161        for local in [0.25, 0.5, 0.75] {
4162            read(span[0] + (span[1] - span[0]) * local)?;
4163        }
4164    }
4165    Ok(worst)
4166}
4167