More DC tests

This commit is contained in:
Mael Rouxel-Labbé 2025-03-24 15:34:21 +01:00
parent dbdb9ec971
commit 76dbf05e36
2 changed files with 144 additions and 63 deletions

View File

@ -61,26 +61,6 @@ box(const typename K::Point_3& b,
return inside ? - d : d; return inside ? - d : d;
} }
// template <typename K>
// typename K::FT
// disk(const typename K::Point_3& c,
// const typename K::Vector_3& n,
// const typename K::FT r,
// const typename K::Point_3& q)
// {
// typename K::Plane_3 pl(c, n);
// typename K::Point_3 pq = pl.projection(q);
// typename K::FT sq_dpl = CGAL::squared_distance(q, pl);
// if(CGAL::squared_distance(pq, c) < CGAL::square(r))
// return CGAL::approximate_sqrt(sq_dpl);
// else
// return CGAL::approximate_sqrt(CGAL::square(CGAL::approximate_sqrt(CGAL::squared_distance(pq, c)) - r) + sq_dpl);
// }
// p is the center of the base disk // p is the center of the base disk
// q is the center of the top disk // q is the center of the top disk
template<typename K> template<typename K>
@ -95,7 +75,6 @@ infinite_cylinder(const typename K::Point_3& b,
return CGAL::approximate_sqrt(CGAL::squared_distance(pq, b)) - r; return CGAL::approximate_sqrt(CGAL::squared_distance(pq, b)) - r;
} }
// c is the center of the torus // c is the center of the torus
// n is the normal of the plane containing all centers of the tube // n is the normal of the plane containing all centers of the tube
// r is the small radius // r is the small radius

View File

