MEPP2 Project
point_cloud_curvature.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 
16 
17 #include <cmath> // for std::pow, std::sqrt, std::abs
18 #include <Eigen/Dense>
19 
20 
21 namespace FEVV {
22 namespace Filters {
23 
32 template< typename PointCloud,
33  typename VertexCurvatureMap >
34 void
35 compute_mean_stdev_curvature(const PointCloud &pc,
36  const VertexCurvatureMap &v_curvm,
37  double &mean,
38  double &stdev)
39 {
40  // init
41  double sum_x = 0.0;
42  double sum_x2 = 0.0;
43  size_t vertices_nbr = 0;
44 
45  // compute sum_x and sum_x2 in a single pass
46  auto iterator_pair = vertices(pc);
47  auto vi = iterator_pair.first;
48  auto vi_end = iterator_pair.second;
49  for(; vi != vi_end; ++vi)
50  {
51  auto curv = get(v_curvm, *vi);
52  sum_x += curv;
53  sum_x2 += curv*curv;
54  vertices_nbr++;
55  }
56 
57  // compute mean
58  mean = sum_x / vertices_nbr;
59 
60  // compute stdev
61  stdev = std::sqrt((sum_x2 / vertices_nbr) - mean*mean);
62 }
63 
64 
72 template< typename PointCloud,
73  typename VertexCurvatureMap,
74  typename VertexColorMap >
75 void
76 curvature_to_color(const PointCloud &pc,
77  const VertexCurvatureMap &v_curvm,
78  VertexColorMap &v_cm)
79 {
80  // compute absolute value of curvature
81  auto v_curvm_abs = FEVV::make_vertex_property_map< PointCloud, double >(pc);
82  auto iterator_pair = vertices(pc);
83  auto vi = iterator_pair.first;
84  auto vi_end = iterator_pair.second;
85  for(; vi != vi_end; ++vi)
86  {
87  auto curv = get(v_curvm, *vi);
88  put(v_curvm_abs, *vi, std::abs(curv));
89  }
90 
91  // compute mean and stdev of absolute curvature
92  double curv_mean, curv_stdev;
93  compute_mean_stdev_curvature(pc, v_curvm_abs, curv_mean, curv_stdev);
94 
95  // compute a restricted curvature range to eliminate outliers
96  double curv_range_min = 0;
97  double curv_range_max = curv_mean + 2*curv_stdev;
98 
99  // populate color map
101  pc, v_curvm_abs, v_cm, curv_range_min, curv_range_max);
102 }
103 
104 
118 template< typename Point,
119  typename PointMap,
120  typename NNIdsVector,
121  typename GeometryTraits >
122 double
123 curvature_at_point(const Point &origin,
124  const PointMap &pm,
125  const NNIdsVector &neighbors_ids,
126  const GeometryTraits &gt)
127 {
128  Eigen::Matrix3d M;
129  M.setZero();
130  Eigen::Vector3d mu;
131  mu.setZero();
132  size_t nneighbors = neighbors_ids.size();
133 
134  for (size_t i = 0; i < nneighbors; ++i)
135  {
136  Point p = get(pm, neighbors_ids[i]);
137  Eigen::Vector3d neighbor(gt.get_x(p), gt.get_y(p), gt.get_z(p));
138  mu = mu + neighbor;
139  M = M + neighbor*neighbor.transpose();
140  }
141 
142  mu = mu / ((double)nneighbors);
143  M = 1. / ((double)nneighbors)*M - mu*mu.transpose();
144 
145  //get local frame
146  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(M);
147 
148  Eigen::Vector3d t1 = eig.eigenvectors().col(2);
149  Eigen::Vector3d t2 = eig.eigenvectors().col(1);
150  Eigen::Vector3d n = eig.eigenvectors().col(0);
151 
152  Eigen::MatrixXd A(nneighbors, 6);
153  Eigen::VectorXd B(nneighbors);
154 
155  //build linear system
156  for (size_t i = 0; i < nneighbors; ++i)
157  {
158  Point p = get(pm, neighbors_ids[i]);
159  double xglob = gt.get_x(p) - gt.get_x(origin);
160  double yglob = gt.get_y(p) - gt.get_y(origin);
161  double zglob = gt.get_z(p) - gt.get_z(origin);
162  Eigen::Vector3d v(xglob, yglob, zglob);
163  double x = v.transpose()*t1;
164  double y = v.transpose()*t2;
165  double z = v.transpose()*n;
166 
167  A(i, 0) = x*x;
168  A(i, 1) = y*y;
169  A(i, 2) = x*y;
170  A(i, 3) = x;
171  A(i, 4) = y;
172  A(i, 5) = 1;
173 
174  B(i) = z;
175  }
176 
177  Eigen::VectorXd coeffs = A.colPivHouseholderQr().solve(B);
178 
179  //corresponding curvature
180  double fxx = 2 * coeffs(0);
181  double fyy = 2 * coeffs(1);
182  double fxy = coeffs(2);
183  double fx = coeffs(3);
184  double fy = coeffs(4);
185 
186  double H = 0.5*((1 + fx*fx)*fyy + (1 + fy*fy)*fxx - 2 * fxy*fx*fy) / pow(1 + fx*fx + fy*fy, 1.5);
187 
188  return H;
189 }
190 
191 
206 template< typename PointCloud,
207  typename PointMap,
208  typename VertexCurvatureMap,
209  typename VertexColorMap,
210  typename GeometryTraits = FEVV::Geometry_traits< PointCloud > >
211 void
212 point_cloud_curvature(const PointCloud &pc,
213  const PointMap &pm,
214  unsigned int k,
215  double radius,
216  VertexCurvatureMap &v_curvm,
217  VertexColorMap &v_cm,
218  const GeometryTraits &gt)
219 {
220  // create k-d tree
221  auto kd_tree_ptr = create_kd_tree(pc);
222 
223  // compute curvature at each vertex
224  auto iterator_pair = vertices(pc);
225  auto vi = iterator_pair.first;
226  auto vi_end = iterator_pair.second;
227  for(; vi != vi_end; ++vi)
228  {
229  // retrieve current point
230  auto point = get(pm, *vi);
231 
232  // do NN-search around current point
233  decltype(kNN_search(*kd_tree_ptr, k, point, pc)) result;
234  if(k != 0)
235  {
236  //DBG std::cout << "kNN_search, k=" << k << std::endl;
237  result = kNN_search(*kd_tree_ptr, k, point, pc);
238  }
239  else
240  {
241  //DBG std::cout << "radius_search, radius=" << radius << std::endl;
242  result = radius_search(*kd_tree_ptr, radius, point, pc);
243  }
244  auto neighbors_ids = result.first;
245 
246  // compute curvature
247  double curv = curvature_at_point(point, pm, neighbors_ids, gt);
248 
249  // store curvature into property map
250  put(v_curvm, *vi, curv);
251  }
252 
253  // convert curvature to color for display
254  curvature_to_color(pc, v_curvm, v_cm);
255 }
256 
257 
270 template< typename PointCloud,
271  typename PointMap,
272  typename VertexCurvatureMap,
273  typename VertexColorMap,
274  typename GeometryTraits = FEVV::Geometry_traits< PointCloud > >
275 void
276 point_cloud_curvature(const PointCloud &pc,
277  const PointMap &pm,
278  unsigned int k,
279  double radius,
280  VertexCurvatureMap &v_curvm,
281  VertexColorMap &v_cm)
282 {
283  GeometryTraits gt(pc);
284  point_cloud_curvature(pc, pm, k, radius, v_curvm, v_cm, gt);
285 }
286 
287 } // namespace Filters
288 } // namespace FEVV
CGAL::kNN_search
std::pair< std::vector< CGALPointSetNNSearch::vertex_descriptor >, std::vector< double > > kNN_search(const CGALPointSetNNSearch::KdTree &kd_tree, unsigned int k, const FEVV::CGALPointSetPoint &query, const FEVV::CGALPointSet &pc)
Search the k nearest neighbors of a geometric point.
Definition: Graph_properties_cgal_point_set.h:113
FEVV::DataStructures::AIF::vertices
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator > vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the iterator range of the vertices of the mesh.
Definition: Graph_traits_aif.h:172
FEVV::Filters::compute_mean_stdev_curvature
void compute_mean_stdev_curvature(const PointCloud &pc, const VertexCurvatureMap &v_curvm, double &mean, double &stdev)
Compute mean and stdev of curvature.
Definition: point_cloud_curvature.hpp:35
CGAL::create_kd_tree
CGALPointSetNNSearch::KdTreePtr create_kd_tree(const FEVV::CGALPointSet &pc)
Initialize a k-d tree with all cloud points.
Definition: Graph_properties_cgal_point_set.h:83
FEVV::Filters::curvature_to_color
void curvature_to_color(const PointCloud &pc, const VertexCurvatureMap &v_curvm, VertexColorMap &v_cm)
Convert a curvature map to a color map.
Definition: point_cloud_curvature.hpp:76
FEVV::Math::Vector::Stats::mean
static ElementType mean(const ElementType v[DIM])
Definition: MatrixOperations.hpp:133
color_mesh.h
FEVV::Geometry_traits
Refer to Geometry_traits_documentation_dummy for further documentation on provided types and algorith...
Definition: Geometry_traits.h:162
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
FEVV::Filters::point_cloud_curvature
void point_cloud_curvature(const PointCloud &pc, const PointMap &pm, unsigned int k, double radius, VertexCurvatureMap &v_curvm, VertexColorMap &v_cm, const GeometryTraits &gt)
Compute the curvature for each point of the point cloud using the nearest neighbors.
Definition: point_cloud_curvature.hpp:212
FEVV::Filters::color_vertices_from_map
void color_vertices_from_map(const HalfedgeGraph &g, const PropertyMap &prop_map, ColorMap &color_pmap, const MapType min_metric, const MapType max_metric, const ColorMeshLUT &colors=make_LUT())
Fill the color map for the vertices of a mesh using a numerical property map.
Definition: color_mesh.h:211
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::Filters::curvature_at_point
double curvature_at_point(const Point &origin, const PointMap &pm, const NNIdsVector &neighbors_ids, const GeometryTraits &gt)
Compute the curvature at origin point using a set of neighbors given by a list of indices.
Definition: point_cloud_curvature.hpp:123
Geometry_traits.h
FEVV::put
void put(FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key, const FEVV::PCLPointCloudPointMap::value_type &value)
Specialization of put(point_map, key, value) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:126
CGAL::radius_search
std::pair< std::vector< CGALPointSetNNSearch::vertex_descriptor >, std::vector< double > > radius_search(const CGALPointSetNNSearch::KdTree &kd_tree, double radius, const FEVV::CGALPointSetPoint &query, const FEVV::CGALPointSet &pc)
Search for the nearest neighbors of a geometric point in the given radius.
Definition: Graph_properties_cgal_point_set.h:157
properties.h
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31