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
//! MC33's face rule: Nielson & Hamann's asymptotic decider.
//!
//! Nielson, G. M. and Hamann, B., *The Asymptotic Decider: Resolving the
//! Ambiguity in Marching Cubes*, Proceedings of Visualization '91, pp. 83–91
//! (`10.1109/visual.1991.175782`).
//!
//! # What it decides
//!
//! An **ambiguous face** has alternating corner signs, so all four of its edges
//! are cut and the two inside corners can be either joined across the face or
//! separated. Marching Cubes proper always separates them (see
//! [`super::table`]). That choice is crack-free, because it is a function of the
//! face's own four corner signs, but it is arbitrary: it agrees with the field's
//! own bilinear interpolant on the face only by luck.
//!
//! The decider replaces it with the interpolant's own answer. On the unit square
//! the bilinear function has a single saddle point, and the sign of the function
//! *at that saddle* says which pair of diagonally opposite corners the level set
//! leaves connected. For corner values `v0..v3` counter-clockwise, with the
//! diagonals `{v0, v2}` and `{v1, v3}`:
//!
//! ```text
//! S = (v0·v2 − v1·v3) / (v0 + v2 − v1 − v3)
//! ```
//!
//! # Why there is no division and no epsilon
//!
//! On an ambiguous face one diagonal is strictly negative — this crate's inside
//! — and the other is non-negative, because a sample of exactly zero counts as
//! outside (`crate::cube::is_inside`). So the denominator is a strictly negative
//! sum minus a non-negative one, or the reverse: **it can never be zero**, and
//! its sign is known from the signs alone. The implementation brief's "guard the
//! denominator near zero" is unnecessary here, for the same reason
//! `crate::cube::edge_offset` needs no epsilon.
//!
//! Only `sign(S)` is wanted, and with the denominator's sign already known that
//! reduces to comparing the two diagonal products. Writing `d_in` for the
//! product of the inside diagonal and `d_out` for the outside one, both branches
//! of the derivation collapse to the same test:
//!
//! ```text
//! joined ⟺ d_in > d_out
//! ```
//!
//! Ties resolve to *separated*, matching Marching Cubes. `d_in == d_out` is
//! `S == 0` exactly: the two branches of the hyperbola degenerate into crossing
//! straight lines and the regions meet at a single point, so either answer is
//! defensible and the one that changes nothing is preferred.
//!
//! # Why this is still crack-free
//!
//! Two cells meeting on a face read the *same four sample values*, in orders
//! that differ by a rotation and a reflection — the shared face is
//! counter-clockwise-from-outside for each of them, and their outsides are
//! opposite. Neither transformation changes which diagonal is which, and IEEE
//! multiplication is commutative and correctly rounded, so `v0·v2` and `v2·v0`
//! are the same bits. The two cells therefore cannot disagree.
//! `the_decider_is_invariant_under_rotation_and_reflection` is that argument as
//! a test.
use crateReal;
use crate;
use face_bit;
/// How a cell resolves an ambiguous face.
///
/// Both settings are crack-free. They differ in which surface they produce
/// there, and therefore in the topology of the result — see A-002's archive
/// entry for the measured difference.
/// Does the surface leave the face's two inside corners joined?
///
/// `v` is the face's four corner values, counter-clockwise as seen from outside
/// the cube — the order [`crate::cube::face_corners`] produces. The result is
/// invariant under rotating or reflecting that order, which is what lets two
/// adjacent cells agree.
///
/// # Panics
///
/// In debug builds, if the face is not ambiguous. There is nothing to decide
/// then, and asking would mean the caller has confused a face's identity.
/// The per-face resolution mask for one cell, over the faces `ambiguous` marks.
///
/// Bit layout is [`face_bit`]'s. Faces outside `ambiguous` are left clear, since
/// [`super::table::segment_links`] ignores them anyway and leaving them clear
/// keeps the mask canonical for the validator.
///
/// Public because a cell's decision is not visible in the mesh it produces and
/// the only way to *show* the rule firing is to ask for it: `E-102` draws a box
/// round every cell with an ambiguous face and colours it by this answer. Pass
/// [`super::table::AMBIGUOUS_FACES`]`[case]` as `ambiguous`.
///
/// # Panics
///
/// In debug builds, if `ambiguous` marks a face that is not ambiguous for these
/// corner values — see [`face_is_joined`].