mirror of https://github.com/CGAL/cgal
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:
commit
ca755e35a8
|
|
@ -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
|
||||
------------
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,23 +366,22 @@ 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,
|
||||
polygons,
|
||||
nef,
|
||||
vol_it->shells_begin(),
|
||||
to_output,
|
||||
triangulate_all_faces);
|
||||
nef_to_pm::collect_polygon_mesh_info(points,
|
||||
polygons,
|
||||
nef,
|
||||
vol_it->shells_begin(),
|
||||
to_output,
|
||||
triangulate_all_faces);
|
||||
}
|
||||
|
||||
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);
|
||||
std::vector<std::vector<std::size_t> > polygons;
|
||||
convert_nef_polyhedron_to_polygon_soup(nef, points, polygons, triangulate_all_faces);
|
||||
Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, polygons, pm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue