BREP_kernel 0.9.0

A boundary representation (BREP) geometry kernel for building CAD applications.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
//! General rolling-ball blends (Golovanov §4.9 + §6.9 surgery).
//!
//! The blend surface is the rational surface (4.9.1) built from three
//! curves: the two support curves cr(t) ⊂ F1 and cs(t) ⊂ F2 where a
//! sphere of radius ρ touches both faces, and the middle curve at the
//! intersection of the two tangent planes, weighted w(t) = cos(α/2)
//! (4.9.3).  The tangency system (4.9.2) + the section-plane constraint
//! (4.9.5) — the sphere center pinned to the normal plane of the edge —
//! is solved per station by Newton with a finite-difference Jacobian.
//!
//! Topology is rebuilt the §6.9 way, with NO tool solid and NO boolean:
//! each mating face's loop swaps the blended edge's coedge for a coedge
//! on its support curve (trimming the adjacent seam edge when the face
//! is a closed carrier with seam-in-one-loop topology), and the blend
//! face is inserted with its own seam.  Open edges take the same route
//! (`edge/open.rs`), and a whole SELECTION goes through `network.rs`, which
//! marches every stripe against the original solid and solves each shared
//! corner from its ball before anything is cut.

mod carve;
mod chain;
mod collapse;
mod corner;
mod edge;
mod fold;
mod miter;
mod network;
mod planar_chart;
mod restrict;
pub(super) mod rollover;
mod rollover_surgery;
pub(crate) mod runout;
mod stations;
mod rows;
mod track_fit;

thread_local! {
    static REFINE_OFF_FOR_TEST: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}

/// Whether the open march's local station refinement runs. Escape hatch
/// `BREP_BLEND_REFINE=0` restores the uniform ladder exactly; a test turns it
/// off for its own thread with `set_refinement_off_for_test`.
pub(crate) fn station_refinement_on() -> bool {
    std::env::var("BREP_BLEND_REFINE").as_deref() != Ok("0")
        && !REFINE_OFF_FOR_TEST.with(|off| off.get())
}

thread_local! {
    static BLEND_NOTES: std::cell::RefCell<Vec<String>> = const { std::cell::RefCell::new(Vec::new()) };
}

thread_local! {
    static EXACT_LANE_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static EXACT_REVOLUTION_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static EXACT_RIM_LANE_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static ACCEPT_ONCE_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static CHAIN_ARC_STATIONS_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static TAPER_NETWORK_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static ROLLOVER_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static EXACT_TRIM_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static UNEQUAL_MITER_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static NO_COMMON_BALL_STAR_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
    static CROSSED_RAILS_FOR_TEST: std::cell::Cell<Option<bool>> = const { std::cell::Cell::new(None) };
}

/// Off, the network names the stripe `crossed_rails` and the selection
/// falls through to the cutter composition, whose body is the union of the
/// canal removals (a ridge). `BREP_BLEND_CROSSED_RAILS=0` is the escape
/// hatch, `=1` forces it on; `set_crossed_rails_for_test` forces either way
/// on a test's thread.
const CROSSED_RAILS_DEFAULT: bool = true;

pub(crate) fn crossed_rails_on() -> bool {
    if let Some(forced) = CROSSED_RAILS_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_CROSSED_RAILS").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => CROSSED_RAILS_DEFAULT,
    }
}

/// Off, the network refuses `unequal_corner_radius` or `n_sided_corner` by
/// name as before. `BREP_BLEND_RIBBON_STAR=0` is the escape hatch, `=1`
/// forces it on; `set_no_common_ball_star_for_test` forces it on a test's
/// thread.
const NO_COMMON_BALL_STAR_DEFAULT: bool = true;

pub(crate) fn no_common_ball_star_on() -> bool {
    if let Some(forced) = NO_COMMON_BALL_STAR_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_RIBBON_STAR").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => NO_COMMON_BALL_STAR_DEFAULT,
    }
}

/// The corner has no common ball; the point both shared-face rails stop at is
/// their rail/rail point (`solve_rail_rail_point`), the seam between the blends
/// is marched on the larger stripe at the smaller stripe's own canal level, and
/// — the seam leaving the smaller strip through its side rail — the larger
/// stripe runs onto that side face and is closed by its section there (the
/// asymmetric miter's connector), so the side face gets two rail vertices.
/// `BREP_BLEND_UNEQUAL_MITER=0` is the escape hatch, `=1` forces it on;
/// `set_unequal_miter_for_test` forces it on a test's thread.
const UNEQUAL_MITER_DEFAULT: bool = true;

