mirror of https://github.com/CGAL/cgal
Add a function and associated test that orient all the connected components of a triangulated face graph positively.
This commit is contained in:
parent
286013bd27
commit
9f986ea9ef
|
|
@ -25,12 +25,14 @@
|
|||
|
||||
#include <CGAL/license/Polygon_mesh_processing/orientation.h>
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <CGAL/Polygon_mesh_processing/connected_components.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_function_params.h>
|
||||
#include <CGAL/Polygon_mesh_processing/internal/named_params_helper.h>
|
||||
#include <CGAL/Projection_traits_xy_3.h>
|
||||
#include <CGAL/Projection_traits_xz_3.h>
|
||||
#include <CGAL/Projection_traits_yz_3.h>
|
||||
#include <CGAL/boost/graph/helpers.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
|
||||
|
|
@ -114,7 +116,21 @@ namespace internal{
|
|||
Orientation p1p2p3_2d = orientation_2(p1, p2, p3);
|
||||
Orientation p2p1p4_2d = orientation_2(p2, p1, p4);
|
||||
|
||||
CGAL_assertion( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR ); // no self-intersection
|
||||
if(!( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR ))
|
||||
{
|
||||
Projection_traits_xz_3<GT> p_gt_bis;
|
||||
typename Projection_traits_xz_3<GT>::Orientation_2 orientation_2_bis = p_gt_bis.orientation_2_object();
|
||||
p1p2p3_2d = orientation_2_bis(p1, p2, p3);
|
||||
p2p1p4_2d = orientation_2_bis(p2, p1, p4);
|
||||
if(!( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR ))
|
||||
{
|
||||
Projection_traits_yz_3<GT> p_gt_last;
|
||||
typename Projection_traits_yz_3<GT>::Orientation_2 orientation_2_last = p_gt_last.orientation_2_object();
|
||||
p1p2p3_2d = orientation_2_last(p1, p2, p3);
|
||||
p2p1p4_2d = orientation_2_last(p2, p1, p4);
|
||||
}
|
||||
}
|
||||
CGAL_assertion( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR );//no self-intersection
|
||||
|
||||
if ( p1p2p3_2d == COLLINEAR)
|
||||
return p2p1p4_2d == LEFT_TURN;
|
||||
|
|
@ -335,6 +351,91 @@ void reverse_face_orientations(const FaceRange& face_range, PolygonMesh& pmesh)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup PMP_orientation_grp
|
||||
* makes the orientation of all the connected_components of a `TriangleMesh` positive.
|
||||
* A closed polygon mesh is considered to have a positive orientation if the normal vectors
|
||||
* to all its faces point outside the domain bounded by the polygon mesh.
|
||||
* The normal vector to each face is chosen pointing on the side of the face
|
||||
* where its sequence of vertices is seen counterclockwise.
|
||||
*
|
||||
* @tparam TriangleMesh a model of `FaceListGraph` and `MutableFaceGraph` with no self-intersection.
|
||||
* @tparam NamedParameters a sequence of \ref namedparameters
|
||||
*
|
||||
* @param tm a triangulated `TriangleMesh`
|
||||
* @param np optional sequence of \ref namedparameters among the ones listed below
|
||||
*
|
||||
* \cgalNamedParamsBegin
|
||||
* \cgalParamBegin{vertex_point_map}
|
||||
* the property map with the points associated to the vertices of `tm`.
|
||||
* If this parameter is omitted, an internal property map for
|
||||
* `CGAL::vertex_point_t` should be available in `TriangleMesh`
|
||||
* \cgalParamEnd
|
||||
* \cgalParamBegin{face_index_map}
|
||||
* a property map containing the index of each face of `tm`.
|
||||
* \cgalParamEnd
|
||||
* \cgalNamedParamsEnd
|
||||
*/
|
||||
template<class TriangleMesh, class NamedParameters>
|
||||
void orient_connected_components(TriangleMesh& tm, const NamedParameters& np)
|
||||
{
|
||||
typedef boost::graph_traits<TriangleMesh> GT;
|
||||
typedef typename GT::vertex_descriptor vertex_descriptor;
|
||||
typedef typename GT::face_descriptor face_descriptor;
|
||||
typedef typename GetVertexPointMap<TriangleMesh,
|
||||
NamedParameters>::const_type Vpm;
|
||||
typedef typename GetFaceIndexMap<TriangleMesh,
|
||||
NamedParameters>::const_type Fid_map;
|
||||
|
||||
if (!is_triangle_mesh(tm)) return ;
|
||||
|
||||
Vpm vpm = boost::choose_param(get_param(np, internal_np::vertex_point),
|
||||
get_const_property_map(boost::vertex_point, tm));
|
||||
|
||||
Fid_map fid_map = boost::choose_param(get_param(np, internal_np::face_index),
|
||||
get_const_property_map(boost::face_index, tm));
|
||||
|
||||
std::vector<std::size_t> face_cc(num_faces(tm), std::size_t(-1));
|
||||
|
||||
// set the connected component id of each face
|
||||
std::size_t nb_cc = connected_components(tm,
|
||||
bind_property_maps(fid_map,make_property_map(face_cc)),
|
||||
parameters::face_index_map(fid_map));
|
||||
|
||||
if (nb_cc == 1)
|
||||
return;
|
||||
|
||||
// extract a vertex with max z coordinate for each connected component
|
||||
std::vector<vertex_descriptor> xtrm_vertices(nb_cc, GT::null_vertex());
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(tm))
|
||||
{
|
||||
face_descriptor test_face = face(halfedge(vd, tm), tm);
|
||||
if(test_face == GT::null_face())
|
||||
continue;
|
||||
std::size_t cc_id = face_cc[get(fid_map,test_face )];
|
||||
if (xtrm_vertices[cc_id]==GT::null_vertex())
|
||||
xtrm_vertices[cc_id]=vd;
|
||||
else
|
||||
if (get(vpm, vd).z()>get(vpm,xtrm_vertices[cc_id]).z())
|
||||
xtrm_vertices[cc_id]=vd;
|
||||
}
|
||||
std::vector<std::vector<face_descriptor> > ccs(nb_cc);
|
||||
BOOST_FOREACH(face_descriptor fd, faces(tm))
|
||||
{
|
||||
ccs[face_cc[get(fid_map,fd)]].push_back(fd);
|
||||
}
|
||||
|
||||
//orient ccs outward
|
||||
for(std::size_t id=0; id<nb_cc; ++id)
|
||||
{
|
||||
if(!internal::is_outward_oriented(xtrm_vertices[id], tm, np))
|
||||
{
|
||||
reverse_face_orientations(ccs[id]
|
||||
,tm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Polygon_mesh_processing
|
||||
} // namespace CGAL
|
||||
#endif // CGAL_ORIENT_POLYGON_MESH_H
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ endif()
|
|||
create_single_source_cgal_program("test_pmp_clip.cpp")
|
||||
create_single_source_cgal_program("triangulate_hole_polyline_test.cpp")
|
||||
create_single_source_cgal_program("surface_intersection_sm_poly.cpp" )
|
||||
create_single_source_cgal_program("test_orient_cc.cpp")
|
||||
|
||||
if(OpenMesh_FOUND)
|
||||
create_single_source_cgal_program("remeshing_test_P_SM_OM.cpp" )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/orientation.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace CGAL;
|
||||
namespace PMP = Polygon_mesh_processing;
|
||||
|
||||
typedef Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Surface_mesh<Kernel::Point_3> Surface_mesh;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
std::ifstream input("data-coref/nested_cubes_invalid_volume.off");
|
||||
assert(input);
|
||||
::Surface_mesh sm;
|
||||
input >> sm;
|
||||
PMP::orient_connected_components(sm, PMP::parameters::all_default());
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue