split at the midpoint to avoid patterns leading to infinite loop

This commit is contained in:
Sébastien Loriot 2025-03-31 20:27:27 +02:00
parent 9c6452dfaf
commit 9ff2696011
2 changed files with 34 additions and 27 deletions

View File

@ -480,48 +480,51 @@ acvd_impl(TriangleMesh& tmesh,
}
FT threshold = 3. * cum / nbe;
std::vector<std::pair<edge_descriptor, double>> to_split;
std::vector<edge_descriptor> to_split;
int ei = -1;
for (edge_descriptor e : edges(tmesh))
{
FT l = lengths[++ei];
if (l >= threshold)
{
double nb_subsegments = std::ceil(l / threshold);
to_split.emplace_back(e, nb_subsegments);
to_split.emplace_back(e);
}
}
auto el = [&gt, &vpm, &tmesh](halfedge_descriptor h)
{
return edge_length(h, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt));
};
while (!to_split.empty())
{
std::vector<std::pair<edge_descriptor, double>> to_split_new;
to_split_new.reserve(2*to_split.size()); //upper bound
for (const auto& [e, nb_subsegments] : to_split)
std::vector<edge_descriptor> to_split_new;
to_split_new.reserve(3*to_split.size()); // upper bound
for (edge_descriptor e : to_split)
{
halfedge_descriptor h = halfedge(e, tmesh);
Point_3 s = get(vpm, source(h,tmesh));
Point_3 t = get(vpm, target(h,tmesh));
for (double k=1; k<nb_subsegments; ++k)
// the new halfedge hnew pointing to the inserted vertex.
// The new halfedge is followed by the old halfedge, i.e., next(hnew,g) == h.
halfedge_descriptor hnew = Euler::split_edge(h, tmesh);
put(vpm, target(hnew, tmesh), midpoint(s,t));
for (halfedge_descriptor hhh : {hnew, opposite(h, tmesh)})
{
// the new halfedge hnew pointing to the inserted vertex.
// The new halfedge is followed by the old halfedge, i.e., next(hnew,g) == h.
halfedge_descriptor hnew = Euler::split_edge(h, tmesh);
put(vpm, target(hnew, tmesh), barycenter(t, k/nb_subsegments, s));
for (halfedge_descriptor hhh : {hnew, opposite(h, tmesh)})
if (!is_border(hhh, tmesh))
{
if (!is_border(hhh, tmesh))
{
halfedge_descriptor hf = Euler::split_face(hhh, next(next(hhh, tmesh), tmesh), tmesh);
FT l = edge_length(hf, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt));
if (l >= threshold)
{
double nb_subsegments = std::ceil(l / threshold);
to_split_new.emplace_back(edge(hf,tmesh), nb_subsegments);
}
}
halfedge_descriptor hf = Euler::split_face(hhh, next(next(hhh, tmesh), tmesh), tmesh);
if (el(hf) >= threshold)
to_split_new.emplace_back(edge(hf,tmesh));
}
}
if (el(hnew) >= threshold)
{
to_split_new.push_back(edge(h, tmesh));
to_split_new.push_back(edge(hnew, tmesh));
}
}
to_split.swap(to_split_new);
}

View File

@ -20,13 +20,14 @@ using Polyhedron = CGAL::Polyhedron_3<K>;
namespace params = CGAL::parameters;
template <class Mesh>
void run_test(std::string fname, std::size_t genus)
void run_test(std::string fname, std::size_t genus, bool subdiv)
{
Mesh mesh;
CGAL::IO::read_polygon_mesh(fname, mesh);
PMP::triangulate_faces(mesh);
CGAL::Subdivision_method_3::Loop_subdivision(mesh, params::number_of_iterations(5));
if (subdiv)
CGAL::Subdivision_method_3::Loop_subdivision(mesh, params::number_of_iterations(5));
Mesh ref=mesh;
CGAL::Bbox_3 bb_ref = PMP::bbox(ref);
@ -52,9 +53,12 @@ void run_test(std::string fname, std::size_t genus)
int main()
{
run_test<Surface_mesh>(CGAL::data_file_path("meshes/tetrahedron.off"), 0);
run_test<Polyhedron>(CGAL::data_file_path("meshes/torus_quad.off"), 1);
run_test<Surface_mesh>(CGAL::data_file_path("meshes/double-torus-example.off"), 2);
run_test<Surface_mesh>(CGAL::data_file_path("meshes/tetrahedron.off"), 0, true);
run_test<Surface_mesh>(CGAL::data_file_path("meshes/tetrahedron.off"), 0, false);
run_test<Polyhedron>(CGAL::data_file_path("meshes/torus_quad.off"), 1, true);
run_test<Polyhedron>(CGAL::data_file_path("meshes/torus_quad.off"), 1, false);
run_test<Surface_mesh>(CGAL::data_file_path("meshes/double-torus-example.off"), 2, true);
run_test<Surface_mesh>(CGAL::data_file_path("meshes/double-torus-example.off"), 2, false);
return 0;
}