pub(crate) fn unequal_miter_on() -> bool {
    if let Some(forced) = UNEQUAL_MITER_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_UNEQUAL_MITER").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => UNEQUAL_MITER_DEFAULT,
    }
}

/// Off, the closed lane names the rollover and declines as it did when the
/// detection landed (`rollover.rs`), and the ladder falls through to the
/// cutter, whose body carries a crease. `BREP_BLEND_ROLLOVER=0` is the
/// escape hatch, `=1` forces it on; `set_rollover_for_test` forces either
/// way on a test's own thread.
const ROLLOVER_DEFAULT: bool = true;

pub(crate) fn rollover_on() -> bool {
    if let Some(forced) = ROLLOVER_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_ROLLOVER").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => ROLLOVER_DEFAULT,
    }
}

/// OPEN stripes: a straight edge between planar mates is one section
/// extruded, so the network marches its stations once and skips the ladder's
/// refinement, fold probe, dense centres and ball-resolve wall reading (the
/// wall is read off the exact rows instead); the body is the ladder's, byte
/// for byte. Landed behind this switch, off by default, until the census
/// promotes it: `BREP_BLEND_EXACT_LANE=1` turns it on, `=0` off; a test
/// forces either way on its own thread with `set_exact_lane_for_test`.
const EXACT_LANE_DEFAULT: bool = true;

/// The exact torus is not the fitted rows' body. `BREP_BLEND_EXACT_RIM=1` turns
/// it on, `=0` off; `set_exact_rim_lane_for_test` forces it on a test's own
/// thread.
const EXACT_RIM_LANE_DEFAULT: bool = true;

pub(crate) fn exact_rim_lane_on() -> bool {
    if let Some(forced) = EXACT_RIM_LANE_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_EXACT_RIM").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => EXACT_RIM_LANE_DEFAULT,
    }
}

pub(crate) fn exact_lane_on() -> bool {
    if let Some(forced) = EXACT_LANE_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_EXACT_LANE").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => EXACT_LANE_DEFAULT,
    }
}

/// The exact rows are not the fitted rows' bytes, so the lane landed behind
/// this switch OFF and was promoted ON by its census (the whole kernel
/// battery, the 96-case manifest at its baseline and the render HLR pins
/// with the switch on). `BREP_BLEND_EXACT_REVOLUTION=0` is the hatch back to
/// the fitted ladder, `=1` forces the lane; a test forces either way on its
/// own thread with `set_exact_revolution_for_test`. The lane declines by
/// name to the ladder (`count.march.exact_revolution_declined`) whenever its
/// witness does not hold.
const EXACT_REVOLUTION_DEFAULT: bool = true;

pub(crate) fn exact_revolution_on() -> bool {
    if let Some(forced) = EXACT_REVOLUTION_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_EXACT_REVOLUTION").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => EXACT_REVOLUTION_DEFAULT,
    }
}

/// The surgery lane's exact support trim (slice 1b of the box fillet's
/// hotspots): on an EXACT EXTRUSION row whose mate is a plane, the rail is
/// a straight line and the plane's (u, v) is affine, so the rail's support
/// trim is the straight line in uv between the feet of the rail's two ends,
/// read once as shipped at the pcurve floor (`exact_planar_trim`); the
/// march trim's read, the track refit and its three reads are skipped. The
/// line is not the refit's curve (two control points against its fitted
/// knots), so the body's pcurve bits move on every box-like fixture; the
/// lane shipped behind this switch, off, until its census (the surgery
/// record of 2026-10-11: battery, suites and case gate unchanged, one HLR
/// input digest moving in pcurve bytes with its drawing byte-identical)
/// re-pinned what moves, and it is ON by default since 2026-10-12.
/// `BREP_BLEND_EXACT_TRIM=0` is the escape hatch back to the refit road
/// (`=1` the lane, as before); `set_exact_trim_for_test` forces either way
/// on a test's own thread.
const EXACT_TRIM_DEFAULT: bool = true;

