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
// SPDX-License-Identifier: MPL-2.0
//! Constrained Delaunay triangulation with bounded quality refinement.
//!
//! # Why this exists
//!
//! The mesh boolean's retriangulation path was ear clipping. Ear clipping
//! terminates and it is fast, but it offers no angle guarantee: it fans from
//! whichever ear is convex, so a narrow opening near a far boundary corner
//! produces slivers whose aspect ratio is bounded only by the input's own
//! geometry. A sliver is not a cosmetic problem downstream -- normals of a
//! near-degenerate triangle are numerically meaningless, and every consumer
//! that shades, offsets, or measures from those normals inherits the error.
//!
//! This crate replaces "some valid triangulation" with a triangulation whose
//! quality is *stated and checked*:
//!
//! - every constraint edge survives as a union of output edges,
//! - the result is Delaunay away from the constraints (empty-circumcircle,
//! decided by the certified `incircle` predicate rather than by a
//! floating-point circumcircle test),
//! - with [`Quality`] refinement, interior angles meet a caller-chosen
//! minimum, or the call reports that it could not get there.
//!
//! # The guarantee is conditional, and says so
//!
//! Ruppert refinement does not terminate for every input. Two boundary
//! segments meeting at a small angle cannot be fixed by inserting interior
//! points: splitting one segment to fix the angle creates a shorter segment
//! that is itself too close to its neighbour, and the process diverges. This
//! implementation therefore carries an explicit Steiner budget and reports
//! [`RefineOutcome::Capped`] when it stops early. The triangulation is still
//! valid and still constrained-Delaunay when capped -- only the angle bound
//! is unmet. Silently returning a worse mesh than requested would make the
//! quality parameter a lie.
use Point2;
use ;
use ;
pub use triangulate;
pub use ;
pub use ;
/// A constraint edge, as indices into the input point slice.
///
/// Held as a pair rather than as two points so the caller's vertex identity
/// survives the triangulation: a consumer that knows "edge 3 was my window
/// head" can still find it in the output.
/// The proven sign of a predicate, or `Sign::Zero` when the configuration is
/// exactly degenerate.
///
/// The certified predicates escalate to exact arithmetic internally, so
/// `Uncertain` cannot survive a top-level call. Treating it as `Zero` rather
/// than unwrapping keeps this total: a degenerate answer is a real geometric
/// outcome here (three collinear points, four cocircular ones), and the
/// callers below all branch on strict positivity.
pub
/// Orientation of three points, decided exactly.
///
/// Wraps the certified predicate so the sign convention is stated once here
/// rather than re-derived at each call site.
pub
/// Whether `a`, `b`, `c` are exactly collinear.
pub
/// Whether `d` lies strictly inside the circumcircle of `a`, `b`, `c`.
///
/// `a`, `b`, `c` must be counter-clockwise; the caller guarantees that by
/// construction. Decided by the certified `incircle` predicate: a
/// floating-point circumcircle test flips sign on nearly-cocircular input,
/// and a flip decision made on a wrong sign can cycle forever.
pub