1#[cfg(feature = "output")]
7pub mod output;
8
9#[cxx::bridge(namespace = "manifold_rs")]
10mod ffi {
11 unsafe extern "C++" {
13 include!("manifold_rs.h");
14
15 type Polygons;
16
17 fn size(self: &Polygons) -> usize;
19
20 fn get_as_slice(self: &Polygons, i: usize) -> &[f64];
22
23 type Manifold;
25
26 fn is_empty(self: &Manifold) -> bool;
27
28 fn slice(self: &Manifold, height: f64) -> UniquePtr<Polygons>;
30
31 fn project(self: &Manifold) -> UniquePtr<Polygons>;
33
34 fn sphere(radius: f64, segments: u32) -> UniquePtr<Manifold>;
36
37 fn cube(x_size: f64, y_size: f64, z_size: f64) -> UniquePtr<Manifold>;
39
40 fn cylinder(
42 radius_low: f64,
43 radius_high: f64,
44 height: f64,
45 segments: u32,
46 ) -> UniquePtr<Manifold>;
47
48 fn union_(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
50
51 fn intersection(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
53
54 fn difference(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
56
57 fn trim_by_plane(
59 self: &Manifold,
60 x: f64,
61 y: f64,
62 z: f64,
63 offset: f64,
64 ) -> UniquePtr<Manifold>;
65
66 fn hull(self: &Manifold) -> UniquePtr<Manifold>;
68
69 fn translate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
71
72 fn scale(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
74
75 fn rotate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
77
78 fn extrude(
80 multi_polygon_data: &[&[f64]],
81 height: f64,
82 n_divisions: u32,
83 twist_degrees: f64,
84 scale_top_x: f64,
85 scale_top_y: f64,
86 ) -> UniquePtr<Manifold>;
87
88 fn revolve(
90 multi_polygon_data: &[&[f64]],
91 circular_segments: u32,
92 revolve_degrees: f64,
93 ) -> UniquePtr<Manifold>;
94
95 fn refine(self: &Manifold, n: i32) -> UniquePtr<Manifold>;
97
98 fn refine_to_length(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
100
101 fn refine_to_tolerance(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
103
104 fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> UniquePtr<Manifold>;
106
107 fn smooth_out(
109 self: &Manifold,
110 min_sharp_angle: f64,
111 min_smoothness: f64,
112 ) -> UniquePtr<Manifold>;
113
114 fn calculate_normals(
116 self: &Manifold,
117 normal_idx: i32,
118 min_sharp_angle: f64,
119 ) -> UniquePtr<Manifold>;
120
121 type Mesh;
123
124 fn num_props(self: &Mesh) -> u32;
126
127 fn vertices(self: &Mesh) -> UniquePtr<CxxVector<f32>>;
129
130 fn indices(self: &Mesh) -> UniquePtr<CxxVector<u32>>;
132
133 fn mesh_from_manifold(manifold: &Manifold) -> UniquePtr<Mesh>;
135
136 fn manifold_from_mesh(mesh: &Mesh) -> UniquePtr<Manifold>;
138
139 fn mesh_from_vertices(vertices: &[f32], indices: &[u32]) -> UniquePtr<Mesh>;
144 }
145}
146
147pub enum BooleanOp {
149 Union,
151 Intersection,
153 Difference,
155}
156
157pub struct Polygons(cxx::UniquePtr<ffi::Polygons>);
159
160impl Polygons {
161 pub fn size(&self) -> usize {
163 self.0.size()
164 }
165
166 pub fn get_as_slice(&self, i: usize) -> &[f64] {
168 self.0.get_as_slice(i)
169 }
170}
171
172pub struct Manifold(cxx::UniquePtr<ffi::Manifold>);
174
175impl Manifold {
176 pub fn is_empty(&self) -> bool {
178 self.0.is_empty()
179 }
180
181 pub fn slice(&self, height: f64) -> Polygons {
183 Polygons(self.0.slice(height))
184 }
185
186 pub fn project(&self) -> Polygons {
188 Polygons(self.0.project())
189 }
190
191 pub fn trim_by_plane(&self, x: f64, y: f64, z: f64, offset: f64) -> Self {
193 Self(self.0.trim_by_plane(x, y, z, offset))
194 }
195
196 pub fn hull(&self) -> Self {
198 Self(self.0.hull())
199 }
200
201 pub fn translate(&self, x: f64, y: f64, z: f64) -> Self {
203 Self(self.0.translate(x, y, z))
204 }
205
206 pub fn scale(&self, x: f64, y: f64, z: f64) -> Self {
208 Self(self.0.scale(x, y, z))
209 }
210
211 pub fn rotate(&self, x: f64, y: f64, z: f64) -> Self {
213 Self(self.0.rotate(x, y, z))
214 }
215
216 pub fn sphere(radius: f64, segments: u32) -> Self {
218 Self(ffi::sphere(radius, segments))
219 }
220
221 pub fn cube(x_size: f64, y_size: f64, z_size: f64) -> Self {
223 Self(ffi::cube(x_size, y_size, z_size))
224 }
225
226 pub fn cylinder(radius_low: f64, radius_high: f64, height: f64, segments: u32) -> Self {
228 Self(ffi::cylinder(radius_low, radius_high, height, segments))
229 }
230
231 pub fn union(&self, b: &Self) -> Self {
233 Self(ffi::union_(self.inner(), b.inner()))
234 }
235
236 pub fn intersection(&self, b: &Self) -> Self {
238 Self(ffi::intersection(self.inner(), b.inner()))
239 }
240
241 pub fn difference(&self, b: &Self) -> Self {
243 Self(ffi::difference(self.inner(), b.inner()))
244 }
245
246 pub fn boolean_op(&self, b: &Self, op: crate::BooleanOp) -> Self {
248 match op {
249 crate::BooleanOp::Union => self.union(b),
250 crate::BooleanOp::Intersection => self.intersection(b),
251 crate::BooleanOp::Difference => self.difference(b),
252 }
253 }
254
255 pub fn extrude(
257 multi_polygon_data: &[&[f64]],
258 height: f64,
259 n_divisions: u32,
260 twist_degrees: f64,
261 scale_top_x: f64,
262 scale_top_y: f64,
263 ) -> Self {
264 Self(ffi::extrude(
265 multi_polygon_data,
266 height,
267 n_divisions,
268 twist_degrees,
269 scale_top_x,
270 scale_top_y,
271 ))
272 }
273
274 pub fn revolve(
276 multi_polygon_data: &[&[f64]],
277 circular_segments: u32,
278 revolve_degrees: f64,
279 ) -> Self {
280 Self(ffi::revolve(
281 multi_polygon_data,
282 circular_segments,
283 revolve_degrees,
284 ))
285 }
286
287 pub fn refine(self: &Manifold, n: i32) -> Self {
289 Self(self.0.refine(n))
290 }
291
292 pub fn refine_to_length(self: &Manifold, t: f64) -> Self {
294 Self(self.0.refine_to_length(t))
295 }
296
297 pub fn refine_to_tolerance(self: &Manifold, t: f64) -> Self {
299 Self(self.0.refine_to_tolerance(t))
300 }
301
302 pub fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> Self {
304 Self(self.0.smooth_by_normals(normal_idx))
305 }
306
307 pub fn smooth_out(self: &Manifold, min_sharp_angle: f64, min_smoothness: f64) -> Self {
309 Self(self.0.smooth_out(min_sharp_angle, min_smoothness))
310 }
311
312 pub fn calculate_normals(self: &Manifold, normal_idx: i32, min_sharp_angle: f64) -> Self {
314 Self(self.0.calculate_normals(normal_idx, min_sharp_angle))
315 }
316
317 pub fn to_mesh(&self) -> Mesh {
319 Mesh(ffi::mesh_from_manifold(&self.0))
320 }
321
322 pub fn from_mesh(mesh: Mesh) -> Self {
324 mesh.into()
325 }
326
327 fn inner(&self) -> &ffi::Manifold {
329 self.0.as_ref().unwrap()
330 }
331}
332
333pub struct Mesh(cxx::UniquePtr<ffi::Mesh>);
335
336impl Mesh {
338 pub fn new(vertices: &[f32], indices: &[u32]) -> Self {
340 let mesh = ffi::mesh_from_vertices(vertices, indices);
341 Self(mesh)
342 }
343
344 pub fn num_props(&self) -> u32 {
346 self.0.num_props()
347 }
348
349 pub fn vertices(&self) -> Vec<f32> {
351 let vertices_binding = self.0.vertices();
352 let vertices = vertices_binding.as_ref().unwrap().as_slice();
353 vertices.to_vec()
354 }
355
356 pub fn indices(&self) -> Vec<u32> {
358 let indices_binding = self.0.indices();
359 let indices = indices_binding.as_ref().unwrap().as_slice();
360 indices.to_vec()
361 }
362
363 pub fn to_manifold(&self) -> Manifold {
365 let manifold = ffi::manifold_from_mesh(&self.0);
366 Manifold(manifold)
367 }
368}
369
370impl From<Mesh> for Manifold {
372 fn from(mesh: Mesh) -> Self {
373 mesh.to_manifold()
374 }
375}
376
377impl From<Manifold> for Mesh {
379 fn from(manifold: Manifold) -> Self {
380 manifold.to_mesh()
381 }
382}
383
384#[test]
385fn test_manifold_ffi() {
386 let sphere = ffi::sphere(1.0, 32);
387
388 let mesh = ffi::mesh_from_manifold(&sphere);
389
390 let vertices_binding = mesh.vertices();
391 let vertices = vertices_binding.as_ref().unwrap().as_slice();
392 assert!(!vertices.is_empty());
393
394 let indices_binding = mesh.indices();
395 let indices = indices_binding.as_ref().unwrap().as_slice();
396 assert!(!indices.is_empty());
397}