MEPP2 Project
Geometric_metrics.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2022 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 
12 #pragma once
13 
14 #include <boost/graph/graph_traits.hpp>
15 #include <boost/graph/properties.hpp>
16 
17 #include <CGAL/Polygon_mesh_processing/distance.h>
18 #include <CGAL/Polygon_mesh_processing/remesh.h>
19 #include <CGAL/AABB_tree.h>
20 #include <CGAL/AABB_traits.h>
21 #include <CGAL/AABB_face_graph_triangle_primitive.h>
22 
24 
25 #include <list>
26 #include <vector>
27 #include <utility>
28 
29 #if defined(CGAL_LINKED_WITH_TBB)
30 #define TAG CGAL::Parallel_tag
31 #else
32 #define TAG CGAL::Sequential_tag
33 #endif
34 
35 
36 namespace FEVV {
37  namespace Filters {
38 
48 template <typename HalfedgeGraph,
49  typename PointMap,
50  typename face_iterator = typename boost::graph_traits<HalfedgeGraph>::face_iterator,
53 
55 {
56  public:
57  typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
58  typedef CGAL::AABB_face_graph_triangle_primitive<HalfedgeGraph> AABB_primitive;
59  typedef CGAL::AABB_traits<CGALKernel, AABB_primitive> AABB_traits;
60  typedef CGAL::AABB_tree<AABB_traits> AABB_tree;
61 
62  Geometric_metrics(const HalfedgeGraph& LoD_init, const PointMap& pm_init) : _LoD_init(LoD_init), _pm_init(pm_init)
63  {
65 
67  }
68 
70  double compute_hausdorff(const HalfedgeGraph& LoD, int cas)
71  {
72  if(cas == 0)
73  {
74  return CGAL::Polygon_mesh_processing::approximate_Hausdorff_distance<TAG>(LoD,
75  _LoD_init,
76  CGAL::Polygon_mesh_processing::parameters::number_of_points_per_area_unit(_number_of_points_per_area_unit_LoD_init));
77  }
78  else
79  { // Computes the approximate Hausdorff distance from _LoD_init to LoD by returning the distance of the farthest point from LoD
80  // amongst a sampling of _LoD_init generated with the function sample_triangle_mesh() with _LoD_init and np1 as parameter.
81  return CGAL::Polygon_mesh_processing::approximate_Hausdorff_distance<TAG>(_LoD_init,
82  LoD,
83  CGAL::Polygon_mesh_processing::parameters::number_of_points_per_area_unit(_number_of_points_per_area_unit_LoD_init));
84  }
85  }
86  protected:
88  {
89  std::pair<face_iterator, face_iterator> f_range_it= faces(_LoD_init);
90  face_iterator orig_begin = f_range_it.first;
91  face_iterator orig_end = f_range_it.second;
92 
93  _LoD_init_tree.clear();
94 
95  _LoD_init_tree.insert(orig_begin, orig_end, _LoD_init);
96  _LoD_init_tree.accelerate_distance_queries();
97  }
98 
100  {
101  _vec_distorsion.clear();
102  std::vector<double> empty_vector;
103  std::swap(_vec_distorsion, empty_vector);
104  _vec_distorsion.push_back(0.0);
105 
106  _samples_LoD_init.clear();
107  std::list<Point> empty_list;
108  std::swap(_samples_LoD_init, empty_list);
109 
110  _area = CGAL::Polygon_mesh_processing::area(_LoD_init);
111  auto nb_v = FEVV::size_of_vertices(_LoD_init);
112  _grid_spacing = std::sqrt(_area / FEVV::size_of_faces(_LoD_init) * 4 / std::sqrt(3));// we assume that they are only triangles
113 
114  CGAL::Polygon_mesh_processing::sample_triangle_mesh(_LoD_init,
115  std::back_inserter(_samples_LoD_init),
116  // the following set of parameters allow an approximate RMSE computation
117  CGAL::Polygon_mesh_processing::parameters::use_grid_sampling(true)
118  .grid_spacing(_grid_spacing)
119  // the following set of parameters does not allow an RMSE computation:
120  // CGAL::Polygon_mesh_processing::parameters::use_random_uniform_sampling(true)
121  // .do_sample_faces(false)
122  // .do_sample_edges(false)
123  // .do_sample_vertices(true)
124  );
125  // the value of this attribute depends on
126  // the selected parameters for sample_triangle_mesh
127 
128  _number_of_points_per_area_unit_LoD_init = nb_v / std::max(0.001, _area) ;
129  //std::cout << "area = " << CGAL::Polygon_mesh_processing::area(_LoD_init) << " ; _number_of_points_per_area_unit_LoD_init = " << _number_of_points_per_area_unit_LoD_init << std::endl;
130 
131  }
132  double compute_L2(const HalfedgeGraph& mesh_to_sample,
133  int cas,
134  bool compute_RMSE_instead_of_max
135  )
136  {
138 
139  using Point_and_primitive_id = typename AABB_tree::Point_and_primitive_id;
140 
141  double L2_error = 0.0;
142  if(cas == 0) // use AABB_tree of init mesh (the finest one) and sample the mesh_to_sample mesh
143  { // distance D(mesh_to_sample, _LoD_init) = min/mean/max over all samples p of min ||p - p_LoD_init||
144  // 1) subsampling of the current LoD
145  std::list<Point> samples;
146  CGAL::Polygon_mesh_processing::sample_triangle_mesh(mesh_to_sample,
147  std::back_inserter(samples),
148 
149  // the following set of parameters allow an approximate RMSE computation
150  CGAL::Polygon_mesh_processing::parameters::use_grid_sampling(true)
151  .grid_spacing(_grid_spacing)
152  // the following set of parameters does not allow an RMSE computation:
153  //CGAL::Polygon_mesh_processing::parameters::use_random_uniform_sampling(true)
154  //.do_sample_faces(true)
155  //.do_sample_edges(true)
156  //.do_sample_vertices(true)
157  //.number_of_points_per_area_unit(_number_of_points_per_area_unit_LoD_init)
158  );
159  std::cout << "L2 cas 0: " << samples.size() << " samples" << std::endl;
160  // 2) compute distance between points and init surface (_LoD_init)
161  for(auto it = samples.begin(); it != samples.end(); ++it)
162  {
163  // computes closest point and primitive id
164  Point_and_primitive_id pp = _LoD_init_tree.closest_point_and_primitive(*it);
165  // get euclidean distance from point *it to surface mesh _LoD_init
166  Vector d = gt.sub_p(pp.first, *it);
167  if(compute_RMSE_instead_of_max)
168  L2_error += gt.length2(d);
169  else
170  { // max is better than either mean or min
171  auto dist = gt.length(d);
172  if(dist > L2_error)
173  L2_error = dist;
174  }
175  }
176  if(compute_RMSE_instead_of_max)
177  L2_error = std::sqrt( L2_error / (double)samples.size() ); // RMSE
178  }
179  else // opposite case
180  { // distance D(_LoD_init, mesh_to_sample) = min/mean/max over all samples p of min ||p - p_mesh_to_sample||
181  std::pair<face_iterator, face_iterator> f_range_it = faces(mesh_to_sample);
182  face_iterator orig_begin = f_range_it.first;
183  face_iterator orig_end = f_range_it.second;
184 
185  AABB_tree tree(orig_begin, orig_end, mesh_to_sample);
186  tree.accelerate_distance_queries();
187  std::cout << "L2 cas 1: " << _samples_LoD_init.size() << " init samples" << std::endl;
188  // Searching for the closest point and facet for each vertex and compute L2
189  for(auto it = _samples_LoD_init.begin(); it != _samples_LoD_init.end(); ++it)
190  {
191  // computes closest point and primitive id
192  Point_and_primitive_id pp = tree.closest_point_and_primitive(*it);
193  // get euclidean distance from point *it to surface mesh mesh_to_sample
194  Vector d = gt.sub_p(pp.first, *it);
195  if(compute_RMSE_instead_of_max)
196  L2_error += gt.length2(d);
197  else
198  { // max is better than either mean or min
199  auto dist = gt.length(d);
200  if(dist > L2_error)
201  L2_error = dist;
202  }
203  }
204  if(compute_RMSE_instead_of_max)
205  L2_error = std::sqrt( L2_error / (double)_samples_LoD_init.size() ); // RMSE
206  }
207  return L2_error;
208  }
209  public:
211  double compute_symmetric_L2(const HalfedgeGraph& LoD, bool compute_RMSE_instead_of_max)
212  {
213  double d_LoD_to_mesh_init = this->compute_L2(LoD, 0, compute_RMSE_instead_of_max);
214  double d_mesh_init_to_LoD = this->compute_L2(LoD, 1, compute_RMSE_instead_of_max);
215 
216  // Hausdorff or RMSE distances: the symmetrical distance takes the max
217  double d_max = (d_LoD_to_mesh_init < d_mesh_init_to_LoD) ? d_mesh_init_to_LoD : d_LoD_to_mesh_init;
218 
219  // save distorsion values (history of computed values)
220  _vec_distorsion.push_back(d_max);
221 
222  return d_max;
223  }
224 
227  const std::vector<double>& get_vec_distorsion() const { return _vec_distorsion; }
228 
229  private:
230  HalfedgeGraph _LoD_init; // copy of init mesh: cannot be const (error with AABB otherwise)
231  PointMap _pm_init; // copy of init pm
233  std::list<Point> _samples_LoD_init;
234 
237 
238  std::vector<double> _vec_distorsion; // distortion values for all batches
239 
240 };
241 } // namespace Filters
242 } // namespace FEVV
FEVV::Filters::Geometric_metrics::AABB_traits
CGAL::AABB_traits< CGALKernel, AABB_primitive > AABB_traits
Definition: Geometric_metrics.h:59
FEVV::Filters::Geometric_metrics::AABB_primitive
CGAL::AABB_face_graph_triangle_primitive< HalfedgeGraph > AABB_primitive
Definition: Geometric_metrics.h:58
FEVV::Filters::Geometric_metrics::subsample_LoD_init
void subsample_LoD_init()
Definition: Geometric_metrics.h:99
FEVV::Filters::Geometric_metrics::_area
double _area
Definition: Geometric_metrics.h:236
FEVV::Filters::Geometric_metrics::initialize_AABB_tree_for_init_LoD
void initialize_AABB_tree_for_init_LoD()
Definition: Geometric_metrics.h:87
FEVV::Filters::Geometric_metrics::Geometric_metrics
Geometric_metrics(const HalfedgeGraph &LoD_init, const PointMap &pm_init)
Definition: Geometric_metrics.h:62
FEVV::Filters::Geometric_metrics::K
CGAL::Exact_predicates_inexact_constructions_kernel K
Definition: Geometric_metrics.h:57
FEVV::Geometry_traits
Refer to Geometry_traits_documentation_dummy for further documentation on provided types and algorith...
Definition: Geometry_traits.h:162
FEVV::Filters::Geometric_metrics
Geometric_metrics is a class dedicated to the geometric distance computation between an original full...
Definition: Geometric_metrics.h:55
FEVV::Filters::Geometric_metrics::_LoD_init_tree
AABB_tree _LoD_init_tree
Definition: Geometric_metrics.h:232
FEVV::Filters::Geometric_metrics::_LoD_init
HalfedgeGraph _LoD_init
Definition: Geometric_metrics.h:230
FEVV::Filters::Geometric_metrics::compute_hausdorff
double compute_hausdorff(const HalfedgeGraph &LoD, int cas)
CGAL Hausdorff distance implementation.
Definition: Geometric_metrics.h:70
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::DataStructures::AIF::faces
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_iterator > faces(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns an iterator range over all faces of the mesh.
Definition: Graph_traits_aif.h:679
FEVV::Filters::Geometric_metrics::_grid_spacing
double _grid_spacing
Definition: Geometric_metrics.h:236
FEVV::Filters::Geometric_metrics::compute_symmetric_L2
double compute_symmetric_L2(const HalfedgeGraph &LoD, bool compute_RMSE_instead_of_max)
Proposed RMSE and Hausdorff distances implementation.
Definition: Geometric_metrics.h:211
Geometry_traits.h
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::size_of_faces
boost::graph_traits< MeshT >::faces_size_type size_of_faces(const MeshT &g)
Real current number of faces of the mesh. Generic version.
Definition: Graph_traits_extension.h:80
FEVV::Filters::Geometric_metrics::_vec_distorsion
std::vector< double > _vec_distorsion
Definition: Geometric_metrics.h:238
FEVV::Filters::Geometric_metrics::get_vec_distorsion
const std::vector< double > & get_vec_distorsion() const
compared with the same reference mesh).
Definition: Geometric_metrics.h:227
FEVV::Filters::Geometric_metrics::_samples_LoD_init
std::list< Point > _samples_LoD_init
Definition: Geometric_metrics.h:233
FEVV::Filters::Geometric_metrics::_pm_init
PointMap _pm_init
Definition: Geometric_metrics.h:231
FEVV::Filters::Geometric_metrics::AABB_tree
CGAL::AABB_tree< AABB_traits > AABB_tree
Definition: Geometric_metrics.h:60
FEVV::Filters::Geometric_metrics::_number_of_points_per_area_unit_LoD_init
double _number_of_points_per_area_unit_LoD_init
Definition: Geometric_metrics.h:235
FEVV::size_of_vertices
boost::graph_traits< MeshT >::vertices_size_type size_of_vertices(const MeshT &g)
Real current number of vertices of the mesh. Generic version.
Definition: Graph_traits_extension.h:29
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31
FEVV::Filters::Geometric_metrics::compute_L2
double compute_L2(const HalfedgeGraph &mesh_to_sample, int cas, bool compute_RMSE_instead_of_max)
Definition: Geometric_metrics.h:132