CGAL / cgal

The public CGAL repository, see the README below
https://github.com/CGAL/cgal#readme
Other
4.67k stars 1.35k forks source link

Partial Mesh Smoothing Fails in CGAL::Polygon_mesh_processing::smooth_shape #7990

Open Tyndall-log opened 5 months ago

Tyndall-log commented 5 months ago

Issue Details

When a range other than the full range of the mesh is input into the FaceRange parameter of CGAL::Polygon_mesh_processing::smooth_shape, the function fails to operate properly.

My goal is to perform smoothing on specific parts of a mesh (such as selected vertices or surfaces). I used the smooth_shape function for this purpose, and it works well with the full range. However, I might not be using the function correctly. Any advice would be appreciated.

Source Code

I created the reproducible code using the example from the link below: CGAL shape smoothing example

#define CGAL_PMP_SMOOTHING_DEBUG 1
#define CGAL_PMP_SMOOTHING_OUTPUT_INTERMEDIARY_STEPS 1

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/draw_surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/smooth_shape.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <iostream>
#include <set>
#include <string>
typedef CGAL::Exact_predicates_inexact_constructions_kernel   K;
typedef CGAL::Surface_mesh<K::Point_3>                        Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char* argv[])
{
    QCoreApplication::addLibraryPath("C:/Qt/5.15.2/msvc2019_64/plugins");
    const std::string filename = (argc > 1) ? argv[1] : "../meshes/pig.off";
    Mesh mesh;
    if(!PMP::IO::read_polygon_mesh(filename, mesh))
    {
        std::cerr << "Invalid input." << std::endl;
        return 1;
    }
    draw(mesh);
    const unsigned int nb_iterations = (argc > 2) ? std::atoi(argv[2]) : 10;
    const double time = (argc > 3) ? std::atof(argv[3]) : 0.0001;
    std::set<Mesh::Vertex_index> constrained_vertices;
    for(Mesh::Vertex_index v : vertices(mesh))
    {
        if(is_border(v, mesh))
            constrained_vertices.insert(v);
    }
    std::cout << "Constraining: " << constrained_vertices.size() << " border vertices" << std::endl;
    CGAL::Boolean_property_map<std::set<Mesh::Vertex_index> > vcmap(constrained_vertices);

    std::cerr.rdbuf(std::cout.rdbuf());
    std::set<Mesh::Face_index> faces_to_smooth;
    faces_to_smooth.insert(faces(mesh).begin(), faces(mesh).end()); // case 1: all faces -> success
    //faces_to_smooth.insert(faces(mesh).begin(), faces(mesh).begin() + 1); // case 2: 1 face -> fail !!! why ???
    std::cout << "Smoothing shape... (" << nb_iterations << " iterations)" << std::endl;
    PMP::smooth_shape(faces_to_smooth, mesh, time, CGAL::parameters::number_of_iterations(nb_iterations)
                                                   .vertex_is_constrained_map(vcmap));
    CGAL::IO::write_polygon_mesh("../meshes/mesh_shape_smoothed.off", mesh, CGAL::parameters::stream_precision(17));
    std::cout << "Done!" << std::endl;
    draw(mesh);

    return EXIT_SUCCESS;
}

output

case 1

Using OpenGL context 4.3 GL
Constraining: 55 border vertices
Smoothing shape... (10 iterations)
iteration #0
iteration #1
iteration #2
iteration #3
iteration #4
iteration #5
iteration #6
iteration #7
iteration #8
iteration #9
Done!
Using OpenGL context 4.3 GL

case 2:

Using OpenGL context 4.3 GL
Constraining: 55 border vertices
Smoothing shape... (10 iterations)
iteration #0
Could not factorize linear system with preconditioner.
Failed to solve system!
Done!
Using OpenGL context 4.3 GL

Environment

afabri commented 5 months ago

Do I get it right that you pass a single face to the smoother? Then it has no degrees of freedom as the border of the region does not move. Did you try with a larger patch?

Tyndall-log commented 4 months ago

Yes, it seems like an error occurs when a range of faces that does not include all vertices of the mesh is provided. Despite giving a range of various faces, the error occurs every time. The reason for providing a range of a single face in the example was simply to provide a minimal example of it not working. However, according to the documentation, I believe that an error should not occur in this case.

afabri commented 2 months ago

I work on a fix. In the current version, when you put the vertices on the border of the patch in constraint_vertices it works.