Skip to content

Commit

Permalink
Nef_3: Fix conversion to a FaceGraph (CGAL#6727)
Browse files Browse the repository at this point in the history
## Summary of Changes

Fix the case of surfaces with borders. Then they may be incident to only
the unbounded volume which so far was ignored.

## Release Management

* Affected package(s): Nef_polyhedron_3
* Issue(s) solved (if any): fix CGAL#6423
  • Loading branch information
sloriot authored Aug 26, 2024
2 parents 9dea168 + d20cef2 commit 5791f21
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Kernel/global_functions_3.h>
#include <CGAL/Nef_S2/Generic_handle_map.h>

#include <unordered_map>

Expand Down Expand Up @@ -81,13 +82,15 @@ struct Shell_polygons_visitor
Vertex_index_map& vertex_indices;
PolygonRange& polygons;
bool triangulate_all_faces;
CGAL::Generic_handle_map<bool> Done;

Shell_polygons_visitor(Vertex_index_map& vertex_indices,
PolygonRange& polygons,
bool triangulate_all_faces)
: vertex_indices( vertex_indices )
, polygons(polygons)
, triangulate_all_faces(triangulate_all_faces)
, Done(false)
{}

std::size_t get_cycle_length( typename Nef_polyhedron::Halffacet_cycle_const_iterator hfc) const
Expand All @@ -103,6 +106,14 @@ struct Shell_polygons_visitor

void visit(typename Nef_polyhedron::Halffacet_const_handle opposite_facet)
{
typename Nef_polyhedron::Halffacet_const_handle twin_facet = opposite_facet->twin();

// skip when we have to do with the unbounded volume and a surface with boundaries
if ((twin_facet->incident_volume() == opposite_facet->incident_volume()) && Done[twin_facet])
return;

Done[opposite_facet] = true;

bool is_marked=opposite_facet->incident_volume()->mark();

CGAL_assertion(Nef_polyhedron::Infi_box::is_standard(opposite_facet->plane()));
Expand Down Expand Up @@ -351,18 +362,50 @@ void convert_nef_polyhedron_to_polygon_soup(const Nef_polyhedron& nef,
typedef Cartesian_converter<Nef_Kernel, Output_kernel> Converter;
typename Nef_polyhedron::Volume_const_iterator vol_it = nef.volumes_begin(),
vol_end = nef.volumes_end();
if ( Nef_polyhedron::Infi_box::extended_kernel() ) ++vol_it; // skip Infi_box
CGAL_assertion ( vol_it != vol_end );
++vol_it; // skip unbounded volume

if (Nef_polyhedron::Infi_box::extended_kernel()) ++vol_it; // skip Infi_box

if ( vol_it == vol_end ) return;

Converter to_output;
bool handling_unbounded_volume = true;

auto shell_is_closed = [](typename Nef_polyhedron::Shell_entry_const_iterator sfh)
{
typename Nef_polyhedron::SFace_const_handle sf = sfh;

typename Nef_polyhedron::SFace_cycle_const_iterator fc;
for(fc = sf->sface_cycles_begin(); fc != sf->sface_cycles_end(); ++fc)
{
if (fc.is_shalfedge() ) {
typename Nef_polyhedron::SHalfedge_const_handle e(fc);
typename Nef_polyhedron::SHalfedge_around_sface_const_circulator ec(e),ee(e);
CGAL_For_all(ec,ee)
{
typename Nef_polyhedron::Halffacet_const_handle f = ec->twin()->facet();
if (f->incident_volume()==f->twin()->incident_volume())
return false;
}
}
}

return true;
};

for (;vol_it!=vol_end;++vol_it)
nef_to_pm::collect_polygon_mesh_info(points,
polygons,
nef,
vol_it->shells_begin(),
to_output,
triangulate_all_faces);
{
for(auto sit = vol_it->shells_begin(); sit != vol_it->shells_end(); ++sit)
{
if ( (handling_unbounded_volume || sit!=vol_it->shells_begin()) && shell_is_closed(sit)) continue;
nef_to_pm::collect_polygon_mesh_info(points,
polygons,
nef,
sit,
to_output,
triangulate_all_faces);
}
handling_unbounded_volume = false;
}
}

template <class Nef_polyhedron, class Polygon_mesh>
Expand Down
45 changes: 45 additions & 0 deletions Nef_3/test/Nef_3/issue_6423.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.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 <CGAL/boost/graph/generators.h>
#include <CGAL/Surface_mesh.h>

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> SurfaceMesh;
typedef CGAL::Nef_polyhedron_3<Kernel> NefPolyhedron;


int main()
{
SurfaceMesh surfaceMesh;
SurfaceMesh::Vertex_index v0 = surfaceMesh.add_vertex(Point_3(-1, 0, 0));
SurfaceMesh::Vertex_index v1 = surfaceMesh.add_vertex(Point_3(1, 0, 0));
SurfaceMesh::Vertex_index v2 = surfaceMesh.add_vertex(Point_3(0, 1, 0));

SurfaceMesh::Vertex_index v3 = surfaceMesh.add_vertex(Point_3(-1, 0, 1));
SurfaceMesh::Vertex_index v4 = surfaceMesh.add_vertex(Point_3(1, 0, 1));
SurfaceMesh::Vertex_index v5 = surfaceMesh.add_vertex(Point_3(0, 1, 1));

surfaceMesh.add_face(v0, v1, v2);
surfaceMesh.add_face(v3, v4, v5);

make_tetrahedron(Point_3(-1, 0, 10),
Point_3(1, 0, 10),
Point_3(0, 1, 10),
Point_3(-1, 0, 11),
surfaceMesh);

std::cout << "Before conversion, number_of_faces: " << surfaceMesh.number_of_faces() << std::endl;

NefPolyhedron nefPoly(surfaceMesh);
std::cout << "NefPolyhedron, number_of_faces: " << nefPoly.number_of_facets() << std::endl;
SurfaceMesh convertedSurfaceMesh;
CGAL::convert_nef_polyhedron_to_polygon_mesh(nefPoly, convertedSurfaceMesh, true);
std::cout << "After conversion, number_of_faces: " << convertedSurfaceMesh.number_of_faces() << std::endl;
std::ofstream("out.off") << convertedSurfaceMesh;
assert(vertices(convertedSurfaceMesh).size()==10);
assert(faces(convertedSurfaceMesh).size()==6);
return EXIT_SUCCESS;
}

0 comments on commit 5791f21

Please sign in to comment.