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 empty() -> UniquePtr<Manifold>;
36
37 fn tetrahedron() -> UniquePtr<Manifold>;
39
40 fn sphere(radius: f64, segments: u32) -> UniquePtr<Manifold>;
42
43 fn cube(x_size: f64, y_size: f64, z_size: f64) -> UniquePtr<Manifold>;
45
46 fn cylinder(
48 radius_low: f64,
49 radius_high: f64,
50 height: f64,
51 segments: u32,
52 ) -> UniquePtr<Manifold>;
53
54 fn union_(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
56
57 fn intersection(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
59
60 fn difference(a: &Manifold, b: &Manifold) -> UniquePtr<Manifold>;
62
63 fn trim_by_plane(
65 self: &Manifold,
66 x: f64,
67 y: f64,
68 z: f64,
69 offset: f64,
70 ) -> UniquePtr<Manifold>;
71
72 fn hull(self: &Manifold) -> UniquePtr<Manifold>;
74
75 fn translate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
77
78 fn scale(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
80
81 fn rotate(self: &Manifold, x: f64, y: f64, z: f64) -> UniquePtr<Manifold>;
83
84 fn extrude(
86 multi_polygon_data: &[&[f64]],
87 height: f64,
88 n_divisions: u32,
89 twist_degrees: f64,
90 scale_top_x: f64,
91 scale_top_y: f64,
92 ) -> UniquePtr<Manifold>;
93
94 fn revolve(
96 multi_polygon_data: &[&[f64]],
97 circular_segments: u32,
98 revolve_degrees: f64,
99 ) -> UniquePtr<Manifold>;
100
101 fn refine(self: &Manifold, n: i32) -> UniquePtr<Manifold>;
103
104 fn refine_to_length(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
106
107 fn refine_to_tolerance(self: &Manifold, t: f64) -> UniquePtr<Manifold>;
109
110 fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> UniquePtr<Manifold>;
112
113 fn smooth_out(
115 self: &Manifold,
116 min_sharp_angle: f64,
117 min_smoothness: f64,
118 ) -> UniquePtr<Manifold>;
119
120 fn calculate_normals(
122 self: &Manifold,
123 normal_idx: i32,
124 min_sharp_angle: f64,
125 ) -> UniquePtr<Manifold>;
126
127 type Mesh;
129
130 fn num_props(self: &Mesh) -> u32;
132
133 fn vertices(self: &Mesh) -> UniquePtr<CxxVector<f32>>;
135
136 fn indices(self: &Mesh) -> UniquePtr<CxxVector<u32>>;
138
139 fn mesh_from_manifold(manifold: &Manifold) -> UniquePtr<Mesh>;
141
142 fn manifold_from_mesh(mesh: &Mesh) -> UniquePtr<Manifold>;
144
145 fn mesh_from_vertices(vertices: &[f32], indices: &[u32]) -> UniquePtr<Mesh>;
150 }
151}
152
153pub enum BooleanOp {
155 Union,
157 Intersection,
159 Difference,
161}
162
163pub struct Polygons(cxx::UniquePtr<ffi::Polygons>);
165
166impl Polygons {
167 pub fn size(&self) -> usize {
169 self.0.size()
170 }
171
172 pub fn get_as_slice(&self, i: usize) -> &[f64] {
174 self.0.get_as_slice(i)
175 }
176}
177
178pub struct Manifold(cxx::UniquePtr<ffi::Manifold>);
180
181impl Manifold {
182 pub fn is_empty(&self) -> bool {
184 self.0.is_empty()
185 }
186
187 pub fn slice(&self, height: f64) -> Polygons {
189 Polygons(self.0.slice(height))
190 }
191
192 pub fn project(&self) -> Polygons {
194 Polygons(self.0.project())
195 }
196
197 pub fn trim_by_plane(&self, x: f64, y: f64, z: f64, offset: f64) -> Self {
199 Self(self.0.trim_by_plane(x, y, z, offset))
200 }
201
202 pub fn hull(&self) -> Self {
204 Self(self.0.hull())
205 }
206
207 pub fn translate(&self, x: f64, y: f64, z: f64) -> Self {
209 Self(self.0.translate(x, y, z))
210 }
211
212 pub fn scale(&self, x: f64, y: f64, z: f64) -> Self {
214 Self(self.0.scale(x, y, z))
215 }
216
217 pub fn rotate(&self, x: f64, y: f64, z: f64) -> Self {
219 Self(self.0.rotate(x, y, z))
220 }
221
222 pub fn empty() -> Self {
224 Self(ffi::empty())
225 }
226
227 pub fn tetrahedron() -> Self {
229 Self(ffi::tetrahedron())
230 }
231
232 pub fn sphere(radius: f64, segments: u32) -> Self {
234 Self(ffi::sphere(radius, segments))
235 }
236
237 pub fn cube(x_size: f64, y_size: f64, z_size: f64) -> Self {
239 Self(ffi::cube(x_size, y_size, z_size))
240 }
241
242 pub fn cylinder(radius_low: f64, radius_high: f64, height: f64, segments: u32) -> Self {
244 Self(ffi::cylinder(radius_low, radius_high, height, segments))
245 }
246
247 pub fn union(&self, b: &Self) -> Self {
249 Self(ffi::union_(self.inner(), b.inner()))
250 }
251
252 pub fn intersection(&self, b: &Self) -> Self {
254 Self(ffi::intersection(self.inner(), b.inner()))
255 }
256
257 pub fn difference(&self, b: &Self) -> Self {
259 Self(ffi::difference(self.inner(), b.inner()))
260 }
261
262 pub fn boolean_op(&self, b: &Self, op: crate::BooleanOp) -> Self {
264 match op {
265 crate::BooleanOp::Union => self.union(b),
266 crate::BooleanOp::Intersection => self.intersection(b),
267 crate::BooleanOp::Difference => self.difference(b),
268 }
269 }
270
271 pub fn extrude(
273 multi_polygon_data: &[&[f64]],
274 height: f64,
275 n_divisions: u32,
276 twist_degrees: f64,
277 scale_top_x: f64,
278 scale_top_y: f64,
279 ) -> Self {
280 Self(ffi::extrude(
281 multi_polygon_data,
282 height,
283 n_divisions,
284 twist_degrees,
285 scale_top_x,
286 scale_top_y,
287 ))
288 }
289
290 pub fn revolve(
292 multi_polygon_data: &[&[f64]],
293 circular_segments: u32,
294 revolve_degrees: f64,
295 ) -> Self {
296 Self(ffi::revolve(
297 multi_polygon_data,
298 circular_segments,
299 revolve_degrees,
300 ))
301 }
302
303 pub fn refine(self: &Manifold, n: i32) -> Self {
305 Self(self.0.refine(n))
306 }
307
308 pub fn refine_to_length(self: &Manifold, t: f64) -> Self {
310 Self(self.0.refine_to_length(t))
311 }
312
313 pub fn refine_to_tolerance(self: &Manifold, t: f64) -> Self {
315 Self(self.0.refine_to_tolerance(t))
316 }
317
318 pub fn smooth_by_normals(self: &Manifold, normal_idx: i32) -> Self {
320 Self(self.0.smooth_by_normals(normal_idx))
321 }
322
323 pub fn smooth_out(self: &Manifold, min_sharp_angle: f64, min_smoothness: f64) -> Self {
325 Self(self.0.smooth_out(min_sharp_angle, min_smoothness))
326 }
327
328 pub fn calculate_normals(self: &Manifold, normal_idx: i32, min_sharp_angle: f64) -> Self {
330 Self(self.0.calculate_normals(normal_idx, min_sharp_angle))
331 }
332
333 pub fn to_mesh(&self) -> Mesh {
335 Mesh(ffi::mesh_from_manifold(&self.0))
336 }
337
338 pub fn from_mesh(mesh: Mesh) -> Self {
340 mesh.into()
341 }
342
343 fn inner(&self) -> &ffi::Manifold {
345 self.0.as_ref().unwrap()
346 }
347}
348
349pub struct Mesh(cxx::UniquePtr<ffi::Mesh>);
351
352impl Mesh {
354 pub fn new(vertices: &[f32], indices: &[u32]) -> Self {
356 let mesh = ffi::mesh_from_vertices(vertices, indices);
357 Self(mesh)
358 }
359
360 pub fn num_props(&self) -> u32 {
362 self.0.num_props()
363 }
364
365 pub fn vertices(&self) -> Vec<f32> {
367 let vertices_binding = self.0.vertices();
368 let vertices = vertices_binding.as_ref().unwrap().as_slice();
369 vertices.to_vec()
370 }
371
372 pub fn indices(&self) -> Vec<u32> {
374 let indices_binding = self.0.indices();
375 let indices = indices_binding.as_ref().unwrap().as_slice();
376 indices.to_vec()
377 }
378
379 pub fn to_manifold(&self) -> Manifold {
381 let manifold = ffi::manifold_from_mesh(&self.0);
382 Manifold(manifold)
383 }
384}
385
386impl From<Mesh> for Manifold {
388 fn from(mesh: Mesh) -> Self {
389 mesh.to_manifold()
390 }
391}
392
393impl From<Manifold> for Mesh {
395 fn from(manifold: Manifold) -> Self {
396 manifold.to_mesh()
397 }
398}
399
400#[test]
401fn test_manifold_ffi() {
402 let sphere = ffi::sphere(1.0, 32);
403
404 let mesh = ffi::mesh_from_manifold(&sphere);
405
406 let vertices_binding = mesh.vertices();
407 let vertices = vertices_binding.as_ref().unwrap().as_slice();
408 assert!(!vertices.is_empty());
409
410 let indices_binding = mesh.indices();
411 let indices = indices_binding.as_ref().unwrap().as_slice();
412 assert!(!indices.is_empty());
413}