pub(crate) fn exact_trim_on() -> bool {
    if let Some(forced) = EXACT_TRIM_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_EXACT_TRIM").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => EXACT_TRIM_DEFAULT,
    }
}

/// Same landing rule and switch shape as [`exact_lane_on`]:
/// `BREP_BLEND_ACCEPT_ONCE=1` / `=0`, default below.
const ACCEPT_ONCE_DEFAULT: bool = true;

pub(crate) fn accept_once_on() -> bool {
    if let Some(forced) = ACCEPT_ONCE_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_ACCEPT_ONCE").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => ACCEPT_ONCE_DEFAULT,
    }
}

/// Equal-length chains are unchanged either way; unequal ones move their
/// stations, so it lands behind this switch until its census:
/// `BREP_BLEND_CHAIN_ARC_STATIONS=1` turns it on, `=0` off;
/// `set_chain_arc_stations_for_test` forces it on a test's own thread.
const CHAIN_ARC_STATIONS_DEFAULT: bool = false;

pub(crate) fn chain_arc_stations_on() -> bool {
    if let Some(forced) = CHAIN_ARC_STATIONS_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_CHAIN_ARC_STATIONS").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => CHAIN_ARC_STATIONS_DEFAULT,
    }
}

/// `BREP_BLEND_TAPER_NETWORK=0` is the escape hatch, `=1` forces it on;
/// `set_taper_network_for_test` forces it on a test's own thread.
const TAPER_NETWORK_DEFAULT: bool = true;

