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
// 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/.
//! The two surface channels behind the geometry fingerprint — split out of
//! `geom_hash.rs` to keep it under the house 400-line rule.
//!
//! ## Why the fingerprint is not over triangles
//!
//! A triangulator's DIAGONAL CHOICE is not a shape:
//! `tests/triangulation_invariance.rs` says outright that "nothing downstream
//! is entitled to depend on which one it gets". A fingerprint over triangles
//! does depend on it — a flat quad re-split along its other diagonal is a
//! different triangle set, and hashed differently. A triangle-based fingerprint
//! therefore reports an element as reshaped even when its vertices, surface,
//! area, centroid and bounding box are all identical, because one coplanar quad
//! was cut the other way.
//!
//! So [`super::GeometryHasher`] hashes a SURFACE instead, and the two things it
//! hashes are computed here: the identity of the PLANE a triangle lies in
//! together with that triangle's exact integer area ([`plane_of`]), and the
//! hash of one distinct quantized vertex ([`vertex_hash`]).
//!
//! Everything here is exact integer arithmetic over already-quantized
//! coordinates. That is the point: an area or a normal recomputed in floating
//! point would land on either side of a rounding boundary depending on how the
//! surface happened to be cut, which is the very dependency being removed.
use ;
/// Fold one wide signed integer as its two 64-bit halves. Plane coefficients
/// are exact `i128` products of quantized coordinates and do not fit `i64`.
/// The cross product of two edges of a quantized triangle — twice its area
/// vector, exactly, in `i128` so the quantized-coordinate products cannot
/// overflow. `None` when the three corners are colinear (which includes the
/// coincident case), i.e. exactly when the triangle is degenerate after
/// quantization and carries no shape signal.
pub
/// Greatest common divisor, Euclid. `gcd(x, 0) == x`, so a normal with zero
/// components (every axis-aligned face) reduces correctly.
/// The exact plane a quantized triangle lies in, and its area weight.
///
/// `cross` is the integer cross product of two of the triangle's edges, so it
/// is `g * n` for the primitive (component-gcd-reduced) integer normal `n` and
/// a positive integer `g`. Reducing to `n` makes the key equal for every
/// triangle in the plane whatever its size, and `g` is then twice the
/// triangle's area in units of `|n|` — the same unit for every triangle in that
/// plane, so summing `g` per plane gives that plane's total area exactly, in
/// integers, with no float rounding anywhere.
///
/// The sign is canonicalised (first non-zero component positive) so a plane and
/// its opposite orientation key the same: winding is not shape.
pub
/// Key the plane of a non-degenerate quantized triangle. `cross` must be
/// non-zero; `point` is any corner of the triangle (all give the same key).
pub
/// Hash one distinct quantized vertex, for the commutative vertex-set sum.
pub