CGAL / cgal

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

remesh_almost_planar_patches,What about returning an empty mesh #7853

Open kuaiqushangzixiba opened 1 year ago

kuaiqushangzixiba commented 1 year ago

Return empty mesh What is going on, I tried many mesh, some can return simplified mesh, some return empty mesh, some return the original input mesh, what is going on in the end? How can you guarantee that a simplified mesh is returned

bool success = PMP::remesh_almost_planar_patches(sm,
    out,
    nb_regions, nb_corners,
    CGAL::make_random_access_property_map(region_ids),
    CGAL::make_random_access_property_map(corner_id_map),
    CGAL::make_random_access_property_map(ecm),
    CGAL::parameters::patch_normal_map(normal_map));
sloriot commented 1 year ago

could you please provide an example mesh with parameters you used (and the example you used)? Did you check the bool returned value?

kuaiqushangzixiba commented 1 year ago

like example diplodocus.off

    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\elephant-with-holes.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\man.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\building.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\bear.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\pig.stl");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\refined_elephant.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\bunny00.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\diplodocus.off");
    baishi("E:\\cppThree\\CGAL-5.6\\data\\meshes\\armadillo.off");

I tried a lot of ply, as well as off in the example folder, the return value 0 and 1, can't see any pattern, some will return itself, some will return a simplified mesh, some will return an empty mesh

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/remesh_planar_patches.h>
#include <CGAL/Polygon_mesh_processing/region_growing.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <CGAL/Polygon_mesh_processing/random_perturbation.h>
#include <boost/property_map/vector_property_map.hpp>
#include <iostream>
#include <fstream>
#include <iostream>
#include <chrono>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
#include <cstdio>
#include <CGAL/Polygon_mesh_processing/stitch_borders.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Kernel::Point_3> Surface_mesh;

namespace PMP = CGAL::Polygon_mesh_processing;
int baishi(const std::string& filename)
{
    Surface_mesh sm;
    CGAL::IO::read_polygon_mesh(CGAL::data_file_path(filename), sm);

    std::cout << sm.number_of_vertices() << std::endl;
    std::vector<std::pair<unsigned, unsigned>> selfIntersections;
    PMP::self_intersections(sm, std::back_inserter(selfIntersections));
    std::cout << selfIntersections.size()  << std::endl;

    // declare vectors to store mesh properties
    std::vector<std::size_t> region_ids(num_faces(sm));
    std::vector<std::size_t> corner_id_map(num_vertices(sm), -1); // corner status of vertices
    std::vector<bool> ecm(num_edges(sm), false); // mark edges at the boundary of regions
    boost::vector_property_map<CGAL::Epick::Vector_3> normal_map; // normal of the supporting planes of the regions detected

    // detect planar regions in the mesh
    std::size_t nb_regions =
        PMP::region_growing_of_planes_on_faces(sm,
            CGAL::make_random_access_property_map(region_ids),
            CGAL::parameters::cosine_of_maximum_angle(0.89).
            region_primitive_map(normal_map).
            maximum_distance(0.0003));

    std::cout << nb_regions << "regions  ";

    // detect corner vertices on the boundary of planar regions
    std::size_t nb_corners =
        PMP::detect_corners_of_regions(sm,
            CGAL::make_random_access_property_map(region_ids),
            nb_regions,
            CGAL::make_random_access_property_map(corner_id_map),
            CGAL::parameters::cosine_of_maximum_angle(0.9).
            maximum_distance(0.0003).
            edge_is_constrained_map(CGAL::make_random_access_property_map(ecm)));
    std::cout << nb_corners << "corners  " << std::endl;
    //run the remeshing algorithm using filled properties
    Surface_mesh out;
    bool success = PMP::remesh_almost_planar_patches(sm,
        out,
        nb_regions, nb_corners,
        CGAL::make_random_access_property_map(region_ids),
        CGAL::make_random_access_property_map(corner_id_map),
        CGAL::make_random_access_property_map(ecm),
        CGAL::parameters::patch_normal_map(normal_map));

    CGAL::IO::write_polygon_mesh(filename.substr(0, filename.size() - 4) += "_test.ply", out);
    std::cout << success << std::endl;
    std::cout << out.number_of_vertices() << std::endl;
    std::cout << std::endl;
    return 0;
}

image

