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
// 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/.
//! Public, documented home for reading a [`Mesh`]'s volume.
use mesh_to_tris;
use signed_volume_of;
use crateMesh;
/// Signed volume of a `Mesh`, via the divergence theorem.
///
/// Positive for a closed, outward-wound mesh; negative if inward-wound;
/// meaningless if the mesh is not closed — the divergence theorem this sum
/// implements requires a closed surface, and an open one has no true volume
/// to read regardless of where it sits. That reading is translation-stable
/// only up to a bounded QUANTIZATION noise floor, not exactly
/// translation-invariant: [`mesh_to_tris`] rounds every coordinate to
/// `kernel::mesh_bridge::SNAP_GRID` (1/65536 m, ~15.26 µm) before this
/// function ever sees it, and a non-grid-aligned translation moves each
/// vertex's rounding independently, so the sum drifts by roughly
/// `surface_area * SNAP_GRID` (plus, at far-from-origin offsets, the
/// coarser f32-ulp term the `Mesh` positions already carried on the way in).
/// Because it delegates to `signed_volume6`, which sums about the
/// operand's own AABB centre rather than a fixed point, that drift is the
/// ONLY thing that moves the reading — a world-origin implementation would
/// additionally vary with the reference point itself, wrong by orders of
/// magnitude more (see the
/// `mesh_volume_is_stable_far_from_the_world_origin_for_an_open_mesh` test
/// below, which pins the AABB-centred reading's noise floor and would fail
/// hard against that class of regression). It is still not the mesh's actual
/// volume. Callers that need a trustworthy reading (e.g. reporting a split
/// zone piece's volume) must establish closedness first, same requirement
/// `signed_volume6` itself carries.
///
/// Delegates to `signed_volume_of` - itself one line over `signed_volume6`,
/// which returns SIX times the volume - rather than dividing here as well.
/// #2579 landed that helper an hour before this file did, with a doc that says
/// exactly why the divide belongs in one place: "a caller that wants the VOLUME
/// divides once, here, rather than growing a second hand-rolled sum in another
/// module, which is how two producers of the same number start to disagree."
///
/// The reference point is what makes the shared implementation matter:
/// `signed_volume6` deliberately sums about the OPERAND'S OWN AABB CENTRE
/// rather than the world origin. That
/// choice is not cosmetic — see `signed_volume::signed_volume6`'s doc for the
/// #198779 incident where a world-origin reference turned a crack sliver on a
/// far-from-origin operand into a wildly wrong, sign-flipping volume. A split
/// zone piece is exactly the shape of operand that provokes this: it can sit
/// anywhere in a building/national-grid-scale model and can carry the same
/// kind of boundary sliver from the cut that produced it, so this function
/// inherits the AABB-centred reference rather than exposing a second,
/// world-origin-referenced volume primitive alongside it.
///
/// This is a raw, UNGATED kernel primitive — it reads whatever `Mesh` it is
/// handed, closed or not, and (via [`mesh_to_tris`]) silently drops any
/// out-of-range-index or non-finite triangle. It is the low-level counterpart
/// to `geom_closure::GeometryHasher::volume`, which is the crate's
/// closedness-GATED, per-entity volume: that one returns `None` unless the
/// hasher's accumulated `GeometryClosure` proves the entity is a single
/// closed orientable solid, but it requires that accumulated per-entity
/// state — it has nothing to gate a bare, freshly-produced `Mesh` (e.g. a
/// zone-split piece) that never went through the hasher. A caller of THIS
/// function that needs the same trustworthiness guarantee must establish
/// closedness itself first — `router::voids::geom::mesh_is_closed_exact` is
/// the crate's existing closed-surface check but is `pub(super)`-scoped to
/// that module today, so a caller outside it needs either that visibility
/// widened or an equivalent check of its own — same requirement
/// `GeometryHasher::volume`'s own gate establishes upstream.
///
/// The other volume readings already in the crate were each wrong for this
/// job for a different reason: `router::voids::geom::mesh_signed_volume`
/// sums about the world origin (fine for its own callers, which only ever see
/// frame-local meshes near the origin — not true of an arbitrary zone piece),
/// and `kernel::mesh_bridge`'s `#[cfg(test)]`-only helper duplicates that same
/// world-origin arithmetic for test-only use. Reusing `signed_volume6`
/// avoids adding another divergence-theorem implementation to reconcile.