Point Cloud Library (PCL)  1.11.0
harris_3d.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
39 #define PCL_HARRIS_KEYPOINT_3D_IMPL_H_
40 
41 #include <pcl/keypoints/harris_3d.h>
42 #include <pcl/common/io.h>
43 #include <pcl/filters/passthrough.h>
44 #include <pcl/filters/extract_indices.h>
45 #include <pcl/features/normal_3d.h>
46 #include <pcl/features/integral_image_normal.h>
47 #include <pcl/common/time.h>
48 #include <pcl/common/centroid.h>
49 #ifdef __SSE__
50 #include <xmmintrin.h>
51 #endif
52 
53 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 template <typename PointInT, typename PointOutT, typename NormalT> void
56 {
57  if (normals_ && input_ && (cloud != input_))
58  normals_.reset ();
59  input_ = cloud;
60 }
61 
62 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63 template <typename PointInT, typename PointOutT, typename NormalT> void
65 {
66  method_ = method;
67 }
68 
69 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70 template <typename PointInT, typename PointOutT, typename NormalT> void
72 {
73  threshold_= threshold;
74 }
75 
76 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77 template <typename PointInT, typename PointOutT, typename NormalT> void
79 {
80  search_radius_ = radius;
81 }
82 
83 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 template <typename PointInT, typename PointOutT, typename NormalT> void
86 {
87  refine_ = do_refine;
88 }
89 
90 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 template <typename PointInT, typename PointOutT, typename NormalT> void
93 {
94  nonmax_ = nonmax;
95 }
96 
97 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 template <typename PointInT, typename PointOutT, typename NormalT> void
100 {
101  normals_ = normals;
102 }
103 
104 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 template <typename PointInT, typename PointOutT, typename NormalT> void
106 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::calculateNormalCovar (const std::vector<int>& neighbors, float* coefficients) const
107 {
108  unsigned count = 0;
109  // indices 0 1 2 3 4 5 6 7
110  // coefficients: xx xy xz ?? yx yy yz ??
111 #ifdef __SSE__
112  // accumulator for xx, xy, xz
113  __m128 vec1 = _mm_setzero_ps();
114  // accumulator for yy, yz, zz
115  __m128 vec2 = _mm_setzero_ps();
116 
117  __m128 norm1;
118 
119  __m128 norm2;
120 
121  float zz = 0;
122 
123  for (const int &neighbor : neighbors)
124  {
125  if (std::isfinite (normals_->points[neighbor].normal_x))
126  {
127  // nx, ny, nz, h
128  norm1 = _mm_load_ps (&(normals_->points[neighbor].normal_x));
129 
130  // nx, nx, nx, nx
131  norm2 = _mm_set1_ps (normals_->points[neighbor].normal_x);
132 
133  // nx * nx, nx * ny, nx * nz, nx * h
134  norm2 = _mm_mul_ps (norm1, norm2);
135 
136  // accumulate
137  vec1 = _mm_add_ps (vec1, norm2);
138 
139  // ny, ny, ny, ny
140  norm2 = _mm_set1_ps (normals_->points[neighbor].normal_y);
141 
142  // ny * nx, ny * ny, ny * nz, ny * h
143  norm2 = _mm_mul_ps (norm1, norm2);
144 
145  // accumulate
146  vec2 = _mm_add_ps (vec2, norm2);
147 
148  zz += normals_->points[neighbor].normal_z * normals_->points[neighbor].normal_z;
149  ++count;
150  }
151  }
152  if (count > 0)
153  {
154  norm2 = _mm_set1_ps (float(count));
155  vec1 = _mm_div_ps (vec1, norm2);
156  vec2 = _mm_div_ps (vec2, norm2);
157  _mm_store_ps (coefficients, vec1);
158  _mm_store_ps (coefficients + 4, vec2);
159  coefficients [7] = zz / float(count);
160  }
161  else
162  memset (coefficients, 0, sizeof (float) * 8);
163 #else
164  memset (coefficients, 0, sizeof (float) * 8);
165  for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt)
166  {
167  if (std::isfinite (normals_->points[*iIt].normal_x))
168  {
169  coefficients[0] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_x;
170  coefficients[1] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_y;
171  coefficients[2] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_z;
172 
173  coefficients[5] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_y;
174  coefficients[6] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_z;
175  coefficients[7] += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z;
176 
177  ++count;
178  }
179  }
180  if (count > 0)
181  {
182  float norm = 1.0 / float (count);
183  coefficients[0] *= norm;
184  coefficients[1] *= norm;
185  coefficients[2] *= norm;
186  coefficients[5] *= norm;
187  coefficients[6] *= norm;
188  coefficients[7] *= norm;
189  }
190 #endif
191 }
192 
193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194 template <typename PointInT, typename PointOutT, typename NormalT> bool
196 {
198  {
199  PCL_ERROR ("[pcl::%s::initCompute] init failed!\n", name_.c_str ());
200  return (false);
201  }
202 
203  if (method_ < 1 || method_ > 5)
204  {
205  PCL_ERROR ("[pcl::%s::initCompute] method (%d) must be in [1..5]!\n", name_.c_str (), method_);
206  return (false);
207  }
208 
209  if (!normals_)
210  {
211  PointCloudNPtr normals (new PointCloudN ());
212  normals->reserve (normals->size ());
213  if (!surface_->isOrganized ())
214  {
216  normal_estimation.setInputCloud (surface_);
217  normal_estimation.setRadiusSearch (search_radius_);
218  normal_estimation.compute (*normals);
219  }
220  else
221  {
224  normal_estimation.setInputCloud (surface_);
225  normal_estimation.setNormalSmoothingSize (5.0);
226  normal_estimation.compute (*normals);
227  }
228  normals_ = normals;
229  }
230  if (normals_->size () != surface_->size ())
231  {
232  PCL_ERROR ("[pcl::%s::initCompute] normals given, but the number of normals does not match the number of input points!\n", name_.c_str (), method_);
233  return (false);
234  }
235 
236  return (true);
237 }
238 
239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240 template <typename PointInT, typename PointOutT, typename NormalT> void
242 {
244 
245  response->points.reserve (input_->points.size());
246 
247  switch (method_)
248  {
249  case HARRIS:
250  responseHarris(*response);
251  break;
252  case NOBLE:
253  responseNoble(*response);
254  break;
255  case LOWE:
256  responseLowe(*response);
257  break;
258  case CURVATURE:
259  responseCurvature(*response);
260  break;
261  case TOMASI:
262  responseTomasi(*response);
263  break;
264  }
265 
266  if (!nonmax_)
267  {
268  output = *response;
269  // we do not change the denseness in this case
270  output.is_dense = input_->is_dense;
271  for (std::size_t i = 0; i < response->size (); ++i)
272  keypoints_indices_->indices.push_back (i);
273  }
274  else
275  {
276  output.points.clear ();
277  output.points.reserve (response->points.size());
278 
279 #pragma omp parallel for \
280  default(none) \
281  shared(output, response) \
282  num_threads(threads_)
283  for (int idx = 0; idx < static_cast<int> (response->points.size ()); ++idx)
284  {
285  if (!isFinite (response->points[idx]) ||
286  !std::isfinite (response->points[idx].intensity) ||
287  response->points[idx].intensity < threshold_)
288  continue;
289 
290  std::vector<int> nn_indices;
291  std::vector<float> nn_dists;
292  tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists);
293  bool is_maxima = true;
294  for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
295  {
296  if (response->points[idx].intensity < response->points[*iIt].intensity)
297  {
298  is_maxima = false;
299  break;
300  }
301  }
302  if (is_maxima)
303 #pragma omp critical
304  {
305  output.points.push_back (response->points[idx]);
306  keypoints_indices_->indices.push_back (idx);
307  }
308  }
309 
310  if (refine_)
311  refineCorners (output);
312 
313  output.height = 1;
314  output.width = static_cast<std::uint32_t> (output.points.size());
315  output.is_dense = true;
316  }
317 }
318 
319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
320 template <typename PointInT, typename PointOutT, typename NormalT> void
322 {
323  PCL_ALIGN (16) float covar [8];
324  output.resize (input_->size ());
325 #pragma omp parallel for \
326  default(none) \
327  shared(output) \
328  private(covar) \
329  num_threads(threads_)
330  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
331  {
332  const PointInT& pointIn = input_->points [pIdx];
333  output [pIdx].intensity = 0.0; //std::numeric_limits<float>::quiet_NaN ();
334  if (isFinite (pointIn))
335  {
336  std::vector<int> nn_indices;
337  std::vector<float> nn_dists;
338  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
339  calculateNormalCovar (nn_indices, covar);
340 
341  float trace = covar [0] + covar [5] + covar [7];
342  if (trace != 0)
343  {
344  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
345  - covar [2] * covar [2] * covar [5]
346  - covar [1] * covar [1] * covar [7]
347  - covar [6] * covar [6] * covar [0];
348 
349  output [pIdx].intensity = 0.04f + det - 0.04f * trace * trace;
350  }
351  }
352  output [pIdx].x = pointIn.x;
353  output [pIdx].y = pointIn.y;
354  output [pIdx].z = pointIn.z;
355  }
356  output.height = input_->height;
357  output.width = input_->width;
358 }
359 
360 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
361 template <typename PointInT, typename PointOutT, typename NormalT> void
363 {
364  PCL_ALIGN (16) float covar [8];
365  output.resize (input_->size ());
366 #pragma omp parallel \
367  for default(none) \
368  shared(output) \
369  private(covar) \
370  num_threads(threads_)
371  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
372  {
373  const PointInT& pointIn = input_->points [pIdx];
374  output [pIdx].intensity = 0.0;
375  if (isFinite (pointIn))
376  {
377  std::vector<int> nn_indices;
378  std::vector<float> nn_dists;
379  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
380  calculateNormalCovar (nn_indices, covar);
381  float trace = covar [0] + covar [5] + covar [7];
382  if (trace != 0)
383  {
384  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
385  - covar [2] * covar [2] * covar [5]
386  - covar [1] * covar [1] * covar [7]
387  - covar [6] * covar [6] * covar [0];
388 
389  output [pIdx].intensity = det / trace;
390  }
391  }
392  output [pIdx].x = pointIn.x;
393  output [pIdx].y = pointIn.y;
394  output [pIdx].z = pointIn.z;
395  }
396  output.height = input_->height;
397  output.width = input_->width;
398 }
399 
400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
401 template <typename PointInT, typename PointOutT, typename NormalT> void
403 {
404  PCL_ALIGN (16) float covar [8];
405  output.resize (input_->size ());
406 #pragma omp parallel for \
407  default(none) \
408  shared(output) \
409  private(covar) \
410  num_threads(threads_)
411  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
412  {
413  const PointInT& pointIn = input_->points [pIdx];
414  output [pIdx].intensity = 0.0;
415  if (isFinite (pointIn))
416  {
417  std::vector<int> nn_indices;
418  std::vector<float> nn_dists;
419  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
420  calculateNormalCovar (nn_indices, covar);
421  float trace = covar [0] + covar [5] + covar [7];
422  if (trace != 0)
423  {
424  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
425  - covar [2] * covar [2] * covar [5]
426  - covar [1] * covar [1] * covar [7]
427  - covar [6] * covar [6] * covar [0];
428 
429  output [pIdx].intensity = det / (trace * trace);
430  }
431  }
432  output [pIdx].x = pointIn.x;
433  output [pIdx].y = pointIn.y;
434  output [pIdx].z = pointIn.z;
435  }
436  output.height = input_->height;
437  output.width = input_->width;
438 }
439 
440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
441 template <typename PointInT, typename PointOutT, typename NormalT> void
443 {
444  PointOutT point;
445  for (std::size_t idx = 0; idx < input_->points.size(); ++idx)
446  {
447  point.x = input_->points[idx].x;
448  point.y = input_->points[idx].y;
449  point.z = input_->points[idx].z;
450  point.intensity = normals_->points[idx].curvature;
451  output.points.push_back(point);
452  }
453  // does not change the order
454  output.height = input_->height;
455  output.width = input_->width;
456 }
457 
458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
459 template <typename PointInT, typename PointOutT, typename NormalT> void
461 {
462  PCL_ALIGN (16) float covar [8];
463  Eigen::Matrix3f covariance_matrix;
464  output.resize (input_->size ());
465 #pragma omp parallel for \
466  default(none) \
467  shared(output) \
468  private(covar, covariance_matrix) \
469  num_threads(threads_)
470  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
471  {
472  const PointInT& pointIn = input_->points [pIdx];
473  output [pIdx].intensity = 0.0;
474  if (isFinite (pointIn))
475  {
476  std::vector<int> nn_indices;
477  std::vector<float> nn_dists;
478  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
479  calculateNormalCovar (nn_indices, covar);
480  float trace = covar [0] + covar [5] + covar [7];
481  if (trace != 0)
482  {
483  covariance_matrix.coeffRef (0) = covar [0];
484  covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = covar [1];
485  covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = covar [2];
486  covariance_matrix.coeffRef (4) = covar [5];
487  covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = covar [6];
488  covariance_matrix.coeffRef (8) = covar [7];
489 
490  EIGEN_ALIGN16 Eigen::Vector3f eigen_values;
491  pcl::eigen33(covariance_matrix, eigen_values);
492  output [pIdx].intensity = eigen_values[0];
493  }
494  }
495  output [pIdx].x = pointIn.x;
496  output [pIdx].y = pointIn.y;
497  output [pIdx].z = pointIn.z;
498  }
499  output.height = input_->height;
500  output.width = input_->width;
501 }
502 
503 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
504 template <typename PointInT, typename PointOutT, typename NormalT> void
506 {
507  Eigen::Matrix3f nnT;
508  Eigen::Matrix3f NNT;
509  Eigen::Matrix3f NNTInv;
510  Eigen::Vector3f NNTp;
511  float diff;
512  const unsigned max_iterations = 10;
513 #pragma omp parallel for \
514  default(none) \
515  shared(corners) \
516  private(nnT, NNT, NNTInv, NNTp, diff) \
517  num_threads(threads_)
518  for (int cIdx = 0; cIdx < static_cast<int> (corners.size ()); ++cIdx)
519  {
520  unsigned iterations = 0;
521  do {
522  NNT.setZero();
523  NNTp.setZero();
524  PointInT corner;
525  corner.x = corners[cIdx].x;
526  corner.y = corners[cIdx].y;
527  corner.z = corners[cIdx].z;
528  std::vector<int> nn_indices;
529  std::vector<float> nn_dists;
530  tree_->radiusSearch (corner, search_radius_, nn_indices, nn_dists);
531  for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
532  {
533  if (!std::isfinite (normals_->points[*iIt].normal_x))
534  continue;
535 
536  nnT = normals_->points[*iIt].getNormalVector3fMap () * normals_->points[*iIt].getNormalVector3fMap ().transpose();
537  NNT += nnT;
538  NNTp += nnT * surface_->points[*iIt].getVector3fMap ();
539  }
540  if (invert3x3SymMatrix (NNT, NNTInv) != 0)
541  corners[cIdx].getVector3fMap () = NNTInv * NNTp;
542 
543  diff = (corners[cIdx].getVector3fMap () - corner.getVector3fMap()).squaredNorm ();
544  } while (diff > 1e-6 && ++iterations < max_iterations);
545  }
546 }
547 
548 #define PCL_INSTANTIATE_HarrisKeypoint3D(T,U,N) template class PCL_EXPORTS pcl::HarrisKeypoint3D<T,U,N>;
549 #endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
550 
Define methods for centroid estimation and covariance matrix calculus.
void setRadiusSearch(double radius)
Set the sphere radius that is to be used for determining the nearest neighbors used for the feature e...
Definition: feature.h:201
void compute(PointCloudOut &output)
Base method for feature estimation for all points given in <setInputCloud (), setIndices ()> using th...
Definition: feature.hpp:193
void calculateNormalCovar(const std::vector< int > &neighbors, float *coefficients) const
calculates the upper triangular part of unnormalized covariance matrix over the normals given by the ...
Definition: harris_3d.hpp:106
typename PointCloudN::Ptr PointCloudNPtr
Definition: harris_3d.h:63
void responseTomasi(PointCloudOut &output) const
Definition: harris_3d.hpp:460
void detectKeypoints(PointCloudOut &output) override
Definition: harris_3d.hpp:241
typename PointCloudN::ConstPtr PointCloudNConstPtr
Definition: harris_3d.h:64
void responseNoble(PointCloudOut &output) const
Definition: harris_3d.hpp:362
bool initCompute() override
Definition: harris_3d.hpp:195
void responseHarris(PointCloudOut &output) const
gets the corner response for valid input points
Definition: harris_3d.hpp:321
typename Keypoint< PointInT, PointOutT >::PointCloudOut PointCloudOut
Definition: harris_3d.h:58
void setNormals(const PointCloudNConstPtr &normals)
Set normals if precalculated normals are available.
Definition: harris_3d.hpp:99
void responseCurvature(PointCloudOut &output) const
Definition: harris_3d.hpp:442
void refineCorners(PointCloudOut &corners) const
Definition: harris_3d.hpp:505
void setRadius(float radius)
Set the radius for normal estimation and non maxima supression.
Definition: harris_3d.hpp:78
void setNonMaxSupression(bool=false)
Whether non maxima suppression should be applied or the response for each point should be returned.
Definition: harris_3d.hpp:92
void setInputCloud(const PointCloudInConstPtr &cloud) override
Provide a pointer to the input dataset.
Definition: harris_3d.hpp:55
void setMethod(ResponseMethod type)
Set the method of the response to be calculated.
Definition: harris_3d.hpp:64
void setThreshold(float threshold)
Set the threshold value for detecting corners.
Definition: harris_3d.hpp:71
void responseLowe(PointCloudOut &output) const
Definition: harris_3d.hpp:402
typename PointCloudIn::ConstPtr PointCloudInConstPtr
Definition: harris_3d.h:60
void setRefine(bool do_refine)
Whether the detected key points should be refined or not.
Definition: harris_3d.hpp:85
Surface normal estimation on organized data using integral images.
void setNormalEstimationMethod(NormalEstimationMethod normal_estimation_method)
Set the normal estimation method.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
void setNormalSmoothingSize(float normal_smoothing_size)
Set the normal smoothing size.
Keypoint represents the base class for key points.
Definition: keypoint.h:49
NormalEstimation estimates local surface properties (surface normals and curvatures)at each 3D point.
Definition: normal_3d.h:244
void setInputCloud(const PointCloudConstPtr &cloud) override
Provide a pointer to the input dataset.
Definition: normal_3d.h:332
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Definition: point_cloud.h:418
std::size_t size() const
Definition: point_cloud.h:448
shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:428
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
Define methods for measuring time spent in code blocks.
Matrix::Scalar invert3x3SymMatrix(const Matrix &matrix, Matrix &inverse)
Calculate the inverse of a 3x3 symmetric matrix.
Definition: eigen.hpp:424
void eigen33(const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi d...
Definition: eigen.hpp:296
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:55
std::uint32_t uint32_t
Definition: types.h:58