mirror of https://github.com/CGAL/cgal
testing file for implemented functions
This commit is contained in:
parent
d5a2cf1f05
commit
1fd56cdd1d
|
|
@ -69,7 +69,7 @@ create_single_source_cgal_program("self_intersection_polyhedron_test.cpp")
|
|||
create_single_source_cgal_program("self_intersection_surface_mesh_test.cpp")
|
||||
create_single_source_cgal_program("pmp_do_intersect_test.cpp")
|
||||
create_single_source_cgal_program("test_is_polygon_soup_a_polygon_mesh.cpp")
|
||||
create_single_source_cgal_program("test_interopolated_corrected_curvatures.cpp")
|
||||
create_single_source_cgal_program("test_interpolated_corrected_curvatures.cpp")
|
||||
create_single_source_cgal_program("test_stitching.cpp")
|
||||
create_single_source_cgal_program("remeshing_test.cpp")
|
||||
create_single_source_cgal_program("remeshing_with_isolated_constraints_test.cpp" )
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_mesh_processing/Curvatures/interpolated_corrected_curvature_measures.h>
|
||||
#include <CGAL/Polygon_mesh_processing/random_perturbation.h>
|
||||
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel EpicKernel;
|
||||
typedef CGAL::Surface_mesh<EpicKernel::Point_3> SMesh;
|
||||
typedef boost::graph_traits<SMesh>::face_descriptor face_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::edge_descriptor edge_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
void test(std::string mesh_path, EpicKernel::FT rel_expansion_radius, EpicKernel::FT rel_noise_magnitude) {
|
||||
SMesh pmesh;
|
||||
const std::string filename = CGAL::data_file_path(mesh_path);
|
||||
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, pmesh))
|
||||
{
|
||||
std::cerr << "Invalid input file." << std::endl;
|
||||
}
|
||||
|
||||
bool created = false;
|
||||
|
||||
SMesh::Property_map<vertex_descriptor, EpicKernel::FT> mean_curvature_map, gaussian_curvature_map;
|
||||
boost::tie(mean_curvature_map, created) = pmesh.add_property_map<vertex_descriptor, EpicKernel::FT>("v:mean_curvature_map", 0);
|
||||
assert(created);
|
||||
|
||||
boost::tie(gaussian_curvature_map, created) = pmesh.add_property_map<vertex_descriptor, EpicKernel::FT>("v:gaussian_curvature_map", 0);
|
||||
assert(created);
|
||||
|
||||
// getting the max and min edge lengthes
|
||||
const auto edge_range = CGAL::edges(pmesh);
|
||||
|
||||
const auto edge_length_comparator = [&, pmesh](auto l, auto r) {
|
||||
return PMP::edge_length(l, pmesh) < PMP::edge_length(r, pmesh);
|
||||
};
|
||||
|
||||
const edge_descriptor longest_edge = *std::max_element(edge_range.begin(), edge_range.end(), edge_length_comparator);
|
||||
const EpicKernel::FT max_edge_length = PMP::edge_length(longest_edge, pmesh);
|
||||
|
||||
const edge_descriptor shortest_edge = *std::min_element(edge_range.begin(), edge_range.end(), edge_length_comparator);
|
||||
const EpicKernel::FT min_edge_length = PMP::edge_length(shortest_edge, pmesh);
|
||||
|
||||
|
||||
if (rel_noise_magnitude > 0)
|
||||
{
|
||||
if (!CGAL::is_triangle_mesh(pmesh))
|
||||
return;
|
||||
|
||||
SMesh::Property_map<vertex_descriptor, EpicKernel::Vector_3> vnm;
|
||||
boost::tie(vnm, created) = pmesh.add_property_map<vertex_descriptor, EpicKernel::Vector_3>("v:vnm", { 0 , 0 , 0 });
|
||||
assert(created);
|
||||
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normals(pmesh, vnm);
|
||||
|
||||
PMP::random_perturbation(pmesh, rel_noise_magnitude * min_edge_length, CGAL::parameters::random_seed(0));
|
||||
PMP::interpolated_corrected_mean_curvature(
|
||||
pmesh,
|
||||
mean_curvature_map,
|
||||
CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length).vertex_normal_map(vnm)
|
||||
);
|
||||
PMP::interpolated_corrected_gaussian_curvature(
|
||||
pmesh,
|
||||
gaussian_curvature_map,
|
||||
CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length).vertex_normal_map(vnm)
|
||||
);
|
||||
}
|
||||
else {
|
||||
PMP::interpolated_corrected_mean_curvature(
|
||||
pmesh,
|
||||
mean_curvature_map,
|
||||
CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length)
|
||||
);
|
||||
PMP::interpolated_corrected_gaussian_curvature(
|
||||
pmesh,
|
||||
gaussian_curvature_map,
|
||||
CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//PMP::interpolated_corrected_mean_curvature(
|
||||
// pmesh,
|
||||
// mean_curvature_map,
|
||||
// CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length)
|
||||
//);
|
||||
//PMP::interpolated_corrected_gaussian_curvature(
|
||||
// pmesh,
|
||||
// gaussian_curvature_map,
|
||||
// CGAL::parameters::ball_radius(rel_expansion_radius * max_edge_length)
|
||||
//);
|
||||
|
||||
|
||||
const EpicKernel::FT max_mean_curvature = *std::max_element(mean_curvature_map.begin(), mean_curvature_map.end());
|
||||
const EpicKernel::FT min_mean_curvature = *std::min_element(mean_curvature_map.begin(), mean_curvature_map.end());
|
||||
const EpicKernel::FT max_gaussian_curvature = *std::max_element(gaussian_curvature_map.begin(), gaussian_curvature_map.end());
|
||||
const EpicKernel::FT min_gaussian_curvature = *std::min_element(gaussian_curvature_map.begin(), gaussian_curvature_map.end());
|
||||
|
||||
std::cout << "# " << mesh_path << ":\n"
|
||||
<< "expansion radius ratio to max length / expansion radius = " << rel_expansion_radius << " / " << rel_expansion_radius * max_edge_length << ",\n"
|
||||
<< "max perturbation ratio to minlength / max perturbation = " << rel_noise_magnitude << " / " << rel_noise_magnitude * min_edge_length << "\n"
|
||||
<< "mean curvature: min = " << min_mean_curvature << " <-> " << max_mean_curvature << " = max" << "\n"
|
||||
<< "gaussian curvature: min = " << min_gaussian_curvature << " <-> " << max_gaussian_curvature << " = max" << "\n\n\n";
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::vector<std::string> mesh_pathes_to_test = {
|
||||
"meshes/icc_test/Sphere Quads + Tris.obj",
|
||||
"meshes/icc_test/Sphere Quads + Tris 100352.obj",
|
||||
"meshes/icc_test/Sphere Tris Ico.obj",
|
||||
"meshes/icc_test/Sphere Tris Tet.obj",
|
||||
"meshes/icc_test/Sphere Tris Oct.obj",
|
||||
"meshes/icc_test/Sphere Quads.obj",
|
||||
"meshes/icc_test/Sphere Quads Remesh.obj",
|
||||
"meshes/icc_test/Sphere Ngons + Quads + Tris.obj",
|
||||
"meshes/icc_test/Cube with fillet Quads.obj",
|
||||
"meshes/cylinder.off",
|
||||
"meshes/icc_test/Lantern Tris.obj",
|
||||
"meshes/icc_test/Lantern Quads.obj"
|
||||
};
|
||||
|
||||
const std::vector<EpicKernel::FT> rel_expansion_radii = { 0, 0.1, 0.5, 1 };
|
||||
const std::vector<EpicKernel::FT> rel_noise_magnitudes = { 0, 0.5, 0.9 };
|
||||
|
||||
for (auto mesh_path : mesh_pathes_to_test) {
|
||||
for (EpicKernel::FT rel_expansion_radius : rel_expansion_radii)
|
||||
for (EpicKernel::FT rel_noise_magnitude : rel_noise_magnitudes)
|
||||
{
|
||||
test(mesh_path, rel_expansion_radius, rel_noise_magnitude);
|
||||
}
|
||||
|
||||
std::cout << "_________________________________________________________________________________\n\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_mesh_processing/Curvatures/interpolated_corrected_curvature_measures.h>
|
||||
#include <CGAL/Polygon_mesh_processing/random_perturbation.h>
|
||||
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#define ABS_ERROR 1e-6
|
||||
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic_kernel;
|
||||
typedef CGAL::Surface_mesh<Epic_kernel::Point_3> SMesh;
|
||||
typedef CGAL::Polyhedron_3<Epic_kernel> Polyhedron;
|
||||
|
||||
struct Average_test_info {
|
||||
Epic_kernel::FT expansion_radius = -1;
|
||||
Epic_kernel::FT mean_curvature_avg;
|
||||
Epic_kernel::FT gaussian_curvature_avg;
|
||||
Epic_kernel::FT principal_curvature_avg;
|
||||
Epic_kernel::FT tolerance = 0.9;
|
||||
|
||||
Average_test_info(
|
||||
Epic_kernel::FT mean_curvature_avg,
|
||||
Epic_kernel::FT gaussian_curvature_avg,
|
||||
Epic_kernel::FT principal_curvature_avg,
|
||||
Epic_kernel::FT expansion_radius = -1,
|
||||
Epic_kernel::FT tolerance = 0.9
|
||||
):
|
||||
expansion_radius(expansion_radius),
|
||||
mean_curvature_avg(mean_curvature_avg),
|
||||
gaussian_curvature_avg(gaussian_curvature_avg),
|
||||
principal_curvature_avg(principal_curvature_avg),
|
||||
tolerance(tolerance)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool passes_comparison(Epic_kernel::FT result, Epic_kernel::FT expected, Epic_kernel::FT tolerance)
|
||||
{
|
||||
if (abs(expected) < ABS_ERROR && abs(result) < ABS_ERROR)
|
||||
return true; // expected 0, got 0
|
||||
else if (abs(expected) < ABS_ERROR)
|
||||
return false; // expected 0, got non-0
|
||||
|
||||
return std::min(result, expected) / std::max(result, expected) > tolerance;
|
||||
}
|
||||
|
||||
template <typename PolygonMesh>
|
||||
void test_average_curvatures(std::string mesh_path, Average_test_info test_info){
|
||||
PolygonMesh pmesh;
|
||||
const std::string filename = CGAL::data_file_path(mesh_path);
|
||||
|
||||
if (!CGAL::IO::read_polygon_mesh(filename, pmesh) || faces(pmesh).size() == 0)
|
||||
{
|
||||
std::cerr << "Invalid input file." << std::endl;
|
||||
}
|
||||
|
||||
typedef boost::graph_traits<PolygonMesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
boost::property_map<PolygonMesh, CGAL::dynamic_vertex_property_t<Epic_kernel::FT>>::type
|
||||
mean_curvature_map = get(CGAL::dynamic_vertex_property_t<Epic_kernel::FT>(), pmesh),
|
||||
gaussian_curvature_map = get(CGAL::dynamic_vertex_property_t<Epic_kernel::FT>(), pmesh);
|
||||
boost::property_map<PolygonMesh, CGAL::dynamic_vertex_property_t<PMP::Principal_curvatures_and_directions<Epic_kernel>>>::type
|
||||
principal_curvatures_and_directions_map = get(CGAL::dynamic_vertex_property_t<PMP::Principal_curvatures_and_directions<Epic_kernel>>(), pmesh);
|
||||
|
||||
// test_info.expansion_radius -> test if no radius is provided by user.
|
||||
if (test_info.expansion_radius < 0) {
|
||||
PMP::interpolated_corrected_mean_curvature(pmesh, mean_curvature_map);
|
||||
PMP::interpolated_corrected_gaussian_curvature(pmesh, gaussian_curvature_map);
|
||||
PMP::interpolated_corrected_principal_curvatures_and_directions(pmesh, principal_curvatures_and_directions_map);
|
||||
}
|
||||
else {
|
||||
PMP::interpolated_corrected_mean_curvature(
|
||||
pmesh,
|
||||
mean_curvature_map,
|
||||
CGAL::parameters::ball_radius(test_info.expansion_radius)
|
||||
);
|
||||
|
||||
PMP::interpolated_corrected_gaussian_curvature(
|
||||
pmesh,
|
||||
gaussian_curvature_map,
|
||||
CGAL::parameters::ball_radius(test_info.expansion_radius)
|
||||
);
|
||||
|
||||
PMP::interpolated_corrected_principal_curvatures_and_directions(
|
||||
pmesh,
|
||||
principal_curvatures_and_directions_map,
|
||||
CGAL::parameters::ball_radius(test_info.expansion_radius)
|
||||
);
|
||||
}
|
||||
|
||||
Epic_kernel::FT mean_curvature_avg = 0, gaussian_curvature_avg = 0, principal_curvature_avg = 0;
|
||||
|
||||
for (vertex_descriptor v : vertices(pmesh))
|
||||
{
|
||||
mean_curvature_avg += get(mean_curvature_map, v);
|
||||
gaussian_curvature_avg += get(gaussian_curvature_map, v);
|
||||
principal_curvature_avg += get(principal_curvatures_and_directions_map, v).min_curvature
|
||||
+ get(principal_curvatures_and_directions_map, v).max_curvature;
|
||||
}
|
||||
|
||||
mean_curvature_avg /= vertices(pmesh).size();
|
||||
gaussian_curvature_avg /= vertices(pmesh).size();
|
||||
principal_curvature_avg /= vertices(pmesh).size() * 2;
|
||||
|
||||
// are average curvatures equal to expected?
|
||||
assert(passes_comparison(mean_curvature_avg, test_info.mean_curvature_avg, test_info.tolerance));
|
||||
assert(passes_comparison(gaussian_curvature_avg, test_info.gaussian_curvature_avg, test_info.tolerance));
|
||||
assert(passes_comparison(principal_curvature_avg, test_info.principal_curvature_avg, test_info.tolerance));
|
||||
|
||||
PMP::interpolated_corrected_curvatures(
|
||||
pmesh,
|
||||
CGAL::parameters::ball_radius(test_info.expansion_radius)
|
||||
.vertex_mean_curvature_map(mean_curvature_map)
|
||||
.vertex_gaussian_curvature_map(gaussian_curvature_map)
|
||||
.vertex_principal_curvatures_and_directions_map(principal_curvatures_and_directions_map)
|
||||
);
|
||||
|
||||
// are average curvatures computed from interpolated_corrected_curvatures() equal to average curvatures each computed on its own?
|
||||
Epic_kernel::FT new_mean_curvature_avg = 0, new_gaussian_curvature_avg = 0, new_principal_curvature_avg = 0;
|
||||
|
||||
for (vertex_descriptor v : vertices(pmesh))
|
||||
{
|
||||
new_mean_curvature_avg += get(mean_curvature_map, v);
|
||||
new_gaussian_curvature_avg += get(gaussian_curvature_map, v);
|
||||
new_principal_curvature_avg += get(principal_curvatures_and_directions_map, v).min_curvature
|
||||
+ get(principal_curvatures_and_directions_map, v).max_curvature;
|
||||
}
|
||||
|
||||
new_mean_curvature_avg /= vertices(pmesh).size();
|
||||
new_gaussian_curvature_avg /= vertices(pmesh).size();
|
||||
new_principal_curvature_avg /= vertices(pmesh).size() * 2;
|
||||
|
||||
assert(passes_comparison(mean_curvature_avg, new_mean_curvature_avg, 0.99));
|
||||
assert(passes_comparison(gaussian_curvature_avg, new_gaussian_curvature_avg, 0.99));
|
||||
assert(passes_comparison(principal_curvature_avg, new_principal_curvature_avg, 0.99));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// testing on a simple sphere(r = 0.5), on both Polyhedron & SurfaceMesh:
|
||||
// Expected: Mean Curvature = 2, Gaussian Curvature = 4, Principal Curvatures = 2 & 2 so 2 on avg.
|
||||
test_average_curvatures<Polyhedron>("meshes/sphere.off", Average_test_info(2,4,2));
|
||||
test_average_curvatures<SMesh>("meshes/sphere.off", Average_test_info(2, 4, 2));
|
||||
|
||||
// Same mesh but with specified expansion radii of 0 and 0.25 (half radius of sphere)
|
||||
test_average_curvatures<SMesh>("meshes/sphere.off", Average_test_info(2, 4, 2, 0));
|
||||
test_average_curvatures<SMesh>("meshes/sphere.off", Average_test_info(2, 4, 2, 0.25));
|
||||
|
||||
// testing on a simple sphere(r = 10), on both Polyhedron & SurfaceMesh:
|
||||
// Expected: Mean Curvature = 0.1, Gaussian Curvature = 0.01, Principal Curvatures = 0.1 & 0.1 so 0.1 on avg.
|
||||
test_average_curvatures<Polyhedron>("meshes/sphere966.off", Average_test_info(0.1, 0.01, 0.1));
|
||||
test_average_curvatures<SMesh>("meshes/sphere966.off", Average_test_info(0.1, 0.01, 0.1));
|
||||
|
||||
// Same mesh but with specified expansion radii of 0 and 5 (half radius of sphere)
|
||||
test_average_curvatures<SMesh>("meshes/sphere966.off", Average_test_info(0.1, 0.01, 0.1, 0));
|
||||
test_average_curvatures<SMesh>("meshes/sphere966.off", Average_test_info(0.1, 0.01, 0.1, 5));
|
||||
|
||||
// testing on a simple half cylinder(r = 1), on both Polyhedron & SurfaceMesh:
|
||||
// Expected: Mean Curvature = 0.5, Gaussian Curvature = 0, Principal Curvatures = 0 & 1 so 0.5 on avg.
|
||||
test_average_curvatures<Polyhedron>("meshes/cylinder.off", Average_test_info(0.5, 0, 0.5));
|
||||
test_average_curvatures<SMesh>("meshes/cylinder.off", Average_test_info(0.5, 0, 0.5));
|
||||
|
||||
// Same mesh but with specified expansion radii of 0 and 0.5 (half radius of cylinder)
|
||||
test_average_curvatures<SMesh>("meshes/cylinder.off", Average_test_info(0.5, 0, 0.5, 0));
|
||||
test_average_curvatures<SMesh>("meshes/cylinder.off", Average_test_info(0.5, 0, 0.5, 0.5));
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue