Skip to main content

brep_kernel/geometry/
pcurve.rs

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