Test code fixes

This commit is contained in:
Mael Rouxel-Labbé 2022-03-23 13:33:00 +01:00
parent a7a9cc0660
commit a43b79a69f
6 changed files with 114 additions and 65 deletions

View File

@ -22,6 +22,7 @@
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Side_of_triangle_mesh.h>
namespace CGAL {
@ -124,6 +125,22 @@ bool is_valid_wrap(const TriangleMesh& wrap,
{
namespace PMP = CGAL::Polygon_mesh_processing;
if(is_empty(wrap))
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "Error: empty wrap" << std::endl;
#endif
return false;
}
if(!is_valid_polygon_mesh(wrap))
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "Error: Invalid wrap mesh" << std::endl;
#endif
return false;
}
if(!is_triangle_mesh(wrap))
{
#ifdef CGAL_AW3_DEBUG
@ -134,8 +151,24 @@ bool is_valid_wrap(const TriangleMesh& wrap,
if(!is_closed(wrap))
{
if(check_manifoldness)
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "Error: Wrap is not closed" << std::endl;
std::cerr << "Error: Wrap is not closed" << std::endl;
#endif
return false;
}
else
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "W: Wrap is not closed" << std::endl;
#endif
}
}
else if(!PMP::does_bound_a_volume(wrap, np))
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "Error: Wrap does not bound a volume" << std::endl;
#endif
return false;
}
@ -166,18 +199,10 @@ bool is_valid_wrap(const TriangleMesh& wrap,
return false;
}
#ifdef CGAL_AW3_DEBUG
std::cerr << "Warning: Wrap self-intersects" << std::endl;
std::cerr << "W: Wrap self-intersects" << std::endl;
#endif
}
if(!PMP::does_bound_a_volume(wrap, np))
{
#ifdef CGAL_AW3_DEBUG
std::cerr << "Error: Wrap does not bound a volume" << std::endl;
#endif
return false;
}
return true;
}
@ -268,6 +293,7 @@ bool is_outer_wrap_of_triangle_soup(const TriangleMesh& wrap,
namespace PMP = CGAL::Polygon_mesh_processing;
// Make a mesh out of the soup
PMP::repair_polygon_soup(points, faces);
PMP::orient_polygon_soup(points, faces);
CGAL_assertion(PMP::is_polygon_soup_a_polygon_mesh(faces));

View File

@ -1,6 +1,6 @@
#define CGAL_AW3_TIMER
#define CGAL_AW3_DEBUG
#define CGAL_AW3_DEBUG_INITIALIZATION
// #define CGAL_AW3_DEBUG_INITIALIZATION
#include <CGAL/Surface_mesh.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
@ -21,24 +21,21 @@ using Mesh = CGAL::Surface_mesh<Point_3>;
using Seeds = std::vector<Point_3>;
Point_3 generate_point(const CGAL::Bbox_3 bbox,
CGAL::Random& r)
{
return Point_3(bbox.xmin() + bbox.x_span() * r.get_double(),
bbox.ymin() + bbox.y_span() * r.get_double(),
bbox.zmin() + bbox.z_span() * r.get_double());
}
template <typename Oracle>
void generate_random_seeds(const Oracle& oracle,
const double offset,
Seeds& seeds,
CGAL::Random& r)
{
auto sq_offset = CGAL::square(offset);
const auto bbox = CGAL::Alpha_wraps_3::internal::Alpha_wrap_3<Oracle>(oracle).construct_bbox(offset);
const double sq_offset = CGAL::square(offset);
while(seeds.size() < 3)
{
const Point_3 seed = generate_point(oracle.bbox(), r);
const Point_3 seed (bbox.xmin() + r.get_double(0., 1.) * (bbox.xmax() - bbox.xmin()),
bbox.ymin() + r.get_double(0., 1.) * (bbox.ymax() - bbox.ymin()),
bbox.zmin() + r.get_double(0., 1.) * (bbox.zmax() - bbox.zmin()));
const FT sqd = oracle.squared_distance(seed);
#ifdef CGAL_AW3_DEBUG
std::cout << "Generate " << seed << " at squared distance " << sqd << " (sqo: " << sq_offset << ")" << std::endl;
@ -66,6 +63,7 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh,
if(has_degeneracies)
std::cerr << "Warning: Failed to remove some degenerate faces." << std::endl;
std::cout << "Processed input: " << vertices(input_mesh).size() << " vertices, " << faces(input_mesh).size() << " faces" << std::endl;
// CGAL::IO::write_polygon_mesh("input.off", input_mesh, CGAL::parameters::stream_precision(17));
Oracle oracle;
@ -81,23 +79,32 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh,
assert(!seeds.empty());
const bool enforce_manifoldness = true;
Mesh wrap;
aw3(alpha, offset, wrap,
CGAL::parameters::seed_points(std::ref(seeds))
.do_enforce_manifoldness(true));
.do_enforce_manifoldness(enforce_manifoldness));
std::cout << "Result: " << vertices(wrap).size() << " vertices, " << faces(wrap).size() << " faces" << std::endl;
// Tolerate failed initialization since we use random seeds and it's difficult to guarantee it
if(is_empty(wrap))
return;
// CGAL::IO::write_polygon_mesh("last.off", wrap, CGAL::parameters::stream_precision(17));
if(!has_degeneracies)
{
assert(AW3::internal::is_valid_wrap(wrap, true /*manifoldness*/));
assert(AW3::internal::is_outer_wrap_of_triangle_mesh(wrap, input_mesh));
// assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset));
if(!enforce_manifoldness)
assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset));
}
// assert(AW3::internal::check_edge_length(wrap, alpha));
if(!enforce_manifoldness)
assert(AW3::internal::check_edge_length(wrap, alpha));
}
void alpha_wrap_triangle_mesh(Mesh& input_mesh,
@ -125,8 +132,8 @@ void alpha_wrap_triangle_mesh(const std::string& filename)
{
CGAL::Random r;
const double alpha_expo = r.get_double(0., 7.5); // to have alpha_rel between 1 and ~200
const double offset_expo = r.get_double(0., 7.5);
const double alpha_expo = r.get_double(0., 6); // to have alpha_rel between 1 and 64
const double offset_expo = r.get_double(0., 6);
const double alpha_rel = std::pow(2, alpha_expo);
const double offset_rel = std::pow(2, offset_expo);
const double alpha = longest_diag_length / alpha_rel;

View File

@ -33,6 +33,7 @@ void alpha_wrap_triangle_manifoldness(Mesh& input_mesh,
namespace PMP = CGAL::Polygon_mesh_processing;
std::cout << "Input: " << num_vertices(input_mesh) << " vertices, " << num_faces(input_mesh) << " faces" << std::endl;
std::cout << "Alpha: " << alpha << " Offset: " << offset << std::endl;
const bool has_degeneracies = !PMP::remove_degenerate_faces(input_mesh);
if(has_degeneracies)
@ -49,9 +50,18 @@ void alpha_wrap_triangle_manifoldness(Mesh& input_mesh,
std::cout << "Result: " << vertices(nm_wrap).size() << " vertices, " << faces(nm_wrap).size() << " faces" << std::endl;
if(!has_degeneracies)
{
assert(AW3::internal::is_valid_wrap(nm_wrap, false));
assert(AW3::internal::is_outer_wrap_of_triangle_mesh(nm_wrap, input_mesh));
assert(AW3::internal::has_expected_Hausdorff_distance(nm_wrap, input_mesh, alpha, offset));
}
assert(AW3::internal::check_edge_length(nm_wrap, alpha));
FT base_vol = 0;
if(!is_closed(nm_wrap))
std::cerr << "Warning: non-manifold wrap is not closed" << std::endl;
std::cerr << "W: non-manifold wrap is not closed" << std::endl;
else
base_vol = PMP::volume(nm_wrap);
@ -66,13 +76,8 @@ void alpha_wrap_triangle_manifoldness(Mesh& input_mesh,
{
assert(AW3::internal::is_valid_wrap(m_wrap, true /*manifoldness*/));
assert(AW3::internal::is_outer_wrap_of_triangle_mesh(m_wrap, input_mesh));
// These assertions might not be honored since we have added material
// assert(AW3::internal::has_expected_Hausdorff_distance(m_wrap, input_mesh, alpha, offset));
}
// assert(AW3::internal::check_edge_length(wrap, alpha));
const FT final_vol = PMP::volume(m_wrap);
if(base_vol != 0)
@ -84,7 +89,7 @@ void alpha_wrap_triangle_manifoldness(Mesh& input_mesh,
<< "after: " << final_vol << "\n"
<< "ratio: " << ratio << std::endl;
if(ratio > 1.1) // more than 10% extra volume
std::cerr << "Warning: large increase of volume after manifoldness resolution" << std::endl;
std::cerr << "W: large increase of volume after manifoldness resolution" << std::endl;
}
}
@ -124,8 +129,8 @@ void alpha_wrap_triangle_manifoldness(const std::string& filename)
for(int i=0; i<2; ++i)
{
const double alpha_expo = r.get_double(0., 7.5); // to have alpha_rel between 1 and ~200
const double offset_expo = r.get_double(0., 7.5);
const double alpha_expo = r.get_double(0., 6); // to have alpha_rel between 1 and 64
const double offset_expo = r.get_double(0., 6);
const double alpha_rel = std::pow(2, alpha_expo);
const double offset_rel = std::pow(2, offset_expo);
const double alpha = longest_diag_length / alpha_rel;

View File

@ -23,32 +23,30 @@ using Point_3 = Kernel::Point_3;
using Vector_3 = Kernel::Vector_3;
using Points = std::vector<Point_3>;
using Face = std::array<std::size_t, 3>;
using Face = std::vector<std::size_t>;
using Faces = std::vector<Face>;
using Mesh = CGAL::Surface_mesh<Point_3>;
void alpha_wrap_triangle_soup(Points& pr,
Faces& fr,
const double alpha,
const double offset)
double alpha,
double offset)
{
namespace AW3 = CGAL::Alpha_wraps_3;
namespace PMP = CGAL::Polygon_mesh_processing;
using Oracle = AW3::internal::Triangle_soup_oracle<Points, Faces, Kernel, int, false>;
using Oracle = AW3::internal::Triangle_soup_oracle<Points, Faces, Kernel, int, false /*subdivide*/>;
std::cout << "Input: " << pr.size() << " points, " << fr.size() << " faces" << std::endl;
PMP::repair_polygon_soup(pr, fr);
std::cout << "Processed input: " << pr.size() << " points, " << fr.size() << " faces" << std::endl;
// CGAL::IO::write_polygon_soup("input.off", pr, fr, CGAL::parameters::stream_precision(17));
Mesh input_mesh;
if(!PMP::orient_polygon_soup(pr, fr) ||
!PMP::is_polygon_soup_a_polygon_mesh(fr))
{
std::cerr << "Warning: polygon soup does not describe a polygon mesh" << std::endl;
return;
}
Mesh input_mesh; // only required for Hausdorff
PMP::orient_polygon_soup(pr, fr);
assert(PMP::is_polygon_soup_a_polygon_mesh(fr));
PMP::polygon_soup_to_polygon_mesh(pr, fr, input_mesh);
// AW3
@ -59,7 +57,7 @@ void alpha_wrap_triangle_soup(Points& pr,
Mesh wrap;
aw3(alpha, offset, wrap, CGAL::parameters::do_enforce_manifoldness(false));
std::cout << "Result: " << vertices(wrap).size() << " vertices, " << faces(wrap).size() << " faces" << std::endl;
std::cout << "First call result: " << vertices(wrap).size() << " vertices, " << faces(wrap).size() << " faces" << std::endl;
// CGAL::IO::write_polygon_mesh("last.off", wrap, CGAL::parameters::stream_precision(17));
@ -68,8 +66,15 @@ void alpha_wrap_triangle_soup(Points& pr,
assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset));
assert(AW3::internal::check_edge_length(wrap, alpha));
alpha *= 2;
offset *= 2;
Mesh wrap_2;
aw3(2 * alpha, 2 * offset, wrap, CGAL::parameters::do_enforce_manifoldness(false));
aw3(alpha, offset, wrap_2, CGAL::parameters::do_enforce_manifoldness(false));
std::cout << "Second call result: " << vertices(wrap).size() << " vertices, " << faces(wrap).size() << " faces" << std::endl;
// CGAL::IO::write_polygon_mesh("last.off", wrap, CGAL::parameters::stream_precision(17));
assert(num_vertices(wrap_2) <= num_vertices(wrap) && num_faces(wrap_2) <= num_faces(wrap));
assert(AW3::internal::is_valid_wrap(wrap_2, false /*manifoldness*/));
@ -95,12 +100,12 @@ void alpha_wrap_triangle_soup(const std::string& filename)
Point_3(bbox.xmin(), bbox.ymin(), bbox.zmin());
double longest_diag_length = CGAL::to_double(CGAL::approximate_sqrt(longest_diag.squared_length()));
CGAL::Random r;
for(int i=0; i<2; ++i)
{
CGAL::Random r;
const double alpha_expo = r.get_double(0., 7.5); // to have alpha_rel between 1 and ~200
const double offset_expo = r.get_double(0., 7.5);
const double alpha_expo = r.get_double(0., 6); // to have alpha_rel between 1 and 64
const double offset_expo = r.get_double(0., 6);
const double alpha_rel = std::pow(2, alpha_expo);
const double offset_rel = std::pow(2, offset_expo);
const double alpha = longest_diag_length / alpha_rel;
@ -139,7 +144,7 @@ int main(int argc, char** argv)
alpha_wrap_triangle_soup("data/tetrahedron_self_intersection_tip.off");
alpha_wrap_triangle_soup("data/tetrahedron_twisted_tip.off");
alpha_wrap_triangle_soup("data/tetrahedron_random_perturbation.off");
alpha_wrap_triangle_soup("data/overlay_triangulation.off");
// alpha_wrap_triangle_soup("data/overlay_triangulation.off"); // due to geometrically degenerate faces + using soups here
alpha_wrap_triangle_soup("data/two_knives.off");
alpha_wrap_triangle_soup("data/three_knives.off");
alpha_wrap_triangle_soup("data/bunny_random_perturbation.off");

View File

@ -1,6 +1,6 @@
#define CGAL_AW3_TIMER
#define CGAL_AW3_DEBUG
#define CGAL_AW3_DEBUG_MANIFOLDNESS
//#define CGAL_AW3_DEBUG
//#define CGAL_AW3_DEBUG_MANIFOLDNESS
//#define CGAL_AW3_DEBUG_STEINER_COMPUTATION
//#define CGAL_AW3_DEBUG_INITIALIZATION
//#define CGAL_AW3_DEBUG_QUEUE
@ -33,6 +33,7 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh,
namespace PMP = CGAL::Polygon_mesh_processing;
std::cout << "Input: " << num_vertices(input_mesh) << " vertices, " << num_faces(input_mesh) << " faces" << std::endl;
std::cout << "Alpha: " << alpha << " Offset: " << offset << std::endl;
bool has_degeneracies = !PMP::remove_degenerate_faces(input_mesh);
if(has_degeneracies)
@ -42,10 +43,12 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh,
// CGAL::IO::write_polygon_mesh("input.off", input_mesh, CGAL::parameters::stream_precision(17));
const bool enforce_manifoldness = true;
Mesh wrap;
CGAL::alpha_wrap_3(input_mesh, alpha, offset, wrap,
CGAL::parameters::default_values(),
CGAL::parameters::do_enforce_manifoldness(true));
CGAL::parameters::do_enforce_manifoldness(enforce_manifoldness));
std::cout << "Result: " << vertices(wrap).size() << " vertices, " << faces(wrap).size() << " faces" << std::endl;
@ -55,10 +58,13 @@ void alpha_wrap_triangle_mesh(Mesh& input_mesh,
{
assert(AW3::internal::is_valid_wrap(wrap, true /*manifoldness*/));
assert(AW3::internal::is_outer_wrap_of_triangle_mesh(wrap, input_mesh));
assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset));
if(!enforce_manifoldness)
assert(AW3::internal::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset));
}
assert(AW3::internal::check_edge_length(wrap, alpha));
if(!enforce_manifoldness)
assert(AW3::internal::check_edge_length(wrap, alpha));
}
void alpha_wrap_triangle_mesh(const std::string& filename,
@ -97,8 +103,8 @@ void alpha_wrap_triangle_mesh(const std::string& filename)
for(int i=0; i<2; ++i)
{
const double alpha_expo = r.get_double(0., 7.5); // to have alpha_rel between 1 and ~200
const double offset_expo = r.get_double(0., 7.5);
const double alpha_expo = r.get_double(0., 6); // to have alpha_rel between 1 and 64
const double offset_expo = r.get_double(0., 6);
const double alpha_rel = std::pow(2, alpha_expo);
const double offset_rel = std::pow(2, offset_expo);
const double alpha = longest_diag_length / alpha_rel;

View File

@ -104,12 +104,12 @@ int main(int argc, char * argv[])
//***************************************
// usage
if (argc-1 < 2)
if(argc == 1)
{
std::cerr << "Reads a point set or a mesh's set of vertices, reconstructs a surface using Poisson,\n";
std::cerr << "and saves the surface.\n";
std::cerr << "\n";
std::cerr << "Usage: " << argv[0] << " file_in file_out [options]\n";
std::cerr << "Usage: " << argv[0] << " [file_in] [file_out] [options]\n";
std::cerr << "Input file formats are .off (mesh) and .xyz or .pwn (point set).\n";
std::cerr << "Output file format is .off.\n";
std::cerr << "Options:\n";
@ -127,8 +127,8 @@ int main(int argc, char * argv[])
double average_spacing_ratio = 5;
// decode parameters
std::string input_filename = argc == 1 ? CGAL::data_file_path("points_3/kitten.xyz") : argv[1];
std::string output_filename = argc == 1 ? "kitten_poisson-20-100-0.5.off" : argv[2];
std::string input_filename = (argc > 1) ? argv[1] : CGAL::data_file_path("points_3/kitten.xyz");
std::string output_filename = (argc > 2) ? argv[2] : "kitten_poisson-20-100-0.5.off";
for (int i=3; i+1<argc ; ++i)
{
if (std::string(argv[i])=="-sm_radius")