It seems that when bool is 1, it can be simplified with high probability (sometimes it can't), but how can we guarantee that boo is 1? Is there any requirement on the input ply?

kuaiqushangzixiba commented 1 year ago

I noticed that remesh_planar_patches has input requirements and can't handle non-manifold vertices. Does remesh_almost_planar_patches also have input requirements?

kuaiqushangzixiba commented 1 year ago

Also, the function only works if maximum_distance(0.0003) is very small, which makes it nearly impossible to handle any input mesh

sloriot commented 1 year ago

I will have a closer look at why the meshing part in failing as soon as I can. In the meantime, considering the input meshes you've been trying, the following package seems better suited (since they do not really have planar parts).

kuaiqushangzixiba commented 12 months ago

Ok, looking forward to your progress

ankofl commented 2 months ago

Hi @kuaiqushangzixiba

This approach works pretty well for me:

#pragma once
#include "mesh_typedefs.h"
#ifdef DEBUG_PLANAR
#include "my_timer.h"
#endif // DEBUG_PLANAR   
#include <CGAL/Polygon_mesh_processing/remesh_planar_patches.h>
#include "remesh_almost_planar.h"

void remesh_planar(Mesh& mesh) {
#ifdef DEBUG_PLANAR
    int pre = mesh.points().size();
    auto ts = start("planar:");
#endif // DEBUG_PLANAR    
    Mesh remeshed;
    PMP::remesh_planar_patches(mesh, remeshed);
    mesh = remeshed;
    remesh_almost_planar(mesh);
#ifdef DEBUG_PLANAR
    int post = pre - mesh.points().size();
    if (post != 0) {
        std::cout << "d(" << post << ") ";
    }
    msg("planared", ts, true);
#endif // DEBUG_PLANAR      
}

mesh_typedefs.h

#pragma once

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Nef_2/debug.h>
#include <CGAL/Polyhedron_3.h>

#include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT                                FT;
typedef K::Point_3                                P;
typedef K::Vector_3                               V;
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3> Mesh;
typedef CGAL::Surface_mesh<P> Surface;

typedef CGAL::Exact_predicates_exact_constructions_kernel K_e;
typedef K_e::Point_3                                P_e;
typedef K_e::Vector_3                               V_e;
typedef CGAL::Polyhedron_3<K_e> Mesh_e;

typedef CGAL::Nef_polyhedron_3<K_e, CGAL::SNC_indexed_items> Nef;
typedef CGAL::Nef_polyhedron_3<K_e> Nef_Sum;

typedef P_e* point_iterator;
typedef std::pair<point_iterator, point_iterator> point_range;
typedef std::list<point_range> polyline;

namespace PMP = CGAL::Polygon_mesh_processing;

remesh_almost_planar.h

#pragma once
#include "mesh_typedefs.h"

#include <CGAL/Polygon_mesh_processing/remesh_planar_patches.h>
#include <CGAL/Polygon_mesh_processing/region_growing.h>

#include <boost/property_map/vector_property_map.hpp>

void remesh_almost_planar(Mesh& mesh)
{
    Surface sm;
    copy(mesh, sm);
    // declare vectors to store mesh properties
    std::vector<std::size_t> region_ids(num_faces(sm));
    std::vector<std::size_t> corner_id_map(num_vertices(sm), -1); // corner status of vertices
    std::vector<bool> ecm(num_edges(sm), false); // mark edges at the boundary of regions
    boost::vector_property_map<CGAL::Epick::Vector_3> normal_map; // normal of the supporting planes of the regions detected

    // detect planar regions in the mesh
    std::size_t nb_regions =
        PMP::region_growing_of_planes_on_faces(sm,
            CGAL::make_random_access_property_map(region_ids),
            CGAL::parameters::cosine_of_maximum_angle(0.6).
            //CGAL::parameters::cosine_of_maximum_angle(0.98).
            region_primitive_map(normal_map).
            maximum_distance(1));
            //maximum_distance(0.011));

    // detect corner vertices on the boundary of planar regions
    std::size_t nb_corners =
        PMP::detect_corners_of_regions(sm,
            CGAL::make_random_access_property_map(region_ids),
            nb_regions,
            CGAL::make_random_access_property_map(corner_id_map),
            CGAL::parameters::cosine_of_maximum_angle(0.6).
            //CGAL::parameters::cosine_of_maximum_angle(0.98).
            //maximum_distance(0.011).
            maximum_distance(1).
            edge_is_constrained_map(CGAL::make_random_access_property_map(ecm)));

    // run the remeshing algorithm using filled properties
    Surface out;
    PMP::remesh_almost_planar_patches(sm,
        out,
        nb_regions, nb_corners,
        CGAL::make_random_access_property_map(region_ids),
        CGAL::make_random_access_property_map(corner_id_map),
        CGAL::make_random_access_property_map(ecm),
        CGAL::parameters::patch_normal_map(normal_map));
    copy(out, mesh);
}