Search code examples
c++cgalboolean-operations

CGAL convert non-manifold Nef_polyhedron_3 to triangle mesh


In my application I have a triangle mesh data structure, and I would like to do boolean operations with CGAL, and convert the result back as triangle mesh. It works fine, but when the result is non-manifold, it works only with Nef_polyhedron_3. The problem is that I can't convert it back to triangle meshes.

In the below code I have a cube and a prism, and one of the prism's edges lays on the face of cube, so the intersection will be non-manifold. I can do the operation with Nef_polyhedron_3, but after the operation I can't convert it back to triangle mesh.

#include <CGAL/Exact_integer.h>
#include <CGAL/Homogeneous.h>
#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/corefinement.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h>

#include <iostream>
#include <sstream>
#include <fstream>

typedef CGAL::Exact_predicates_exact_constructions_kernel   Kernel;
typedef Kernel::Point_3                                     Point_3;
typedef CGAL::Surface_mesh<Point_3>                         Surface_mesh;
typedef CGAL::Polyhedron_3<Kernel>                          Polyhedron_3;
typedef CGAL::Nef_polyhedron_3<Kernel>                      Nef_polyhedron_3;
typedef Polyhedron_3::HalfedgeDS                            HalfedgeDS;

template <typename T>
void fill_cube (T& result)
{
    std::string input =
"OFF\n\
8 12 0\n\
-0.5 -0.5 -0.5\n\
0.5 -0.5 -0.5\n\
0.5 -0.5 0.5\n\
-0.5 -0.5 0.5\n\
-0.5 0.5 -0.5\n\
0.5 0.5 -0.5\n\
0.5 0.5 0.5\n\
-0.5 0.5 0.5\n\
3 0 1 2\n\
3 0 2 3\n\
3 1 5 6\n\
3 1 6 2\n\
3 5 4 7\n\
3 5 7 6\n\
3 4 0 3\n\
3 4 3 7\n\
3 0 4 5\n\
3 0 5 1\n\
3 3 2 6\n\
3 3 6 7\n";
    std::stringstream ss;
    ss << input;
    ss >> result;
}

template <typename T>
void fill_prism (T& result)
{
    std::string input =
"OFF\n\
6 8 0\n\
0.5 0 -0.5\n\
-0.25 0.433013 -0.5\n\
-0.25 -0.433013 -0.5\n\
0.5 0 0.5\n\
-0.25 0.433013 0.5\n\
-0.25 -0.433013 0.5\n\
3 2 1 0\n\
3 3 4 5\n\
3 0 1 4\n\
3 0 4 3\n\
3 1 2 5\n\
3 1 5 4\n\
3 2 0 3\n\
3 2 3 5\n";
    std::stringstream ss;
    ss << input;
    ss >> result;
}

int main()
{
    { // try with mesh processing
        Surface_mesh cube;
        Surface_mesh prism;

        fill_cube (cube);
        fill_prism (prism);

        Surface_mesh result;
        // will return false
        bool success = CGAL::Polygon_mesh_processing::corefine_and_compute_difference (cube, prism, result);
    }

    { // try with nef polyhedron
        Polyhedron_3 cube;
        Polyhedron_3 prism;

        fill_cube (cube);
        fill_prism (prism);

        Nef_polyhedron_3 nefCube (cube);
        Nef_polyhedron_3 nefPrism (prism);

        Nef_polyhedron_3 result = nefCube - nefPrism;

        Surface_mesh resultMesh;
        // throws exception because is_polygon_soup_a_polygon_mesh(polygons) is false
        CGAL::convert_nef_polyhedron_to_polygon_mesh (result, resultMesh, true);
    }

    system ("pause");
}

Do you have any idea how to convert Nef_polyhedron_3 to triangle mesh?


Solution

  • In the output you have a non-manifold edge (one edge of the prism is tangent to a face of the cube). So the output is not a valid surface mesh, which is why the PMP approach is not returning an output and the nef cannot be converted into a polygon mesh too.

    I guess I could write a convert_nef_polyhedron_to_polygon_soup() that would give you a set of triangles and orient_polygon_soup() would be able to duplicate all non-manifold edges and you would get a self-intersecting triangle mesh.