Merge pull request #3599 from maxGimeno/Nef_3-Document_Nef_3_to_Polygon_soup-GF

Nef_3 : Document convert_nef_polyhedron_to_polygon_soup-GF
This commit is contained in:
Sébastien Loriot 2019-04-23 09:52:26 +02:00
commit ca755e35a8
6 changed files with 151 additions and 50 deletions

View File

@ -13,6 +13,9 @@ Release date: September 2019
### IO Streams
- **Breaking change:** The API of `CGAL::Color` has been cleaned up.
###3D Boolean Operations on Nef Polyhedra
- Added a function to convert a Nef_polyhedron_3 to a polygon soup:
- `CGAL::convert_nef_to_polygon_soup()`
Release 4.14
------------

View File

@ -5,9 +5,47 @@ namespace CGAL {
/// Note that contrary to `Nef_polyhedron_3::convert_to_polyhedron()`, the output is not triangulated
/// (but faces with more than one connected component of the boundary).
/// The polygon mesh can be triangulated by setting `triangulate_all_faces` to `true` or by calling the function `triangulate_faces()`.
/// @tparam Nef_polyhedron an object of type `Nef_polyhedron_3`.
/// @tparam Polygon_mesh a model of `MutableFaceGraph` with an internal property map for `CGAL::vertex_point_t`.
///
/// The points from `nef` to `pm` are converted using
/// `CGAL::Cartesian_converter<NefKernel, TargetKernel>`.
/// `NefKernel` and `TargetKernel` are deduced using `CGAL::Kernel_traits`
/// from the point type of `nef` and the value type of the vertex_point_map of `tm`.
///
/// @param nef the input.
/// @param pm the output.
/// @param triangulate_all_faces indicates whether all the faces must be triangulated.
///
/// \pre `Polygon_mesh` must have an internal point property map with value type being `Nef_polyhedron_3::Point_3`.
/// \pre `nef.simple()`
template <class Nef_polyhedron, class Polygon_mesh>
void convert_nef_polyhedron_to_polygon_mesh(const Nef_polyhedron& nef, Polygon_mesh& pm, bool triangulate_all_faces = false);
/// \ingroup PkgNef3IOFunctions
/// Converts an objet of type `Nef_polyhedron_3` into a polygon soup.
/// The polygons can be triangulated by setting `triangulate_all_faces` to `true`.
/// @tparam Nef_polyhedron an object of type `Nef_polyhedron_3`.
/// @tparam PointRange a model of the concept `BackInsertionSequence`
/// whose `value_type` is the point type
/// @tparam PolygonRange a model of the concept
/// `BackInsertionSequence` whose `value_type` is a model of the concept
/// `BackInsertionSequence` whose
/// `value_type` is `std::size_t`.
///
/// The points from `nef` to `points` are converted using
/// `CGAL::Cartesian_converter<NefKernel, OutputKernel>`.
/// `NefKernel` and `OutputKernel` are deduced using `CGAL::Kernel_traits`
/// from the point types.
///
/// @param nef the input.
/// @param points the output points of the soup
/// @param polygons the output polygons of the soup.
/// @param triangulate_all_faces indicates whether all polygons must be triangulated.
template <class Nef_polyhedron, typename PolygonRange, typename PointRange>
void convert_nef_polyhedron_to_polygon_soup(const Nef_polyhedron& nef,
PointRange& points,
PolygonRange& polygons,
bool triangulate_all_faces = false);
}

View File

@ -60,6 +60,7 @@ a simple OpenGL visualization for debugging and illustrations.
\cgalCRPSection{Functions}
- `CGAL::OFF_to_nef_3()`
- `CGAL::convert_nef_polyhedron_to_polygon_mesh()`
- `CGAL::convert_nef_polyhedron_to_polygon_soup()`
- \link PkgNef3IOFunctions `CGAL::operator<<()` \endlink
- \link PkgNef3IOFunctions `CGAL::operator>>()` \endlink

