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
//--- Copyright (C) 2025 Saki Komikado <komietty@gmail.com>
//--- This Source Code Form is subject to the terms of the Mozilla Public
//--- License v.2.0.
//! The mesh boolean, absorbed from `boolmesh` 0.1.9 (ADR 0047).
//!
//! Absorbed rather than depended upon so that the defects and the hot
//! paths are reachable: over 99% of a boolean's runtime is inside
//! [`compute_boolean`], which upstream exposes as a single opaque call.
//! See `docs/adr/0047-absorb-mesh-boolean.md` for the full reasoning and
//! the measurements behind it.
//!
//! # Provenance
//!
//! Upstream is <https://github.com/komietty/boolmesh> by Saki Komikado,
//! MPL-2.0, a from-scratch Rust implementation of the algorithm described
//! by Elalish's Manifold. Every file in this module keeps its original
//! copyright header. Axiolid is MPL-2.0 itself, so absorbing adds no
//! licence obligation the project has not already accepted -- but those
//! headers must survive refactoring.
//!
//! # What was not absorbed
//!
//! Upstream's `compose` module (cube, sphere, torus, cone, cylinder,
//! extrude, fractal) is deliberately absent. Axiolid has its own
//! primitives and profile extrusion; a second set would be a second
//! answer to one question.
pub
pub
pub
pub
pub
pub
// Absorbed modules import these through the module root, exactly as they did
// through upstream's crate root. Keeping the re-export means the absorbed
// files need no import rewriting beyond `crate::` -> `crate::csg::`.
pub use *;
pub use *;
use ;
use boolean45;
use ;
use simplify_topology;
use triangulate;
pub use ;
pub use Manifold;
/// The boolean's result as plain geometry.
///
/// `compute_boolean` used to end by feeding its result back through
/// `Manifold::new_impl`, which sorts faces into Morton order, builds a
/// half-edge mesh, a BVH, and a coplanar-face index, then validates
/// two-manifoldness. The provider reads none of that: `from_manifold`
/// takes positions and triangles and nothing else, and the provider
/// re-checks orientation itself.
///
/// Returning the geometry directly skips that whole rebuild. The
/// validity it used to assert is not lost -- see `compute_boolean`.
pub
/// Boolean of two closed, oriented manifolds.
///
/// Returns plain geometry rather than a rebuilt [`Manifold`]. Upstream
/// ended by calling `Manifold::new_impl` on the result, which sorts the
/// faces into Morton order, rebuilds a half-edge mesh, builds a BVH and
/// a coplanar-face index, and validates two-manifoldness. The provider
/// consumes none of it: `from_manifold` read only positions and
/// triangles, so every one of those structures was discarded on the
/// next line.
///
/// Two behaviours of that call did matter and are kept explicitly:
///
/// - An empty result was signalled by `new_impl` failing on an empty
/// position matrix, which the provider matches on to return the empty
/// solid. The same error is raised directly here.
/// - `new_impl` rejected a non-two-manifold result. `simplify_topology`
/// can in principle leave one, so the check is retained -- but on the
/// half-edge data the boolean already has, rather than on a fresh
/// half-edge mesh built solely to ask the question.
///
/// `fast_winding` selects [`boolean03_fast`] over [`boolean03`] for the
/// winding-number classification -- see `kernel03::winding03_fast`'s doc
/// comment for the guarantee and the trade-off. `false` reproduces exactly
/// what this function did before the fast path existed.
pub