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