-
Notifications
You must be signed in to change notification settings - Fork 0
Add 3D mesh generation examples #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| use meshing::export::{faces_to_stl, tetrahedra_to_stl, tetrahedra_to_vtk}; | ||
| use meshing::marching_cubes::marching_cubes; | ||
| use meshing::pipeline::{octree_refined, surface_to_volume, voxel_refined}; | ||
| use meshing::Point3D; | ||
| use std::fs; | ||
|
|
||
| fn main() { | ||
| let min = Point3D { | ||
| index: 0, | ||
| x: -2.0, | ||
| y: -2.0, | ||
| z: -2.0, | ||
| }; | ||
| let max = Point3D { | ||
| index: 0, | ||
| x: 2.0, | ||
| y: 2.0, | ||
| z: 2.0, | ||
| }; | ||
|
|
||
| // --- Marching Cubes: sphere isosurface --- | ||
| println!("=== Marching Cubes (sphere) ==="); | ||
| let sphere = |x: f64, y: f64, z: f64| x * x + y * y + z * z - 1.0; | ||
| let faces = marching_cubes(15, 15, 15, min, max, &sphere, 0.0); | ||
| println!(" Faces: {}", faces.len()); | ||
| let stl = faces_to_stl(&faces, "marching_cubes_sphere"); | ||
| fs::write("examples/marching_cubes_sphere.stl", &stl).unwrap(); | ||
| println!(" -> examples/marching_cubes_sphere.stl"); | ||
|
|
||
| // --- Marching Cubes: torus isosurface --- | ||
| println!("\n=== Marching Cubes (torus) ==="); | ||
| let torus = |x: f64, y: f64, z: f64| { | ||
| let r_major = 1.0; | ||
| let r_minor = 0.4; | ||
| let q = ((x * x + y * y).sqrt() - r_major).powi(2) + z * z; | ||
| q - r_minor * r_minor | ||
| }; | ||
| let faces = marching_cubes(20, 20, 20, min, max, &torus, 0.0); | ||
| println!(" Faces: {}", faces.len()); | ||
| let stl = faces_to_stl(&faces, "marching_cubes_torus"); | ||
| fs::write("examples/marching_cubes_torus.stl", &stl).unwrap(); | ||
| println!(" -> examples/marching_cubes_torus.stl"); | ||
|
|
||
| // --- Surface to Volume (sphere) --- | ||
| println!("\n=== Surface to Volume (sphere) ==="); | ||
| let tets = surface_to_volume(8, 8, 8, min, max, &sphere, 0.0); | ||
| println!(" Tetrahedra: {}", tets.len()); | ||
| let stl = tetrahedra_to_stl(&tets, "surface_to_volume"); | ||
| fs::write("examples/surface_to_volume.stl", &stl).unwrap(); | ||
| let vtk = tetrahedra_to_vtk(&tets, "surface_to_volume"); | ||
| fs::write("examples/surface_to_volume.vtk", &vtk).unwrap(); | ||
| println!(" -> examples/surface_to_volume.stl, .vtk"); | ||
|
|
||
| // --- Octree Refined --- | ||
| println!("\n=== Octree Refined ==="); | ||
| let tets = octree_refined( | ||
| min, | ||
| max, | ||
| 2, | ||
| &|p| p.x * p.x + p.y * p.y + p.z * p.z < 1.5 * 1.5, | ||
| 2.0, | ||
| ); | ||
| println!(" Tetrahedra: {}", tets.len()); | ||
| let vtk = tetrahedra_to_vtk(&tets, "octree_refined"); | ||
| fs::write("examples/octree_refined.vtk", &vtk).unwrap(); | ||
| println!(" -> examples/octree_refined.vtk"); | ||
|
|
||
| // --- Voxel Refined --- | ||
| println!("\n=== Voxel Refined ==="); | ||
| let tets = voxel_refined( | ||
| min, | ||
| max, | ||
| 3, | ||
| 3, | ||
| 3, | ||
| &|p| p.x * p.x + p.y * p.y + p.z * p.z < 1.5 * 1.5, | ||
| 2.0, | ||
| ); | ||
| println!(" Tetrahedra: {}", tets.len()); | ||
| let vtk = tetrahedra_to_vtk(&tets, "voxel_refined"); | ||
| fs::write("examples/voxel_refined.vtk", &vtk).unwrap(); | ||
| println!(" -> examples/voxel_refined.vtk"); | ||
|
|
||
| println!("\nDone! View STL files with MeshLab/Blender, VTK files with ParaView."); | ||
| } | ||
|
Comment on lines
+84
to
+85
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| use meshing::{bowyer_watson_3d, Point3D}; | ||
|
|
||
| fn main() { | ||
| let cube = vec![ | ||
| Point3D { | ||
| index: 0, | ||
| x: 0.0, | ||
| y: 0.0, | ||
| z: 0.0, | ||
| }, | ||
| Point3D { | ||
| index: 1, | ||
| x: 1.0, | ||
| y: 0.0, | ||
| z: 0.0, | ||
| }, | ||
| Point3D { | ||
| index: 2, | ||
| x: 0.0, | ||
| y: 1.0, | ||
| z: 0.0, | ||
| }, | ||
| Point3D { | ||
| index: 3, | ||
| x: 1.0, | ||
| y: 1.0, | ||
| z: 0.0, | ||
| }, | ||
| Point3D { | ||
| index: 4, | ||
| x: 0.0, | ||
| y: 0.0, | ||
| z: 1.0, | ||
| }, | ||
| Point3D { | ||
| index: 5, | ||
| x: 1.0, | ||
| y: 0.0, | ||
| z: 1.0, | ||
| }, | ||
| Point3D { | ||
| index: 6, | ||
| x: 0.0, | ||
| y: 1.0, | ||
| z: 1.0, | ||
| }, | ||
| Point3D { | ||
| index: 7, | ||
| x: 1.0, | ||
| y: 1.0, | ||
| z: 1.0, | ||
| }, | ||
| ]; | ||
|
|
||
| let tetrahedra = bowyer_watson_3d(cube); | ||
| println!("3D Delaunay tetrahedralization of a unit cube:"); | ||
| println!(" Number of tetrahedra: {}", tetrahedra.len()); | ||
| for (i, tet) in tetrahedra.iter().enumerate() { | ||
| println!( | ||
| " Tet {}: ({}, {}, {}, {})", | ||
| i, tet.a.index, tet.b.index, tet.c.index, tet.d.index | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| use meshing::export::{ | ||
| faces_to_glb, faces_to_glb_quantized, faces_to_obj, faces_to_stl, tetrahedra_to_vtk, | ||
| }; | ||
| use meshing::marching_cubes::marching_cubes; | ||
| use meshing::pipeline::surface_to_volume; | ||
| use meshing::Point3D; | ||
| use std::fs; | ||
|
|
||
| fn main() { | ||
| let min = Point3D { | ||
| index: 0, | ||
| x: -2.0, | ||
| y: -2.0, | ||
| z: -2.0, | ||
| }; | ||
| let max = Point3D { | ||
| index: 0, | ||
| x: 2.0, | ||
| y: 2.0, | ||
| z: 2.0, | ||
| }; | ||
| let sphere = |x: f64, y: f64, z: f64| x * x + y * y + z * z - 1.0; | ||
|
|
||
| // Generate sphere surface mesh with marching cubes | ||
| println!("Generating sphere surface with marching cubes (resolution 20x20x20)..."); | ||
| let faces = marching_cubes(20, 20, 20, min, max, &sphere, 0.0); | ||
| println!(" Surface faces: {}", faces.len()); | ||
|
|
||
| // Export surface to STL | ||
| let stl = faces_to_stl(&faces, "sphere"); | ||
| fs::write("examples/sphere.stl", &stl).unwrap(); | ||
| println!(" Wrote examples/sphere.stl ({} bytes)", stl.len()); | ||
|
|
||
| // Export surface to OBJ | ||
| let obj = faces_to_obj(&faces); | ||
| fs::write("examples/sphere.obj", &obj).unwrap(); | ||
| println!(" Wrote examples/sphere.obj ({} bytes)", obj.len()); | ||
|
|
||
| // Export surface to GLB | ||
| let glb = faces_to_glb(&faces); | ||
| fs::write("examples/sphere.glb", &glb).unwrap(); | ||
| println!(" Wrote examples/sphere.glb ({} bytes)", glb.len()); | ||
|
|
||
| // Export surface to quantized GLB | ||
| let glb_q = faces_to_glb_quantized(&faces); | ||
| fs::write("examples/sphere_quantized.glb", &glb_q).unwrap(); | ||
| println!( | ||
| " Wrote examples/sphere_quantized.glb ({} bytes, {:.0}% of regular)", | ||
| glb_q.len(), | ||
| glb_q.len() as f64 / glb.len() as f64 * 100.0 | ||
| ); | ||
|
|
||
| // Generate volume mesh with surface_to_volume pipeline | ||
| println!("\nGenerating volume mesh with surface_to_volume pipeline (8x8x8)..."); | ||
| let tetrahedra = surface_to_volume(8, 8, 8, min, max, &sphere, 0.0); | ||
| println!(" Volume tetrahedra: {}", tetrahedra.len()); | ||
|
|
||
| // Export volume to VTK | ||
| let vtk = tetrahedra_to_vtk(&tetrahedra, "sphere_volume"); | ||
| fs::write("examples/sphere_volume.vtk", &vtk).unwrap(); | ||
| println!(" Wrote examples/sphere_volume.vtk ({} bytes)", vtk.len()); | ||
|
|
||
| println!("\nDone! Output files can be viewed with:"); | ||
| println!(" STL/OBJ/GLB -> MeshLab, Blender, https://gltf-viewer.donmccurdy.com/"); | ||
| println!(" VTK -> ParaView"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The README claims this example covers “All pipeline algorithms”, but
meshing::pipelinealso exposesrefine_tetrahedra(src/pipeline.rs) and this example doesn’t demonstrate it. Either includerefine_tetrahedrahere or reword this line to avoid implying complete coverage of the pipeline APIs.