@ -17,15 +17,17 @@
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h> #include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/Image_3.h> #include <CGAL/Image_3.h>
#include <CGAL/boost/graph/IO/OFF.h> #include <CGAL/boost/graph/IO/OFF.h>
#include <CGAL/Random.h>
#include <array> #include <array>
#include <deque> #include <deque>
#include <iostream> #include <iostream>
#include <functional>
namespace IS = CGAL::Isosurfacing; namespace IS = CGAL::Isosurfacing;
template <typename K> template <typename K>
void test_cube() void test_implicit_shape(std::function<typename K::FT(const typename K::Point_3&)> implicit_function)
{ {
using FT = typename K::FT; using FT = typename K::FT;
using Point = typename K::Point_3; using Point = typename K::Point_3;
@ -40,40 +42,6 @@ void test_cube()
using Point_range = std::vector<Point>; using Point_range = std::vector<Point>;
using Polygon_range = std::vector<std::array<std::size_t, 4> >; using Polygon_range = std::vector<std::array<std::size_t, 4> >;
using Mesh = CGAL::Surface_mesh<Point>;
auto implicit_function = [](const Point& q) -> FT
{
return IS::Shapes::box<K>(Point(-1,-1,-1), Point(1,1,1), q);
// ---
auto cyl = [](const Point& q) { return IS::Shapes::infinite_cylinder<K>(Point(0,0,0), Vector(0,0,1), 0.5, q); };
auto cube = [](const Point& q) { return IS::Shapes::box<K>(Point(-0.5,-0.5,-0.5), Point(0.5,0.5,0.5), q); };
auto cyl_and_cube = [&](const Point& q) { return IS::Shapes::shape_union<K>(cyl, cube, q); };
auto sphere = [](const Point& q) { return IS::Shapes::sphere<K>(Point(0,0,0.5), 1, q); };
return IS::Shapes::shape_difference<K>(cyl_and_cube, sphere, q);
// ---
auto box_1 = [](const Point& q) { return IS::Shapes::box<K>(Point(0,0,0), Point(1,1,1), q); };
auto box_2 = [](const Point& q) { return IS::Shapes::box<K>(Point(0.5,0.5,0.5), Point(1.5,1.5,1.5), q); };
return IS::Shapes::shape_union<K>(box_1, box_2, q);
// ---
return IS::Shapes::box<K>(Point(0,0,0), Point(1,2,3), q);
// ---
return IS::Shapes::torus<K>(Point(0,0,0), Vector(0,0,1), 0.25, 1, q);
// ---
return IS::Shapes::infinite_cylinder<K>(Point(0,0,0), Vector(1,1,1), 1, q);
// ---
auto sphere_1 = [](const Point& q) { return IS::Shapes::sphere<K>(Point(0,0,0), 1, q); };
auto sphere_2 = [](const Point& q) { return IS::Shapes::sphere<K>(Point(0,0,0.5), 1, q); };
return IS::Shapes::shape_union<K>(sphere_1, sphere_2, q);
};
const CGAL::Bbox_3 bbox = {-2., -2., -2., 2., 2., 2.}; const CGAL::Bbox_3 bbox = {-2., -2., -2., 2., 2., 2.};
const Vector spacing { 0.05, 0.05, 0.05 }; const Vector spacing { 0.05, 0.05, 0.05 };
const FT isovalue = 0; const FT isovalue = 0;
@ -83,13 +51,13 @@ auto implicit_function = [](const Point& q) -> FT
std::cout << "Kernel: " << typeid(K).name() << std::endl; std::cout << "Kernel: " << typeid(K).name() << std::endl;
Grid grid { bbox, spacing }; Grid grid { bbox, spacing };
Values values {implicit_function , grid }; Values values { implicit_function, grid };
Gradients gradients { values, 0.01 * spacing[0] }; Gradients gradients { values, 0.01 * spacing[0] };
Domain domain { grid, values, gradients }; Domain domain { grid, values, gradients };
Point_range points; Point_range points;
Polygon_range polygons; Polygon_range polygons;
IS::dual_contouring<CGAL::Parallel_if_available_tag>(domain, isovalue, points, polygons, CGAL::parameters::do_not_triangulate_faces(true)); // if you change that, change the array IS::dual_contouring<CGAL::Parallel_if_available_tag>(domain, isovalue, points, polygons, CGAL::parameters::do_not_triangulate_faces(true));
std::cout << "Output #vertices: " << points.size() << std::endl; std::cout << "Output #vertices: " << points.size() << std::endl;
std::cout << "Output #polygons: " << polygons.size() << std::endl; std::cout << "Output #polygons: " << polygons.size() << std::endl;
@ -121,8 +89,142 @@ auto implicit_function = [](const Point& q) -> FT
std::cout << "Check for degenerate faces..." << std::endl; std::cout << "Check for degenerate faces..." << std::endl;
assert(!has_degenerate_faces(mesh)); assert(!has_degenerate_faces(mesh));
std::cout << "Volume: " << CGAL::Polygon_mesh_processing::volume(mesh) << std::endl; const FT computed_volume = CGAL::Polygon_mesh_processing::volume(mesh);
assert(CGAL::abs(CGAL::Polygon_mesh_processing::volume(mesh) - FT(8)) < 1e-2); std::cout << "Computed Volume: " << computed_volume << std::endl;
// Brute force estimation of the volume
std::cout << "Estimating volume using Monte Carlo..." << std::endl;
const std::size_t num_samples = 1000000;
CGAL::Random rng(0);
std::size_t inside_count = 0;
for (std::size_t i = 0; i < num_samples; ++i) {
Point sample(rng.get_double(bbox.xmin(), bbox.xmax()),
rng.get_double(bbox.ymin(), bbox.ymax()),
rng.get_double(bbox.zmin(), bbox.zmax()));
if (implicit_function(sample) <= isovalue) {
++inside_count;
}
}
const FT bbox_volume = (bbox.xmax() - bbox.xmin()) * (bbox.ymax() - bbox.ymin()) * (bbox.zmax() - bbox.zmin());
const FT monte_carlo_volume = bbox_volume * static_cast<FT>(inside_count) / static_cast<FT>(num_samples);
std::cout << "Monte Carlo Estimated Volume: " << monte_carlo_volume << std::endl;
// Compare computed volume with Monte Carlo estimation
const FT tolerance = 1e-2 * bbox_volume;
assert(CGAL::abs(computed_volume - monte_carlo_volume) < tolerance);
std::cout << "Volume check passed!" << std::endl;
}
template <typename K>
void test_box()
{
auto box_function = [](const typename K::Point_3& q) {
return IS::Shapes::box<K>(typename K::Point_3(-1, -1, -1), typename K::Point_3(1, 1, 1), q);
};
test_implicit_shape<K>(box_function);
}
template <typename K>
void test_union_of_boxes()
{
auto union_of_boxes_function = [](const typename K::Point_3& q) {
auto box_1 = [](const typename K::Point_3& q) {
return IS::Shapes::box<K>(typename K::Point_3(0, 0, 0), typename K::Point_3(1, 1, 1), q);
};
auto box_2 = [](const typename K::Point_3& q) {
return IS::Shapes::box<K>(typename K::Point_3(0.5, 0.5, 0.5), typename K::Point_3(1.5, 1.5, 1.5), q);
};
return IS::Shapes::shape_union<K>(box_1, box_2, q);
};
test_implicit_shape<K>(union_of_boxes_function);
}
template <typename K>
void test_union_of_boxes_minus_sphere()
{
auto b1_b2_ms1_function = [](const typename K::Point_3& q) {
auto box_1 = [](const typename K::Point_3& q) {
return IS::Shapes::box<K>(typename K::Point_3(0, 0, 0), typename K::Point_3(1, 1, 1), q);
};
auto box_2 = [](const typename K::Point_3& q) {
return IS::Shapes::box<K>(typename K::Point_3(0.5, 0.5, 0.5), typename K::Point_3(1.5, 1.5, 1.5), q);
};
auto b1_and_b2 = [&](const typename K::Point_3& q) {
return IS::Shapes::shape_union<K>(box_1, box_2, q);
};
auto s1 = [](const typename K::Point_3& q) {
return IS::Shapes::sphere<K>(typename K::Point_3(0, 0, 0.5), 1, q);
};
return IS::Shapes::shape_difference<K>(b1_and_b2, s1, q);
};
test_implicit_shape<K>(b1_b2_ms1_function);
}
template <typename K>
void test_union_of_spheres()
{
auto union_of_spheres_function = [](const typename K::Point_3& q) {
auto sphere_1 = [](const typename K::Point_3& q) {
return IS::Shapes::sphere<K>(typename K::Point_3(0, 0, 0), 1, q);
};
auto sphere_2 = [](const typename K::Point_3& q) {
return IS::Shapes::sphere<K>(typename K::Point_3(0, 0, 0.5), 1, q);
};
return IS::Shapes::shape_union<K>(sphere_1, sphere_2, q);
};
test_implicit_shape<K>(union_of_spheres_function);
}
template <typename K>
void test_torus()
{
auto torus_function = [](const typename K::Point_3& q) {
return IS::Shapes::torus<K>(typename K::Point_3(0, 0, 0), typename K::Vector_3(0, 0, 1), 0.25, 1, q);
};
test_implicit_shape<K>(torus_function);
}
// template <typename K>
// void test_infinite_cylinder()
// {
// auto cylinder_function = [](const typename K::Point_3& q) {
// return IS::Shapes::infinite_cylinder<K>(typename K::Point_3(0, 0, 0), typename K::Vector_3(1, 1, 1), 1, q);
// };
// test_implicit_shape<K>(cylinder_function);
// }
// template <typename K>
// void test_cylinder_and_cube_minus_sphere()
// {
// auto cyl_cube_function = [](const typename K::Point_3& q) {
// auto cyl = [](const typename K::Point_3& q) {
// return IS::Shapes::infinite_cylinder<K>(typename K::Point_3(0, 0, 0), typename K::Vector_3(0, 0, 1), 0.5, q);
// };
// auto cube = [](const typename K::Point_3& q) {
// return IS::Shapes::box<K>(typename K::Point_3(-0.5, -0.5, -0.5), typename K::Point_3(0.5, 0.5, 0.5), q);
// };
// auto cyl_and_cube = [&](const typename K::Point_3& q) {
// return IS::Shapes::shape_union<K>(cyl, cube, q);
// };
// auto sphere = [](const typename K::Point_3& q) {
// return IS::Shapes::sphere<K>(typename K::Point_3(0, 0, 0.5), 1, q);
// };
// return IS::Shapes::shape_difference<K>(cyl_and_cube, sphere, q);
// };
// test_implicit_shape<K>(cyl_cube_function);
// }
template <typename K>
void test_implicit_shapes()
{
test_box<K>();
test_union_of_boxes<K>();
test_union_of_boxes_minus_sphere<K>();
test_union_of_spheres<K>();
test_torus<K>();
} }
template <typename K> template <typename K>
@ -190,10 +292,10 @@ void test_image()
int main(int, char**) int main(int, char**)
{ {
test_cube<CGAL::Simple_cartesian<double> >(); test_implicit_shapes<CGAL::Simple_cartesian<double>>();
test_image<CGAL::Simple_cartesian<double> >(); test_image<CGAL::Simple_cartesian<double>>();
test_cube<CGAL::Exact_predicates_inexact_constructions_kernel>(); test_implicit_shapes<CGAL::Exact_predicates_inexact_constructions_kernel>();
test_image<CGAL::Exact_predicates_inexact_constructions_kernel>(); test_image<CGAL::Exact_predicates_inexact_constructions_kernel>();
std::cout << "Done" << std::endl; std::cout << "Done" << std::endl;