diff --git a/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt b/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt
index ae6c369494d..9778d0ccf99 100644
--- a/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt
+++ b/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt
@@ -261,9 +261,19 @@ run both methods on different types of input data.
The following example illustrates a basic run of the Marching Cubes algorithm, and in particular
the free function to create a domain from a %Cartesian grid, and the named parameter
that enables the user to switch from Marching Cubes to Topologically Correct Marching Cubes.
+The resulting triangle soup is converted to a triangle mesh, and is remeshed using
+the isotropic remeshing algorithm.
\cgalExample{Isosurfacing_3/marching_cubes.cpp}
+\cgalFigureAnchor{IsosurfacingMC}
+
+
+
+\cgalFigureCaptionBegin{IsosurfacingMC}
+Results of the Marching Cubes algorithm, and the final result after remeshing.
+\cgalFigureCaptionEnd
+
\subsection SubSecDCExample Dual Contouring
The following example illustrates a basic run of the %Dual Contouring algorithm, and in particular
diff --git a/Isosurfacing_3/doc/Isosurfacing_3/fig/MC.png b/Isosurfacing_3/doc/Isosurfacing_3/fig/MC.png
new file mode 100644
index 00000000000..9f0a930c7c0
Binary files /dev/null and b/Isosurfacing_3/doc/Isosurfacing_3/fig/MC.png differ
diff --git a/Isosurfacing_3/examples/Isosurfacing_3/marching_cubes.cpp b/Isosurfacing_3/examples/Isosurfacing_3/marching_cubes.cpp
index 2ca5984a58a..d1a23d92201 100644
--- a/Isosurfacing_3/examples/Isosurfacing_3/marching_cubes.cpp
+++ b/Isosurfacing_3/examples/Isosurfacing_3/marching_cubes.cpp
@@ -1,12 +1,18 @@
#include
+#include
#include
#include
#include
#include
-#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
using Kernel = CGAL::Simple_cartesian;
@@ -21,25 +27,32 @@ using Domain = CGAL::Isosurfacing::Marching_cubes_domain_3;
using Point_range = std::vector;
using Polygon_range = std::vector >;
+using Mesh = CGAL::Surface_mesh;
+
+auto value_fn = [](const Point& p) -> FT
+{
+ const FT& x = p.x(), y = p.y(), z = p.z();
+
+ // "Klein Bottle" - https://www-sop.inria.fr/galaad/surface/
+ return -1-4*y*z*z*x*x-2*y+6*z*z*x*x*y*y-16*x*z+16*x*z*y*y+3*x*x+7*y*y+11*z*z-11*z*z*z*z+z*z*z*z*z*z-3*x*x*x*x-7*y*y*y*y+x*x*x*x*x*x+y*y*y*y*y*y-14*z*z*x*x-18*z*z*y*y+3*z*z*z*z*x*x+3*z*z*z*z*y*y-10*x*x*y*y-4*y*y*y*z*z+3*z*z*x*x*x*x+3*z*z*y*y*y*y+16*x*x*x*z+3*x*x*x*x*y*y+3*x*x*y*y*y*y+4*x*x*y-12*z*z*y-2*x*x*x*x*y-4*x*x*y*y*y-2*z*z*z*z*y+16*x*z*z*z+12*y*y*y-2*y*y*y*y*y-32*x*z*y;
+};
+
int main(int argc, char** argv)
{
- const FT isovalue = (argc > 1) ? std::stod(argv[1]) : 0.8;
+ const FT isovalue = (argc > 1) ? std::stod(argv[1]) : 0.1;
+ const FT box_c = (argc > 2) ? std::abs(std::stod(argv[2])) : 5.;
+ const std::size_t grid_n = (argc > 3) ? std::stoi(argv[3]) : 50;
// create bounding box and grid
- const CGAL::Bbox_3 bbox { -1., -1., -1., 1., 1., 1. };
- Grid grid { bbox, CGAL::make_array(30, 30, 30) };
+ const CGAL::Bbox_3 bbox { -box_c, -box_c, -box_c, box_c, box_c, box_c };
+ Grid grid { bbox, CGAL::make_array(grid_n, grid_n, grid_n) };
std::cout << "Span: " << grid.span() << std::endl;
std::cout << "Cell dimensions: " << grid.spacing()[0] << " " << grid.spacing()[1] << " " << grid.spacing()[2] << std::endl;
std::cout << "Cell #: " << grid.xdim() << ", " << grid.ydim() << ", " << grid.zdim() << std::endl;
// fill up values
- auto sphere_value_fn = [](const Point& p) -> FT
- {
- return sqrt(p.x()*p.x() + p.y()*p.y() + p.z()*p.z());
- };
-
- Values values { sphere_value_fn, grid };
+ Values values { value_fn, grid };
// Below is equivalent to:
// Domain domain { grid, values };
@@ -53,9 +66,28 @@ int main(int argc, char** argv)
CGAL::Isosurfacing::marching_cubes(domain, isovalue, points, triangles,
CGAL::parameters::use_topologically_correct_marching_cubes(true));
- std::cout << "Output #vertices: " << points.size() << std::endl;
- std::cout << "Output #triangles: " << triangles.size() << std::endl;
- CGAL::IO::write_polygon_soup("marching_cubes.off", points, triangles);
+ std::cout << "Soup #vertices: " << points.size() << std::endl;
+ std::cout << "Soup #triangles: " << triangles.size() << std::endl;
+
+ if(!CGAL::Polygon_mesh_processing::is_polygon_soup_a_polygon_mesh(triangles)) {
+ std::cerr << "Warning: the soup is not a 2-manifold surface, non-manifoldness?..." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Convert the soup to a triangle mesh..." << std::endl;
+ Mesh mesh;
+ CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, triangles, mesh);
+
+ CGAL::IO::write_polygon_mesh("marching_cubes.off", mesh, CGAL::parameters::stream_precision(17));
+
+ // Let's remesh it to something nicer looking
+ std::cout << "Remeshing..." << std::endl;
+ const FT target_edge_length = box_c / 50;
+ CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(mesh), target_edge_length, mesh,
+ CGAL::parameters::number_of_iterations(5)
+ .number_of_relaxation_steps(5));
+
+ CGAL::IO::write_polygon_mesh("marching_cubes-remeshed.off", mesh, CGAL::parameters::stream_precision(17));
std::cout << "Done" << std::endl;