pub(crate) fn taper_network_on() -> bool {
    if let Some(forced) = TAPER_NETWORK_FOR_TEST.with(|forced| forced.get()) {
        return forced;
    }
    match std::env::var("BREP_BLEND_TAPER_NETWORK").as_deref() {
        Ok("0") => false,
        Ok("1") => true,
        _ => TAPER_NETWORK_DEFAULT,
    }
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum StripeRadius {
    Constant(f64),
    /// `(edge fraction, radius)` stops sorted by fraction, interpolated
    /// linearly between and held flat past the ends: `blend_edge_variable`'s
    /// convention, which the law entries sample into.
    Stops(Vec<(f64, f64)>),
}

impl StripeRadius {
    /// From a stop list: one constant when every stop carries the same
    /// radius (to 1e-12 relative, the single-edge lane's own test).
    pub(crate) fn from_stops(stops: &[(f64, f64)]) -> Self {
        let mut sorted = stops.to_vec();
        sorted.sort_by(|a, b| a.0.total_cmp(&b.0));
        match sorted.first() {
            Some(&(_, first)) if sorted.iter().all(|(_, r)| (r - first).abs() <= 1e-12 * (1.0 + first.abs())) => {
                StripeRadius::Constant(first)
            }
            _ => StripeRadius::Stops(sorted),
        }
    }

    /// The radius at an edge fraction in `[0, 1]` (clamped).
    pub(crate) fn at_fraction(&self, fraction: f64) -> f64 {
        match self {
            StripeRadius::Constant(radius) => *radius,
            StripeRadius::Stops(stops) => {
                let fraction = fraction.clamp(0.0, 1.0);
                if fraction <= stops[0].0 {
                    return stops[0].1;
                }
                for pair in stops.windows(2) {
                    if fraction <= pair[1].0 {
                        let width = (pair[1].0 - pair[0].0).max(1e-12);
                        return pair[0].1 + (pair[1].1 - pair[0].1) * (fraction - pair[0].0) / width;
                    }
                }
                stops[stops.len() - 1].1
            }
        }
    }

    /// The constant, for a constant law.
    pub(crate) fn constant(&self) -> Option<f64> {
        match self {
            StripeRadius::Constant(radius) => Some(*radius),
            StripeRadius::Stops(_) => None,
        }
    }

    /// The largest radius the law takes.
    pub(crate) fn largest(&self) -> f64 {
        match self {
            StripeRadius::Constant(radius) => *radius,
            StripeRadius::Stops(stops) => stops.iter().map(|(_, r)| *r).fold(0.0, f64::max),
        }
    }

    /// The law's END value at the edge's start (`at_start`) or finish: what
    /// the user asked for at that vertex, and the constant every corner solve
    /// there uses (C2).
    pub(crate) fn end(&self, at_start: bool) -> f64 {
        self.at_fraction(if at_start { 0.0 } else { 1.0 })
    }

    /// Whether every radius is positive and finite.
    pub(crate) fn is_positive(&self) -> bool {
        match self {
            StripeRadius::Constant(radius) => radius.is_finite() && *radius > 0.0,
            StripeRadius::Stops(stops) => !stops.is_empty() && stops.iter().all(|(_, r)| r.is_finite() && *r > 0.0),
        }
    }
}








/// Record what a blend that SHIPS needs its feature to say about it — today,
/// a march whose rails still stand off their carriers after its station
/// ladder and local refinement ran out. Drained per feature by the history
/// loop ([`take_blend_notes`]), beside the soundness acceptance's repairs.
pub(crate) fn record_blend_note(note: String) {
    BLEND_NOTES.with(|notes| notes.borrow_mut().push(note));
}

/// Take every blend note recorded on this thread since the last call.
/// Blending runs on the feature's own thread (no parallel march), so the
/// history loop's drain sees every note its feature recorded.
pub fn take_blend_notes() -> Vec<String> {
    BLEND_NOTES.with(|notes| std::mem::take(&mut *notes.borrow_mut()))
}

/// The ledger's length, and a way back to it: a lane that refuses takes back
/// the notes it recorded, so a note never describes a wall that did not ship.
pub(crate) fn blend_notes_mark() -> usize {
    BLEND_NOTES.with(|notes| notes.borrow().len())
}

pub(crate) fn blend_notes_truncate(mark: usize) {
    BLEND_NOTES.with(|notes| notes.borrow_mut().truncate(mark));
}

/// A fillet chain wall that SHIPPED short of the construction request its
/// accepted rung made (`KernelTolerances::model` on the wall between its
/// rails): which wall — the blend face's name and its exact surface — what
/// was asked, what the wall reads, and the typed budget that ran out.
#[derive(Clone, Debug)]
pub(crate) struct WallModelReport {
    pub(crate) name: Option<String>,
    pub(crate) surface: crate::NurbsSurface,
    pub(crate) request: f64,
    pub(crate) residual: f64,
    /// What else the lane measured that the message must say (an unaccepted
    /// rung's deficit, a ladder rung's local refinement), verbatim.
    pub(crate) detail: Option<String>,
    pub(crate) budget: crate::ApproximationBudget,
}

thread_local! {
    static BLEND_APPROXIMATIONS: std::cell::RefCell<Vec<WallModelReport>> = const { std::cell::RefCell::new(Vec::new()) };
}

thread_local! {
    static BLEND_OPERATION_DEPTH: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
}

/// One blend OPERATION's scope on this thread: every public blend entry point
/// (and the history loop, around each feature) holds one. The OUTERMOST
/// entry drops whatever an earlier operation recorded and nobody consumed —
/// a direct API caller consumes ([`take_blend_approximations`]) after the
/// operation whose reports it wants, before starting the next — while a
/// nested entry (a fillet's per-edge chain blend) clears nothing, so every
/// report of the operation in flight is kept, however many there are.
pub(crate) struct BlendOperation;

impl BlendOperation {
    pub(crate) fn enter() -> BlendOperation {
        BLEND_OPERATION_DEPTH.with(|depth| {
            if depth.get() == 0 {
                BLEND_APPROXIMATIONS.with(|reports| reports.borrow_mut().clear());
                timing::begin_operation();
            }
            depth.set(depth.get() + 1);
        });
        BlendOperation
    }
}

impl Drop for BlendOperation {
    fn drop(&mut self) {
        BLEND_OPERATION_DEPTH.with(|depth| {
            depth.set(depth.get().saturating_sub(1));
            if depth.get() == 0 {
                timing::end_operation();
            }
        });
    }
}

/// Phase timing of the blend lanes, on the same switch as the boolean's
/// `boolean.<stage>_ms` lines: set `BREP_PROFILE` and the outermost blend
/// operation prints one `blend.<measure>=<ms>` line per measure to stderr when
/// it ends. Off (one `Cell` read per hook), nothing is recorded.
///
/// Measures ACCUMULATE: a stage that runs per stripe, per rung or per
/// component adds to one entry and bumps its count, so the ledger reads as a
/// split of the operation, not as the worst instance. `timing.*` entries are
/// milliseconds, `count.*` entries are plain counters.
pub(crate) mod timing {
    use std::cell::{Cell, RefCell};
    use web_time::Instant;

    /// One ledger entry: the measure's name, its accumulated milliseconds
    /// (zero for a `count.*` entry) and how many times it was recorded.
    #[derive(Clone, Debug, PartialEq)]
    pub struct BlendTiming {
        pub measure: String,
        pub ms: f64,
        pub count: u64,
    }

    thread_local! {
        static CAPTURE: Cell<bool> = const { Cell::new(false) };
        static ENABLED: Cell<bool> = const { Cell::new(false) };
        static TO_STDERR: Cell<bool> = const { Cell::new(false) };
        static LEDGER: RefCell<Vec<BlendTiming>> = const { RefCell::new(Vec::new()) };
    }

    /// Turn the ledger on (or off) for the blend operations that FOLLOW on
    /// this thread; `BREP_PROFILE` turns it on for every operation.
    pub fn blend_timing_capture(on: bool) {
        CAPTURE.with(|capture| capture.set(on));
    }

    /// Take every entry recorded on this thread since the last call (or the
    /// last outermost operation's start), sorted by measure name.
    pub fn take_blend_timings() -> Vec<BlendTiming> {
        let mut entries = LEDGER.with(|ledger| std::mem::take(&mut *ledger.borrow_mut()));
        entries.sort_by(|a, b| a.measure.cmp(&b.measure));
        entries
    }

    /// Whether the hooks record anything right now.
    pub(crate) fn enabled() -> bool {
        ENABLED.with(|enabled| enabled.get())
    }

    pub(super) fn begin_operation() {
        let profile = std::env::var_os("BREP_PROFILE").is_some();
        TO_STDERR.with(|to_stderr| to_stderr.set(profile));
        let on = profile || CAPTURE.with(|capture| capture.get());
        ENABLED.with(|enabled| enabled.set(on));
        if on {
            LEDGER.with(|ledger| ledger.borrow_mut().clear());
        }
    }

    pub(super) fn end_operation() {
        if TO_STDERR.with(|to_stderr| to_stderr.get()) {
            let mut entries = LEDGER.with(|ledger| ledger.borrow().clone());
            entries.sort_by(|a, b| a.measure.cmp(&b.measure));
            for entry in entries {
                if entry.measure.starts_with("timing.") {
                    eprintln!("blend.{}={:.3} n={}", entry.measure, entry.ms, entry.count);
                } else {
                    eprintln!("blend.{}={}", entry.measure, entry.count);
                }
            }
        }
        ENABLED.with(|enabled| enabled.set(false));
    }

    fn add(measure: &str, ms: f64, count: u64) {
        LEDGER.with(|ledger| {
            let mut ledger = ledger.borrow_mut();
            match ledger.iter_mut().find(|entry| entry.measure == measure) {
                Some(entry) => {
                    entry.ms += ms;
                    entry.count += count;
                }
                None => ledger.push(BlendTiming { measure: measure.to_string(), ms, count }),
            }
        });
    }

    /// Add `ms` to a `timing.*` measure (one more occurrence).
    pub(crate) fn record_ms(measure: &str, ms: f64) {
        if enabled() {
            add(measure, ms, 1);
        }
    }

    /// Add `n` to a `count.*` measure.
    pub(crate) fn record_count(measure: &str, n: u64) {
        if enabled() {
            add(measure, 0.0, n);
        }
    }

    /// A stage timer: records its measure when stopped or dropped. Costs one
    /// flag read when the ledger is off.
    pub(crate) struct BlendTimer {
        measure: &'static str,
        started: Option<Instant>,
    }

    impl BlendTimer {
        pub(crate) fn start(measure: &'static str) -> BlendTimer {
            BlendTimer { measure, started: enabled().then(Instant::now) }
        }

        /// Milliseconds since the start (zero when the ledger is off).
        pub(crate) fn elapsed_ms(&self) -> f64 {
            self.started.map_or(0.0, |started| started.elapsed().as_secs_f64() * 1_000.0)
        }

        /// Record now and return the reading.
        pub(crate) fn stop(mut self) -> f64 {
            let ms = self.elapsed_ms();
            if self.started.take().is_some() {
                add(self.measure, ms, 1);
            }
            ms
        }
    }

    impl Drop for BlendTimer {
        fn drop(&mut self) {
            if let Some(started) = self.started.take() {
                add(self.measure, started.elapsed().as_secs_f64() * 1_000.0, 1);
            }
        }
    }
}
pub use timing::{blend_timing_capture, take_blend_timings, BlendTiming};
pub(crate) use timing::{record_count, BlendTimer};

/// Record a wall that ships with its request unmet. Written by the rung that
/// keeps its body; whether the body reaches a caller is decided at
/// consumption ([`take_blend_approximations`]), not here. Every report of
/// the operation in flight is kept (see [`BlendOperation`]).
pub(crate) fn record_wall_model_report(report: WallModelReport) {
    BLEND_APPROXIMATIONS.with(|reports| reports.borrow_mut().push(report));
}


/// Whether any wall-model report is waiting (the history loop reads the
/// returned bodies only then).
pub(crate) fn blend_approximations_pending() -> bool {
    BLEND_APPROXIMATIONS.with(|reports| !reports.borrow().is_empty())
}

/// Bit-identical surfaces: the same degrees, knots and homogeneous control
/// points, compared by their bits.
pub(crate) fn same_surface(a: &crate::NurbsSurface, b: &crate::NurbsSurface) -> bool {
    let bits = |values: &[f64]| values.iter().map(|value| value.to_bits()).collect::<Vec<_>>();
    a.degree_u == b.degree_u
        && a.degree_v == b.degree_v
        && bits(&a.knots_u) == bits(&b.knots_u)
        && bits(&a.knots_v) == bits(&b.knots_v)
        && a.control_points.len() == b.control_points.len()
        && a.control_points.iter().zip(&b.control_points).all(|(row_a, row_b)| {
            row_a.len() == row_b.len()
                && row_a.iter().zip(row_b).all(|(p, q)| {
                    [p.x, p.y, p.z, p.w].map(f64::to_bits) == [q.x, q.y, q.z, q.w].map(f64::to_bits)
                })
        })
}

/// Whether `face_name` names the report's wall: its exact name, or that
/// name with the `[k]` (decimal) suffix `ensure_unique_face_names` gives a
/// colliding name at registration. Nothing else: no prefix, no other suffix.
fn names_the_wall(face_name: &Option<String>, report_name: &Option<String>) -> bool {
    match (face_name, report_name) {
        (Some(face), Some(report)) => {
            face == report
                || face.strip_prefix(report.as_str()).and_then(|rest| rest.strip_prefix('[')).and_then(|rest| rest.strip_suffix(']')).is_some_and(
                    |index| !index.is_empty() && index.bytes().all(|byte| byte.is_ascii_digit()),
                )
        }
        (None, None) => true,
        _ => false,
    }
}

/// Consume EVERY wall-model report recorded on this thread since the last
/// call, in ONE snapshot, against ALL the bodies a call returned
/// (`(body name, solid)`): a report becomes a typed `blend.wall_model`
/// [`crate::Approximation`] on each body carrying its wall — a face with a
/// bit-identical surface AND the report's name, exactly or as registration
/// renamed it (`NAME[k]`) — and is dropped when no returned body carries it
/// (a lane that refused, a body a later step discarded). A wall carried by
/// two returned bodies (one surface, bit for bit, in both) is reported on
/// both: the reading is a property of that surface. Reports for one wall
/// collapse to the last. Never a match by name alone.
/// `take_blend_approximations(&[])` discards everything recorded (the
/// history loop's stale drain before a feature runs).
pub fn take_blend_approximations(bodies: &[(&str, &crate::BrepSolid)]) -> Vec<crate::Approximation> {
    let snapshot = BLEND_APPROXIMATIONS.with(|reports| std::mem::take(&mut *reports.borrow_mut()));
    let mut unique: Vec<WallModelReport> = Vec::new();
    for report in snapshot {
        unique.retain(|kept| !(kept.name == report.name && same_surface(&kept.surface, &report.surface)));
        unique.push(report);
    }
    let mut approximations = Vec::new();
    for (body, solid) in bodies {
        for report in &unique {
            let carried = solid.shells.iter().flat_map(|shell| &shell.faces).any(|face| {
                names_the_wall(&face.name, &report.name) && same_surface(&face.surface, &report.surface)
            });
            if carried {
                let wall = report.name.as_deref().unwrap_or("(unnamed)");
                let unaccepted = matches!(report.budget.reason, crate::BudgetReason::Unaccepted | crate::BudgetReason::Unread);
                let budget = match report.budget.mechanism {
                    crate::BudgetMechanism::LocalRounds => format!(
                        "local refinement stopped: {:?} after {} of {} rounds, {} of {} stations per segment",
                        report.budget.reason, report.budget.rounds_used, report.budget.rounds_limit,
                        report.budget.stations, report.budget.station_limit,
                    ),
                    crate::BudgetMechanism::StationRungs => format!(
                        "the open march's station ladder stopped: {:?} after {} of {} global station rungs, {} of {} stations",
                        report.budget.reason, report.budget.rounds_used, report.budget.rounds_limit,
                        report.budget.stations, report.budget.station_limit,
                    ),
                };
                let unknown = report.budget.unread > 0;
                let rails = report.budget.measured_component == crate::MeasuredComponent::Rails;
                let mut message = if !unaccepted && (rails || unknown) {
                    // A request that covers the rails and the wall says WHICH
                    // it measured, and never offers a partial reading as the
                    // worst: with unread intervals the worst is unknown.
                    let what = if rails {
                        format!("the fillet wall {wall}'s support rails stand")
                    } else {
                        format!("the fillet wall {wall} stands")
                    };
                    let against = if rails {
                        "off their exact construction (their carriers / the exact ball contacts)"
                    } else {
                        "from the rolling ball between its rails"
                    };
                    let reading = if unknown {
                        format!(
                            "an UNKNOWN distance {against}: {} interval(s) could not be read (the largest READABLE reading is {:.3e} mm, not the worst)",
                            report.budget.unread, report.residual
                        )
                    } else {
                        format!("{:.3e} mm {against}", report.residual)
                    };
                    format!(
                        "{what} {reading}, against a construction request of {:.3e} mm (accepted at the intersection-fit bar); {budget}",
                        report.request,
                    )
                } else if unaccepted {
                    format!(
                        "the blend wall {wall} ships from a rung that never met acceptance: its worst reading \
                         {:.3e} mm against its acceptance bar {:.3e} mm; {budget}",
                        report.residual, report.request,
                    )
                } else {
                    format!(
                        "the fillet wall {wall} stands {:.3e} mm from the rolling ball between its rails, against a \
                         construction request of {:.3e} mm (accepted at the intersection-fit bar); {budget}",
                        report.residual, report.request,
                    )
                };
                if let Some(detail) = &report.detail {
                    message = format!("{message} ({detail})");
                }
                approximations.push(crate::Approximation {
                    code: if unaccepted { "blend.wall_acceptance" } else { "blend.wall_model" }.to_string(),
                    body: body.to_string(),
                    measured: report.residual,
                    bar: report.request,
                    volume_bound: None,
                    edges: Vec::new(),
                    budget: Some(report.budget.clone()),
                    message,
                });
            }
        }
    }
    approximations
}


pub use chain::{blend_smooth_chain, blend_smooth_chain_if_closed};
pub(crate) use corner::round_concave_chain_corner;
pub use corner::round_convex_corner;
pub use edge::{blend_closed_edge, blend_edge_variable, blend_open_edge};
pub(crate) use collapse::is_full_width_collapse;
pub(crate) use planar_chart::{
    fit_planar_charts_to_trims, is_planar_chart_refusal, planar_chart_overrun,
};
pub(crate) use track_fit::PCURVE_OFF_FLOOR;
pub(crate) use edge::{consumed_band, is_consumed_snap, is_rail_collapse};
pub(crate) use network::{
    blend_star_network, blend_star_network_laws, blend_star_network_with_corner_policy, degenerate_corner_setbacks, mixed_convexity_corner, mixed_convexity_corners, selection_convexity, DegenerateSetback,
    MixedCorner,
};
pub(crate) use miter::{is_marched_fit_off_carriers, is_miter_support_overrun};
pub(crate) use runout::{build_runout_walls, plan_runout, take_runout_reports, RunoutPlan, RunoutWallReport};
pub(crate) use fold::{is_wall_fold, WALL_FOLDS};
pub(crate) use stations::is_ball_off_carrier;