View File

@ -42,15 +42,17 @@ namespace CGAL{
namespace nef_to_pm{
// Visitor used to collect and index vertices of a shell
template<class Nef_polyhedron, class Point_3, class Converter>
template<class Nef_polyhedron, class PointRange, class Converter>
struct Shell_vertex_index_visitor
{
typedef boost::unordered_map<typename Nef_polyhedron::Vertex_const_handle, std::size_t> Vertex_index_map;
std::vector<Point_3>& points;
typedef boost::unordered_map<
typename Nef_polyhedron::Vertex_const_handle, std::size_t> Vertex_index_map;
typedef typename PointRange::value_type Point_3;
PointRange& points;
Vertex_index_map vertex_indices;
const Converter& converter;
Shell_vertex_index_visitor(std::vector<Point_3>& points, const Converter& converter)
Shell_vertex_index_visitor(PointRange& points, const Converter& converter)
:points(points), converter(converter)
{}
@ -80,16 +82,17 @@ struct FaceInfo2
};
//Visitor used to collect polygons
template <class Nef_polyhedron>
template <class Nef_polyhedron, typename PolygonRange>
struct Shell_polygons_visitor
{
typedef boost::unordered_map<typename Nef_polyhedron::Vertex_const_handle, std::size_t> Vertex_index_map;
typedef typename PolygonRange::value_type Polygon;
Vertex_index_map& vertex_indices;
std::vector< std::vector<std::size_t> >& polygons;
PolygonRange& polygons;
bool triangulate_all_faces;
Shell_polygons_visitor(Vertex_index_map& vertex_indices,
std::vector< std::vector<std::size_t> >& polygons,
PolygonRange& polygons,
bool triangulate_all_faces)
: vertex_indices( vertex_indices )
, polygons(polygons)
@ -146,22 +149,22 @@ struct Shell_polygons_visitor
{
if (is_marked)
{
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[1]]);
polygons.back().push_back(vertex_indices[v[2]]);
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[2]]);
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[3]]);
}
else
{
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[1]]);
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[2]]);
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[2]]);
polygons.back().push_back(vertex_indices[v[3]]);
@ -171,22 +174,22 @@ struct Shell_polygons_visitor
{
if (is_marked)
{
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[1]]);
polygons.back().push_back(vertex_indices[v[3]]);
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[3]]);
polygons.back().push_back(vertex_indices[v[1]]);
polygons.back().push_back(vertex_indices[v[2]]);
}
else
{
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[0]]);
polygons.back().push_back(vertex_indices[v[3]]);
polygons.back().push_back(vertex_indices[v[1]]);
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
polygons.back().push_back(vertex_indices[v[1]]);
polygons.back().push_back(vertex_indices[v[3]]);
polygons.back().push_back(vertex_indices[v[2]]);
@ -197,7 +200,7 @@ struct Shell_polygons_visitor
case 3:
{
// create a new polygon
polygons.push_back( std::vector<std::size_t>() );
polygons.push_back( Polygon() );
fc = f->facet_cycles_begin();
se = typename Nef_polyhedron::SHalfedge_const_handle(fc);
CGAL_assertion(se!=0);
@ -288,7 +291,7 @@ struct Shell_polygons_visitor
queue.pop_back();
if (e.first->info().visited) continue;
e.first->info().visited=true;
polygons.resize(polygons.size()+1);
polygons.push_back(Polygon());
if (is_marked)
for (int i=2; i>=0; --i)
polygons.back().push_back(e.first->vertex(i)->info());
@ -320,21 +323,21 @@ struct Shell_polygons_visitor
{}
};
template <class Point_3, class Nef_polyhedron, class Converter>
template <typename PointRange, class Nef_polyhedron, class Converter, typename PolygonRange>
void collect_polygon_mesh_info(
std::vector<Point_3>& points,
std::vector< std::vector<std::size_t> >& polygons,
PointRange& points,
PolygonRange& polygons,
Nef_polyhedron& nef,
typename Nef_polyhedron::Shell_entry_const_iterator shell,
const Converter& converter,
bool triangulate_all_faces)
{
// collect points and set vertex indices
Shell_vertex_index_visitor<Nef_polyhedron, Point_3, Converter> vertex_index_visitor(points, converter);
Shell_vertex_index_visitor<Nef_polyhedron, PointRange, Converter> vertex_index_visitor(points, converter);
nef.visit_shell_objects(typename Nef_polyhedron::SFace_const_handle(shell), vertex_index_visitor);
// collect polygons
Shell_polygons_visitor<Nef_polyhedron> polygon_visitor(
Shell_polygons_visitor<Nef_polyhedron, PolygonRange> polygon_visitor(
vertex_index_visitor.vertex_indices,
polygons,
triangulate_all_faces);
@ -343,16 +346,18 @@ void collect_polygon_mesh_info(
} //end of namespace nef_to_pm
template <class Output_kernel, class Nef_polyhedron>
template < class Nef_polyhedron, typename PolygonRange, typename PointRange>
void convert_nef_polyhedron_to_polygon_soup(const Nef_polyhedron& nef,
std::vector<typename Output_kernel::Point_3>& points,
std::vector< std::vector<std::size_t> >& polygons,
PointRange& points,
PolygonRange& polygons,
bool triangulate_all_faces = false)
{
typedef typename Nef_polyhedron::Point_3 Point_3;
typedef typename Kernel_traits<Point_3>::Kernel Nef_Kernel;
typedef typename PointRange::value_type Out_Point;
typedef typename Kernel_traits<Out_Point>::Kernel Output_kernel;
typedef Cartesian_converter<Nef_Kernel, Output_kernel> Converter;
typedef typename Output_kernel::Point_3 Out_point;
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
@ -361,7 +366,7 @@ void convert_nef_polyhedron_to_polygon_soup(const Nef_polyhedron& nef,
Converter to_output;
for (;vol_it!=vol_end;++vol_it)
nef_to_pm::collect_polygon_mesh_info<Out_point>(points,
nef_to_pm::collect_polygon_mesh_info(points,
polygons,
nef,
vol_it->shells_begin(),
@ -373,11 +378,10 @@ template <class Nef_polyhedron, class Polygon_mesh>
void convert_nef_polyhedron_to_polygon_mesh(const Nef_polyhedron& nef, Polygon_mesh& pm, bool triangulate_all_faces = false)
{
typedef typename boost::property_traits<typename boost::property_map<Polygon_mesh, vertex_point_t>::type>::value_type PM_Point;
typedef typename Kernel_traits<PM_Point>::Kernel PM_Kernel;
std::vector<PM_Point> points;
std::vector<std::vector<std::size_t> > polygons;
convert_nef_polyhedron_to_polygon_soup<PM_Kernel>(nef, points, polygons, triangulate_all_faces);
convert_nef_polyhedron_to_polygon_soup(nef, points, polygons, triangulate_all_faces);
Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, polygons, pm);
}

View File

@ -0,0 +1,50 @@
#include <CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <fstream>
typedef CGAL::Exact_predicates_exact_constructions_kernel EPEC;
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC;
int main()
{
typedef CGAL::Nef_polyhedron_3< EPEC > Nef_polyhedron;
typedef CGAL::Polyhedron_3< EPEC > Polyhedron;
typedef CGAL::Polyhedron_3< EPIC > PolygonMesh;
typedef typename EPIC::Point_3 Point;
typedef std::list<std::list<std::size_t> > PolygonRange;
typedef std::list<Point> PointRange;
typename EPEC::RT n, d;
std::istringstream str_n("6369051672525773");
str_n >> n;
std::istringstream str_d("4503599627370496");
str_d >> d;
EPEC::Point_3 p(n, 0, 0, d);
EPEC::Point_3 q(0, n, 0, d);
EPEC::Point_3 r(0, 0, n, d);
EPEC::Point_3 s(0, 0, 0, 1);
std::cout << " build...\n";
Polyhedron P;
P.make_tetrahedron( p, q, r, s);
Nef_polyhedron nef( P );
PointRange points;
PolygonRange polygons;
std::cout << " convert...\n";
CGAL::convert_nef_polyhedron_to_polygon_soup(nef, points, polygons);
CGAL_assertion(points.size() == 4);
CGAL_assertion(polygons.size() == 4);
PolygonMesh pm;
CGAL::convert_nef_polyhedron_to_polygon_mesh<
Nef_polyhedron,
PolygonMesh>(nef, pm);
return 0;
}

View File

@ -44,12 +44,12 @@ namespace Polygon_mesh_processing
namespace internal
{
template <typename PM
, typename Point
, typename Polygon>
, typename PointRange
, typename PolygonRange>
class Polygon_soup_to_polygon_mesh
{
const std::vector<Point>& _points;
const std::vector<Polygon>& _polygons;
const PointRange& _points;
const PolygonRange& _polygons;
typedef typename boost::property_map<PM, CGAL::vertex_point_t>::type Vpmap;
typedef typename boost::property_traits<Vpmap>::value_type Point_3;
@ -57,15 +57,17 @@ class Polygon_soup_to_polygon_mesh
typedef typename boost::graph_traits<PM>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<PM>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PM>::face_descriptor face_descriptor;
typedef typename PolygonRange::value_type Polygon;
typedef typename PointRange::value_type Point;
public:
/**
* The constructor for modifier object.
* @param points points of the soup of polygons.
* @param polygons each element in the vector describes a polygon using the index of the points in the vector.
* @param polygons each element in the range describes a polygon using the index of the points in the range.
*/
Polygon_soup_to_polygon_mesh(const std::vector<Point>& points,
const std::vector<Polygon>& polygons)
Polygon_soup_to_polygon_mesh(const PointRange& points,
const PolygonRange& polygons)
: _points(points),
_polygons(polygons)
{ }
@ -195,10 +197,13 @@ public:
* @pre the input polygon soup describes a consistently oriented
* polygon mesh.
*
* @tparam PolygonMesh a model of `MutableFaceGraph` with an internal point property map
* @tparam Point a point type that has an operator `[]` to access coordinates
* @tparam Polygon a `std::vector<std::size_t>` containing the indices
* of the points of the face
* @tparam PolygonMesh a model of `MutableFaceGraph` with an internal point
* property map
* @tparam PointRange a model of the concepts `RandomAccessContainer` and
* `BackInsertionSequence` whose value type is the point type
* @tparam PolygonRange a model of the concept `RandomAccessContainer` whose
* `value_type` is a model of the concept `RandomAccessContainer` whose `value_type` is `std::size_t`.
*
* @param points points of the soup of polygons
* @param polygons each element in the vector describes a polygon using the index of the points in `points`
@ -211,16 +216,16 @@ public:
* \sa `CGAL::Polygon_mesh_processing::is_polygon_soup_a_polygon_mesh()`
*
*/
template<class PolygonMesh, class Point, class Polygon>
template<class PolygonMesh, class PointRange, class PolygonRange>
void polygon_soup_to_polygon_mesh(
const std::vector<Point>& points,
const std::vector<Polygon>& polygons,
const PointRange& points,
const PolygonRange& polygons,
PolygonMesh& out)
{
CGAL_precondition_msg(is_polygon_soup_a_polygon_mesh(polygons),
"Input soup needs to be a polygon mesh!");
internal::Polygon_soup_to_polygon_mesh<PolygonMesh, Point, Polygon>
internal::Polygon_soup_to_polygon_mesh<PolygonMesh, PointRange, PolygonRange>
converter(points, polygons);
converter(out);
}