MEPP2 Project
calculate_face_normal.hpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 #include <boost/graph/graph_traits.hpp>
14 #include <boost/graph/properties.hpp>
16 
17 namespace FEVV {
18 namespace Operators {
19 
31 template< typename HalfedgeGraph, typename PointMap, typename GeometryTraits >
34  typename boost::graph_traits< HalfedgeGraph >::face_descriptor f,
35  const HalfedgeGraph &g,
36  const PointMap &pm,
37  const GeometryTraits &gt)
38 {
39  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
40  typedef typename GraphTraits::halfedge_descriptor halfedge_descriptor;
41  typedef typename GeometryTraits::Point Point;
42  typedef typename GeometryTraits::Vector Vector;
43 
44  halfedge_descriptor edg = halfedge(f, g);
45  halfedge_descriptor edgb = edg;
46 
47  Point p0 = get(pm, target(edg, g));
48  edg = next(edg, g);
49  Point p1 = get(pm, target(edg, g));
50  edg = next(edg, g);
51  Point p2 = get(pm, target(edg, g));
52  edg = next(edg, g);
53 
54  if(edg == edgb)
55  {
56  // triangle
57  try
58  {
59  Vector normal = gt.unit_normal(p1, p2, p0);
60  return normal;
61  }
62  catch(const std::exception &e)
63  {
64  // When 2 edges of the face are collinear an exception is triggered, in
65  // debug mode only. Then the line:
66  // std::cout << "e.what() = '" << e.what() << "'" << std::endl;
67  // produces the following output:
68  // e.what() = 'CGAL ERROR: precondition violation!
69  // Expr: ! K().collinear_3_object()(p,q,r)
70  // File: /home/eric/CGAL-4.11/include/CGAL/Kernel/function_objects.h
71  // Line: 2490'
72 
73  if(std::string(e.what()).find("collinear_3_object") == std::string::npos)
74  {
75  // This is NOT the true 'collinear' exception. Re-throw the exception
76  // unchanged.
77  throw;
78  }
79 
80  // This is the true 'collinear' exception. We set normal vector to be
81  // (NaN, NaN, NaN) and hope the caller will find out that the normal
82  // is snafu.
83  Vector normal(std::numeric_limits< double >::quiet_NaN(),
84  std::numeric_limits< double >::quiet_NaN(),
85  std::numeric_limits< double >::quiet_NaN());
86 
87  return normal;
88  }
89  }
90  else
91  { // not a triangle but a quad, a polygon
92 
93  // The correct algorithme would be to compute the optimal plane fitting
94  // all the face vertices. However this would be too computationally
95  // expensive for such a common operation and hence we fold back to
96  // computing the mean of the normals of the triangles build out of
97  // triplets of vertices "skifully" taken among the vertices of the face.
98  Vector n(gt.normal(p1, p2, p0));
99 
100  p0 = p2; // do not move P0 in the following loop
101  do
102  {
103  edg = next(edg, g);
104  p1 = get(pm, source(edg, g));
105  p2 = get(pm, target(edg, g));
106 
107  n = gt.add_v(n, gt.normal(p1, p2, p0));
108  } while(edg != edgb);
109 
110  return gt.normalize(n);
111  }
112 }
113 
114 } // namespace Operators
115 } // namespace FEVV
FEVV::DataStructures::AIF::next
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor next(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the next halfedge around its face.
Definition: Graph_traits_aif.h:599
Vector
AIFMesh::Vector Vector
Definition: Graph_properties_aif.h:22
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
FEVV::DataStructures::AIF::source
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor source(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the source vertex of e.
Definition: Graph_traits_aif.h:387
FEVV::Operators::calculate_face_normal
GeometryTraits::Vector calculate_face_normal(typename boost::graph_traits< HalfedgeGraph >::face_descriptor f, const HalfedgeGraph &g, const PointMap &pm, const GeometryTraits &gt)
Calculate "some" normal to the considered face.
Definition: calculate_face_normal.hpp:33
FEVV::get
FEVV::PCLPointCloudPointMap::value_type get(const FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key)
Specialization of get(point_map, key) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:117
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::DataStructures::AIF::halfedge
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor halfedge(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor v, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns a halfedge with target v.
Definition: Graph_traits_aif.h:296
FEVV::DataStructures::AIF::target
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor target(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the target vertex of e.
Definition: Graph_traits_aif.h:400
Geometry_traits.h
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31