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
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//! Issue #3353 (`sweep_261`), Vid-space instrument — NOT a fix.
//!
//! `issue_3353_sweep_261_classification_tear.rs` (a `tests/` integration
//! test, `#[ignore]`d because it documents a known-open defect) records that
//! a prior instrumented run found, for this exact operand pair under
//! `Union`: `arr.unrecovered == 0` (the arrangement fully recovers every
//! input constraint — not a missing-constraint failure) alongside a
//! KEPT-triangle set that is non-manifold in pure Vid space, before any
//! float geometry is emitted — the undirected edges `(13,17)` used once and
//! `(14,17)`/`(13,14)` each used three times among the triangles
//! `boolean_vids` decided to KEEP.
//!
//! This module turns that one-off instrumented run into a standing,
//! re-runnable measurement.
//!
//! ## Why this cannot be a `tests/` integration test
//!
//! `boolean_vids`/`boolean_vids_components`/`BComponents` are declared
//! `pub(super) ` in `classify.rs` — visible only inside `kernel::arrangement`
//! (`classify.rs`'s parent module) and its descendants, never outside this
//! crate. Separately, the production entry points
//! (`kernel::mesh_bridge::union`/`boolean`) orient each operand with
//! `kernel::mesh_bridge::orient_outward`, which is `pub(crate)` — also
//! unreachable from an external integration-test crate. Both gaps close for
//! an in-crate `#[cfg(test)]` module, which is why this file is wired in
//! with the same `#[path = "..."] mod ...;` mechanism `classify_tests.rs`
//! already uses (see the bottom of `classify.rs`), rather than living under
//! `rust/geometry/tests/`.
//!
//! ## What this measures
//!
//! For the `sweep_261` operand pair, reproduced via the SAME construction
//! `kernel::mesh_bridge::union` runs internally
//! (`orient_outward(mesh_to_tris(mesh))` on each operand, then `arrange`,
//! then `boolean_vids`) rather than a hand-rolled substitute for either
//! step:
//!
//! 1. The kept-triangle Vid set `boolean_vids` returns, before
//! `to_f64_pt`/consolidation ever run.
//! 2. An undirected-edge census over those kept triangles in Vid space:
//! every edge's usage count, and specifically every edge whose count is
//! not exactly 2 — the Vid-space analogue of the `open_edges` check the
//! sibling `tests/issue_3353_*` files run on FLOAT geometry, run here one
//! layer earlier, on the symbolic triangles `boolean_vids` decided to
//! keep.
//! 3. Per over-used edge, which kept triangles share it and which operand
//! (A or B) each came from — origin is recovered by exact (unrotated)
//! membership against `arr.tris_a`/`arr.tris_b`, not by re-deriving
//! classification (see `origin_of`'s doc comment for why this is valid
//! for `Union`).
//!
//! ## Which regime decides each implicated triangle (measured)
//!
//! The edge census below says WHICH triangles disagree. This section records
//! WHY, from an instrumented run of `boolean_vids_components`'s own three-regime
//! chain over this exact arrangement. Every triangle on an over-used edge:
//!
//! ```text
//! edge (13,17) A[17] [15,13,17] |n|=6.11e-1 R3 inside_b=true keep=false
//! A[22] [17,13,14] |n|=6.56e-5 R1 dot=1.19e-4 keep=true
//! edge (13,14) A[15] [13,10,14] |n|=6.01e-6 R3 inside_b=false keep=true
//! B[17] [13,39,14] |n|=1.62e-4 R3 inside_a=true keep=false
//! B[18] [41,13,14] |n|=3.66e-5 R3 inside_a=false keep=true
//! edge (14,17) A[21] [14,11,17] |n|=1.03e0 R3 inside_b=false keep=true
//! B[66] [14,39,17] |n|=1.62e0 R3 inside_a=true keep=false
//! B[67] [42,14,17] |n|=1.15e0 R3 inside_a=false keep=true
//! ```
//!
//! The last column is the DECIDING test, so the B rows name the ray cast that
//! actually decided them. `c_on_or_near_a` — the B loop's dedup drop, which runs
//! first — returned false for all four, so none of them reached it.
//!
//! `A[22]` is the whole defect, and it is the ONLY triangle here decided by
//! regime 1. Edge `(13,17)` is bounded by exactly two A sub-triangles, `A[17]`
//! and `A[22]`, and they lie in ONE A face plane — Vids 13, 14, 15 and 17 are
//! exactly coplanar (`orient3d == 0`, not merely within a tolerance), on the
//! plane the original `a[2]` and `a[3]` share as the diagonal split of one box
//! face. Two sub-triangles of one flat face, and they disagree: the well-formed
//! one is dropped as inside B by the ray cast, the needle is kept by the
//! coincident-face regime. Dropping `A[22]` alone repairs all three edges:
//! `(13,17)` goes to 0, since `A[22]` is its only user, and the other two to 2.
//! So it is the single wrong verdict, not a symptom of several.
//!
//! And the ray cast agrees it should be dropped. Probed directly, `A[22]` has
//! `R3 inside_b == true` and `R2 solid_side == (true, true)`: regime 1 is
//! OVERRIDING a fallback that already had the right answer.
//!
//! ## Why regime 1 fires on it, and why that is the root cause
//!
//! `classify.rs`'s `on_surface_tri`/`near_on_surface_tri` establish "this is a
//! coincident SHARED face of the other operand" from the sub-triangle's CENTROID
//! alone: on the other face's plane (or within `NearBand`) and inside its
//! outline. `boolean_vids_components` then resolves that by NORMAL AGREEMENT,
//! `dot3(tri_normal, n_other) > 0.0`.
//!
//! A sub-triangle need not have its parent's plane. Retriangulation can leave
//! one DEGENERATE onto the line where the two parent planes MEET, at which point
//! its whole extent sits within the NEAR band of the other operand's plane
//! however transversal the two faces are. (Measured: the exact
//! `on_surface_normal` returns `None` here; only `near_on_surface_normal`
//! accepts it, at 1.86e-5 off the B face.) `A[22]` is exactly that: a needle whose two ends are
//! 8.4e-5 apart, sitting on the A-B plane intersection line, centroid 1.86e-5
//! from a B face and inside its outline. So regime 1 fires on a face pair that
//! is not coincident, and resolves it by the sign of a cross product a
//! near-collinear triple does not pin down (`|own_n| = 6.56e-5` against
//! `|n_other| = 3.4`). What it happens to yield is `cos = 5.32e-1`, 58 degrees:
//! nowhere near parallel, so there is no shared face to be co-oriented with.
//!
//! ## What was tried against that, and why none of it landed
//!
//! Coincidence is a property of the two INPUT faces, so the natural fix is to
//! ask it of the sub-triangle's PARENT face: carry the originating triangle on
//! the `Arrangement` and require the whole parent to lie on, or be flush within
//! the band of, the candidate face's plane. That is exact, threshold-free, and
//! strictly stricter than the centroid test, so a genuine shared face keeps its
//! verdict. Measured, against a corpus census whose baseline matches the golden
//! exactly:
//!
//! A second shape drops out of the same reading. Only the NEAR test accepts
//! `A[22]`, and `coplanar_a[22] == false`, so gating the A-side near call on the
//! coplanar-parent flag also takes it out of regime 1 — and that is what
//! `near_on_surface_normal`'s own doc claimed the code already did.
//!
//! ```text
//! sweep_261 union sweep census
//! parent-flush, A and B sides passes 98 -> 72 39 hosts regressed
//! parent-flush, A side only passes 98 -> 77 20 hosts regressed
//! near test gated on coplanar_a passes 98 -> 77 20 hosts regressed
//! parent NORMAL for the dot FAILS not run not run
//! flush test on the sub-tri FAILS not run not run
//! parent-flush, A side, 3 verts passes 98 -> 77 26 regressed, 9 improved
//! needle refused (area < 1e-6 parent) FAILS 98 -> 92 12 regressed, 3 improved
//! ```
//!
//! The last two rows were re-measured on 2026-09-04 with the parent index
//! carried on the `Arrangement` (patches kept off-tree). The all-vertex flush
//! gate fixes the target but also refuses the #1007 tilted-flush caps whose far
//! vertices leave the band: one host doubles its open edges (622 -> 1333) and
//! seven read "geometry lost". The needle gate is scale-free but a 1e-12 cut
//! in |n|^2 misses the very needle in `sweep_261` (its ratio is 3.7e-10), and
//! loosening it to catch that would be tuning a constant on one case. What a
//! fix still needs: a coincidence criterion that is a property of the parent
//! face yet tolerates a tilt of a few um across the face's extent, measured
//! against the corpus golden, with the 26-host row as the first thing to beat.
//!
//! (The two that fail `sweep_261` were not carried further; "not run" is not a
//! null result.)
//!
//! Why the rows read as they do:
//!
//! 1. The B side must NOT require it. `c_on_or_near_a` is a DEDUP drop, not an
//! orientation verdict, so making coincidence harder there leaves B copies of
//! genuinely shared faces alive next to the A copy — the 39-host run's
//! reasons are dominated by hosts GAINING triangles and open edges.
//! 2. The sliver has to LEAVE regime 1, not be re-oriented inside it: the
//! parent's normal gives the same sign, so substituting it changes nothing.
//! 3. Gating the near test costs MORE than the census row shows: it also breaks
//! two pinned near-band invariants in `tests/clash_intersection_oracle.rs`,
//! `no_surviving_near_band_triangle_has_an_x_facing_normal` and
//! `the_near_band_shortfall_is_a_missing_face_pair_not_a_shape_dependent_wedge`,
//! which need that path ungated. So the doc claiming the gate exists is
//! describing an intent the corpus has since contradicted, not a lost
//! invariant to restore.
//! 4. Both shapes that fix `sweep_261` improve every aggregate — the A-side
//! parent-flush one reads corpus unmatched edges 17863 -> 15992, strict-rule
//! edges 19344 -> 17612, torn hosts 165 -> 161 — while still regressing 20
//! pinned per-host rows, most of them reading "geometry lost". That is the
//! per-host golden doing its job: those hosts were watertight BECAUSE regime 1
//! kept a zero-area sliver on an arbitrary sign, and they have a pre-existing
//! tear the sliver was patching. Two independent shapes landing on the same
//! 20 is itself evidence the cost is that population, not either criterion.
//!
//! So the remaining work is not another criterion for regime 1. It is the tear
//! those hosts already carry, which today is masked. `various/rvt01.ifc` #7295,
//! #7544, #16805 and `ISSUE_129_...` #34385, #295370, #296868 are the ones that
//! lose the most geometry and are the place to start.
//!
//! ## Deliberately NOT changed
//!
//! No production function's signature, behaviour, or visibility changes.
//! This file only CALLS existing `pub(super)`/`pub(crate)` functions from a
//! new vantage point and post-processes their unmodified return values.
//!
//! ## CI-visible pin, not a `#[ignore]`d printout
//!
//! `sweep_261_kept_triangles_are_nonmanifold_in_vid_space` (below) runs in
//! normal `cargo test` (no `--ignored`) and asserts the DEFECT SHAPE
//! described above: `unrecovered == 0` together with at least one
//! kept-triangle edge whose Vid-space multiplicity is not 2.
//!
//! It deliberately does NOT assert the exact Vid numbers
//! `(13,17)`/`(14,17)`/`(13,14)` — those are Vid-interner allocation labels,
//! not geometry, and pinning them would fail on any relabelling for a reason
//! unrelated to the defect. The assertion stays on the SHAPE.
//!
//! The original reason given here was different, and is now spent: it said this
//! file's reproduction had never been executed (no `cargo test` was run to
//! produce it — the workstation that wrote it was disk-constrained), so the
//! labels were unverified. They have since been verified. Every number in the
//! regime table above comes from an instrumented run of this exact
//! reproduction, and the labels match. Leaving the old wording in would tell
//! the next reader the table directly above it is guesswork.
//!
//! The full kept set and edge census are printed, but CI will NOT show
//! them: `.github/workflows/test.yml` runs `cargo test --workspace` with no
//! `--nocapture`, and cargo suppresses stdout for a PASSING test — which
//! this is by design while the defect exists. Confirmed absent from the
//! first green run's log rather than assumed. To read the numbers:
//!
//! cargo test -p ifc-lite-geometry --lib issue_3353_vid_census -- --nocapture
//!
//! They have now been observed (see the regime table above); they are still
//! deliberately not pinned, for the relabelling reason given above.
//!
//! This is a characterisation pin of a KNOWN-DEFECTIVE state, not a health
//! check: a green tick on this test means "the defect still reproduces
//! exactly as documented," NOT "issue #3353 is fixed." Read together with
//! `sweep_261_overlapping_rotated_union_never_tears`'s `#[ignore]` in the
//! sibling file (which this patch does not touch and does not un-ignore),
//! the pair is meant to be unambiguous: that file documents the defect
//! end-to-end (ignored, because it fails outright), this one documents its
//! Vid-space signature (not ignored, because — until the defect is fixed —
//! it is expected to keep finding one). If `classify.rs` changes and this
//! test starts failing, that is the expected trigger to re-diagnose BOTH
//! files together, not to loosen either assertion.
//!
//! Refs #3353
use boolean_vids;
use crate;
use crateVid;
use crate;
use crateMesh;
use ;
use ;
/// `sweep_261`'s operand builder, verbatim from
/// `issue_3353_sweep_261_classification_tear.rs`'s `boxed()` (same
/// tessellation and corner/face order — load-bearing, per that file's doc
/// comment). Kept as a `Mesh` here (rather than emitting `Tri` directly) so
/// this file can feed it through the ACTUAL production `mesh_to_tris` +
/// `orient_outward` pair instead of duplicating their logic.
/// `sweep_261`'s exact operands, verbatim from
/// `issue_3353_sweep_261_classification_tear.rs`.
/// Which operand a kept Vid triangle came from, recovered by exact
/// (unrotated) membership against `arr.tris_a`/`arr.tris_b` rather than by
/// re-deriving classification. Valid for `Union` specifically: in
/// `boolean_vids_components` (`classify.rs`), `flip` is
/// `matches!(op, BoolOp::Difference)` only, so a kept `Union` triangle is
/// always pushed VERBATIM — either a `tris_a[i]` entry unchanged, or a
/// `tris_b[i]` entry unchanged. The one case where this could be ambiguous —
/// a true co-oriented A/B duplicate face — is exactly what `Union`'s own
/// dedup (the `a_kept`/`rotate_min_first` bookkeeping in
/// `boolean_vids_components`) already collapses to the A-copy before a B
/// duplicate is ever pushed, so any triangle actually present in `kept`
/// should resolve unambiguously against one `HashSet` or the other. The
/// test body below asserts that rather than assuming it silently.
/// Squared Euclidean distance between two points.
/// Closest point to `p` on the closed segment `[a, b]`. The zero-length case
/// is guarded explicitly: the projection divides by the squared segment
/// length, which would otherwise be `0.0 / 0.0`.
/// Closest point to `p` on the CLOSED (filled) triangle, not on its plane — a
/// centroid can be near a triangle's plane while far from the triangle itself.
/// Ericson's seven-region barycentric test. Its interior branch needs `va`,
/// `vb`, `vc` all positive, which needs strictly positive area, so a degenerate
/// triangle can never reach the final division; the guard below is explicit
/// rather than relying on that unstated invariant.
/// Minimum distance from `p` to any triangle of `mesh`. The operands here are
/// a handful of `boxed()` triangles, so a linear scan is adequate and avoids
/// the production BVH's own pruning.
/// Undirected Vid-space edge census over `kept`: canonical `(min(u,v),
/// max(u,v))` -> the `(index into kept, origin)` of every triangle that uses
/// it. A triangle contributes each of its 3 edges once; an edge's count
/// reaching anything other than 2 across `kept` is exactly the symbolic
/// (pre-float) signature of a classification-level tear.
/// See the module doc for the full rationale. Runs in normal `cargo test`
/// (no `--ignored`) and PINS the current, known-defective Vid-space shape:
/// a fully-recovered arrangement (`unrecovered == 0`) whose kept triangles
/// are nonetheless non-manifold in Vid space. A green tick here means "the
/// #3353 classification-level tear still reproduces exactly as documented,"
/// NOT "issue #3353 is fixed."