Point Cloud Library (PCL)  1.14.1-dev
sac_model_plane.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $Id$
38  *
39  */
40 
41 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_PLANE_H_
42 #define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_PLANE_H_
43 
44 #include <pcl/sample_consensus/sac_model_plane.h>
45 #include <pcl/common/centroid.h>
46 #include <pcl/common/eigen.h>
47 #include <pcl/common/concatenate.h>
48 
49 //////////////////////////////////////////////////////////////////////////
50 template <typename PointT> bool
52 {
53  if (samples.size () != sample_size_)
54  {
55  PCL_ERROR ("[pcl::SampleConsensusModelPlane::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
56  return (false);
57  }
58 
59  // Check if the sample points are collinear
60  // Similar checks are implemented as precaution in computeModelCoefficients,
61  // so if you find the need to fix something in here, look there, too.
62  pcl::Vector3fMapConst p0 = (*input_)[samples[0]].getVector3fMap ();
63  pcl::Vector3fMapConst p1 = (*input_)[samples[1]].getVector3fMap ();
64  pcl::Vector3fMapConst p2 = (*input_)[samples[2]].getVector3fMap ();
65 
66  // Check if the norm of the cross-product would be non-zero, otherwise
67  // normalization will fail. One could also interpret this as kind of check
68  // if the triangle spanned by those three points would have an area greater
69  // than zero.
70  if ((p1 - p0).cross(p2 - p0).stableNorm() < Eigen::NumTraits<float>::dummy_precision ())
71  {
72  PCL_ERROR ("[pcl::SampleConsensusModelPlane::isSampleGood] Sample points too similar or collinear!\n");
73  return (false);
74  }
75 
76  return (true);
77 }
78 
79 //////////////////////////////////////////////////////////////////////////
80 template <typename PointT> bool
82  const Indices &samples, Eigen::VectorXf &model_coefficients) const
83 {
84  // The checks are redundant with isSampleGood above, but since most of the
85  // computed values are also used to compute the model coefficients, this might
86  // be a situation where this duplication is acceptable.
87  if (samples.size () != sample_size_)
88  {
89  PCL_ERROR ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
90  return (false);
91  }
92 
93  pcl::Vector3fMapConst p0 = (*input_)[samples[0]].getVector3fMap ();
94  pcl::Vector3fMapConst p1 = (*input_)[samples[1]].getVector3fMap ();
95  pcl::Vector3fMapConst p2 = (*input_)[samples[2]].getVector3fMap ();
96 
97  const Eigen::Vector3f cross = (p1 - p0).cross(p2 - p0);
98  const float crossNorm = cross.stableNorm();
99 
100  // Checking for collinearity here
101  if (crossNorm < Eigen::NumTraits<float>::dummy_precision ())
102  {
103  PCL_ERROR ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Chosen samples are collinear!\n");
104  return (false);
105  }
106 
107  // Compute the plane coefficients from the 3 given points in a straightforward manner
108  // calculate the plane normal n = (p2-p1) x (p3-p1) = cross (p2-p1, p3-p1)
109  model_coefficients.resize (model_size_);
110  model_coefficients.template head<3>() = cross / crossNorm;
111 
112  // ... + d = 0
113  model_coefficients[3] = -1.0f * (model_coefficients.template head<3>().dot (p0));
114 
115  PCL_DEBUG ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Model is (%g,%g,%g,%g).\n",
116  model_coefficients[0], model_coefficients[1], model_coefficients[2], model_coefficients[3]);
117  return (true);
118 }
119 
120 //////////////////////////////////////////////////////////////////////////
121 template <typename PointT> void
123  const Eigen::VectorXf &model_coefficients, std::vector<double> &distances) const
124 {
125  // Needs a valid set of model coefficients
126  if (!isModelValid (model_coefficients))
127  {
128  PCL_ERROR ("[pcl::SampleConsensusModelPlane::getDistancesToModel] Given model is invalid!\n");
129  return;
130  }
131 
132  distances.resize (indices_->size ());
133 
134  // Iterate through the 3d points and calculate the distances from them to the plane
135  for (std::size_t i = 0; i < indices_->size (); ++i)
136  {
137  // Calculate the distance from the point to the plane normal as the dot product
138  // D = (P-A).N/|N|
139  /*distances[i] = std::abs (model_coefficients[0] * (*input_)[(*indices_)[i]].x +
140  model_coefficients[1] * (*input_)[(*indices_)[i]].y +
141  model_coefficients[2] * (*input_)[(*indices_)[i]].z +
142  model_coefficients[3]);*/
143  Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
144  (*input_)[(*indices_)[i]].y,
145  (*input_)[(*indices_)[i]].z,
146  1.0f);
147  distances[i] = std::abs (model_coefficients.dot (pt));
148  }
149 }
150 
151 //////////////////////////////////////////////////////////////////////////
152 template <typename PointT> void
154  const Eigen::VectorXf &model_coefficients, const double threshold, Indices &inliers)
155 {
156  // Needs a valid set of model coefficients
157  if (!isModelValid (model_coefficients))
158  {
159  PCL_ERROR ("[pcl::SampleConsensusModelPlane::selectWithinDistance] Given model is invalid!\n");
160  return;
161  }
162 
163  inliers.clear ();
164  error_sqr_dists_.clear ();
165  inliers.reserve (indices_->size ());
166  error_sqr_dists_.reserve (indices_->size ());
167 
168  // Iterate through the 3d points and calculate the distances from them to the plane
169  for (std::size_t i = 0; i < indices_->size (); ++i)
170  {
171  // Calculate the distance from the point to the plane normal as the dot product
172  // D = (P-A).N/|N|
173  Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
174  (*input_)[(*indices_)[i]].y,
175  (*input_)[(*indices_)[i]].z,
176  1.0f);
177 
178  float distance = std::abs (model_coefficients.dot (pt));
179 
180  if (distance < threshold)
181  {
182  // Returns the indices of the points whose distances are smaller than the threshold
183  inliers.push_back ((*indices_)[i]);
184  error_sqr_dists_.push_back (static_cast<double> (distance));
185  }
186  }
187 }
188 
189 //////////////////////////////////////////////////////////////////////////
190 template <typename PointT> std::size_t
192  const Eigen::VectorXf &model_coefficients, const double threshold) const
193 {
194  // Needs a valid set of model coefficients
195  if (!isModelValid (model_coefficients))
196  {
197  PCL_ERROR ("[pcl::SampleConsensusModelPlane::countWithinDistance] Given model is invalid!\n");
198  return (0);
199  }
200 #if defined (__AVX__) && defined (__AVX2__)
201  return countWithinDistanceAVX (model_coefficients, threshold);
202 #elif defined (__SSE__) && defined (__SSE2__) && defined (__SSE4_1__)
203  return countWithinDistanceSSE (model_coefficients, threshold);
204 #else
205  return countWithinDistanceStandard (model_coefficients, threshold);
206 #endif
207 }
208 
209 //////////////////////////////////////////////////////////////////////////
210 template <typename PointT> std::size_t
212  const Eigen::VectorXf &model_coefficients, const double threshold, std::size_t i) const
213 {
214  std::size_t nr_p = 0;
215  // Iterate through the 3d points and calculate the distances from them to the plane
216  for (; i < indices_->size (); ++i)
217  {
218  // Calculate the distance from the point to the plane normal as the dot product
219  // D = (P-A).N/|N|
220  Eigen::Vector4f pt ((*input_)[(*indices_)[i]].x,
221  (*input_)[(*indices_)[i]].y,
222  (*input_)[(*indices_)[i]].z,
223  1.0f);
224  if (std::abs (model_coefficients.dot (pt)) < threshold)
225  {
226  nr_p++;
227  }
228  }
229  return (nr_p);
230 }
231 
232 //////////////////////////////////////////////////////////////////////////
233 #if defined (__SSE__) && defined (__SSE2__) && defined (__SSE4_1__)
234 template <typename PointT> std::size_t
236  const Eigen::VectorXf &model_coefficients, const double threshold, std::size_t i) const
237 {
238  std::size_t nr_p = 0;
239  const __m128 a_vec = _mm_set1_ps (model_coefficients[0]);
240  const __m128 b_vec = _mm_set1_ps (model_coefficients[1]);
241  const __m128 c_vec = _mm_set1_ps (model_coefficients[2]);
242  const __m128 d_vec = _mm_set1_ps (model_coefficients[3]);
243  const __m128 threshold_vec = _mm_set1_ps (threshold);
244  const __m128 abs_help = _mm_set1_ps (-0.0F); // -0.0F (negative zero) means that all bits are 0, only the sign bit is 1
245  __m128i res = _mm_set1_epi32(0); // This corresponds to nr_p: 4 32bit integers that, summed together, hold the number of inliers
246  for (; (i + 4) <= indices_->size (); i += 4)
247  {
248  const __m128 mask = _mm_cmplt_ps (dist4 (i, a_vec, b_vec, c_vec, d_vec, abs_help), threshold_vec); // The mask contains 1 bits if the corresponding points are inliers, else 0 bits
249  res = _mm_add_epi32 (res, _mm_and_si128 (_mm_set1_epi32 (1), _mm_castps_si128 (mask))); // The latter part creates a vector with ones (as 32bit integers) where the points are inliers
250  //const int res = _mm_movemask_ps (mask);
251  //if (res & 1) nr_p++;
252  //if (res & 2) nr_p++;
253  //if (res & 4) nr_p++;
254  //if (res & 8) nr_p++;
255  }
256  nr_p += _mm_extract_epi32 (res, 0);
257  nr_p += _mm_extract_epi32 (res, 1);
258  nr_p += _mm_extract_epi32 (res, 2);
259  nr_p += _mm_extract_epi32 (res, 3);
260 
261  // Process the remaining points (at most 3)
262  nr_p += countWithinDistanceStandard(model_coefficients, threshold, i);
263  return (nr_p);
264 }
265 #endif
266 
267 //////////////////////////////////////////////////////////////////////////
268 #if defined (__AVX__) && defined (__AVX2__)
269 template <typename PointT> std::size_t
271  const Eigen::VectorXf &model_coefficients, const double threshold, std::size_t i) const
272 {
273  std::size_t nr_p = 0;
274  const __m256 a_vec = _mm256_set1_ps (model_coefficients[0]);
275  const __m256 b_vec = _mm256_set1_ps (model_coefficients[1]);
276  const __m256 c_vec = _mm256_set1_ps (model_coefficients[2]);
277  const __m256 d_vec = _mm256_set1_ps (model_coefficients[3]);
278  const __m256 threshold_vec = _mm256_set1_ps (threshold);
279  const __m256 abs_help = _mm256_set1_ps (-0.0F); // -0.0F (negative zero) means that all bits are 0, only the sign bit is 1
280  __m256i res = _mm256_set1_epi32(0); // This corresponds to nr_p: 8 32bit integers that, summed together, hold the number of inliers
281  for (; (i + 8) <= indices_->size (); i += 8)
282  {
283  const __m256 mask = _mm256_cmp_ps (dist8 (i, a_vec, b_vec, c_vec, d_vec, abs_help), threshold_vec, _CMP_LT_OQ); // The mask contains 1 bits if the corresponding points are inliers, else 0 bits
284  res = _mm256_add_epi32 (res, _mm256_and_si256 (_mm256_set1_epi32 (1), _mm256_castps_si256 (mask))); // The latter part creates a vector with ones (as 32bit integers) where the points are inliers
285  //const int res = _mm256_movemask_ps (mask);
286  //if (res & 1) nr_p++;
287  //if (res & 2) nr_p++;
288  //if (res & 4) nr_p++;
289  //if (res & 8) nr_p++;
290  //if (res & 16) nr_p++;
291  //if (res & 32) nr_p++;
292  //if (res & 64) nr_p++;
293  //if (res & 128) nr_p++;
294  }
295  nr_p += _mm256_extract_epi32 (res, 0);
296  nr_p += _mm256_extract_epi32 (res, 1);
297  nr_p += _mm256_extract_epi32 (res, 2);
298  nr_p += _mm256_extract_epi32 (res, 3);
299  nr_p += _mm256_extract_epi32 (res, 4);
300  nr_p += _mm256_extract_epi32 (res, 5);
301  nr_p += _mm256_extract_epi32 (res, 6);
302  nr_p += _mm256_extract_epi32 (res, 7);
303 
304  // Process the remaining points (at most 7)
305  nr_p += countWithinDistanceStandard(model_coefficients, threshold, i);
306  return (nr_p);
307 }
308 #endif
309 
310 //////////////////////////////////////////////////////////////////////////
311 template <typename PointT> void
313  const Indices &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) const
314 {
315  // Needs a valid set of model coefficients
316  if (!isModelValid (model_coefficients))
317  {
318  PCL_ERROR ("[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] Given model is invalid!\n");
319  optimized_coefficients = model_coefficients;
320  return;
321  }
322 
323  // Need more than the minimum sample size to make a difference
324  if (inliers.size () <= sample_size_)
325  {
326  PCL_ERROR ("[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] Not enough inliers found to optimize model coefficients (%lu)! Returning the same coefficients.\n", inliers.size ());
327  optimized_coefficients = model_coefficients;
328  return;
329  }
330 
331  Eigen::Vector4f plane_parameters;
332 
333  // Use Least-Squares to fit the plane through all the given sample points and find out its coefficients
334  EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
335  Eigen::Vector4f xyz_centroid;
336 
337  if (0 == computeMeanAndCovarianceMatrix (*input_, inliers, covariance_matrix, xyz_centroid))
338  {
339  PCL_ERROR ("[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] computeMeanAndCovarianceMatrix failed (returned 0) because there are no valid inliers.\n");
340  optimized_coefficients = model_coefficients;
341  return;
342  }
343 
344  // Compute the model coefficients
345  EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
346  EIGEN_ALIGN16 Eigen::Vector3f eigen_vector;
347  pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
348 
349  // Hessian form (D = nc . p_plane (centroid here) + p)
350  optimized_coefficients.resize (model_size_);
351  optimized_coefficients[0] = eigen_vector [0];
352  optimized_coefficients[1] = eigen_vector [1];
353  optimized_coefficients[2] = eigen_vector [2];
354  optimized_coefficients[3] = 0.0f;
355  optimized_coefficients[3] = -1.0f * optimized_coefficients.dot (xyz_centroid);
356 
357  // Make sure it results in a valid model
358  if (!isModelValid (optimized_coefficients))
359  {
360  optimized_coefficients = model_coefficients;
361  }
362 }
363 
364 //////////////////////////////////////////////////////////////////////////
365 template <typename PointT> void
367  const Indices &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields) const
368 {
369  // Needs a valid set of model coefficients
370  if (!isModelValid (model_coefficients))
371  {
372  PCL_ERROR ("[pcl::SampleConsensusModelPlane::projectPoints] Given model is invalid!\n");
373  return;
374  }
375 
376  projected_points.header = input_->header;
377  projected_points.is_dense = input_->is_dense;
378 
379  Eigen::Vector4f mc (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
380 
381  // normalize the vector perpendicular to the plane...
382  mc.normalize ();
383  // ... and store the resulting normal as a local copy of the model coefficients
384  Eigen::Vector4f tmp_mc = model_coefficients;
385  tmp_mc[0] = mc[0];
386  tmp_mc[1] = mc[1];
387  tmp_mc[2] = mc[2];
388 
389  // Copy all the data fields from the input cloud to the projected one?
390  if (copy_data_fields)
391  {
392  // Allocate enough space and copy the basics
393  projected_points.resize (input_->size ());
394  projected_points.width = input_->width;
395  projected_points.height = input_->height;
396 
397  using FieldList = typename pcl::traits::fieldList<PointT>::type;
398  // Iterate over each point
399  for (std::size_t i = 0; i < input_->size (); ++i)
400  // Iterate over each dimension
401  pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> ((*input_)[i], projected_points[i]));
402 
403  // Iterate through the 3d points and calculate the distances from them to the plane
404  for (const auto &inlier : inliers)
405  {
406  // Calculate the distance from the point to the plane
407  Eigen::Vector4f p ((*input_)[inlier].x,
408  (*input_)[inlier].y,
409  (*input_)[inlier].z,
410  1);
411  // use normalized coefficients to calculate the scalar projection
412  float distance_to_plane = tmp_mc.dot (p);
413 
414  pcl::Vector4fMap pp = projected_points[inlier].getVector4fMap ();
415  pp.matrix () = p - mc * distance_to_plane; // mc[3] = 0, therefore the 3rd coordinate is safe
416  }
417  }
418  else
419  {
420  // Allocate enough space and copy the basics
421  projected_points.resize (inliers.size ());
422  projected_points.width = inliers.size ();
423  projected_points.height = 1;
424 
425  using FieldList = typename pcl::traits::fieldList<PointT>::type;
426  // Iterate over each point
427  for (std::size_t i = 0; i < inliers.size (); ++i)
428  {
429  // Iterate over each dimension
430  pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> ((*input_)[inliers[i]], projected_points[i]));
431  }
432 
433  // Iterate through the 3d points and calculate the distances from them to the plane
434  for (std::size_t i = 0; i < inliers.size (); ++i)
435  {
436  // Calculate the distance from the point to the plane
437  Eigen::Vector4f p ((*input_)[inliers[i]].x,
438  (*input_)[inliers[i]].y,
439  (*input_)[inliers[i]].z,
440  1.0f);
441  // use normalized coefficients to calculate the scalar projection
442  float distance_to_plane = tmp_mc.dot (p);
443 
444  pcl::Vector4fMap pp = projected_points[i].getVector4fMap ();
445  pp.matrix () = p - mc * distance_to_plane; // mc[3] = 0, therefore the 3rd coordinate is safe
446  }
447  }
448 }
449 
450 //////////////////////////////////////////////////////////////////////////
451 template <typename PointT> bool
453  const std::set<index_t> &indices, const Eigen::VectorXf &model_coefficients, const double threshold) const
454 {
455  // Needs a valid set of model coefficients
456  if (!isModelValid (model_coefficients))
457  {
458  PCL_ERROR ("[pcl::SampleConsensusModelPlane::doSamplesVerifyModel] Given model is invalid!\n");
459  return (false);
460  }
461 
462  for (const auto &index : indices)
463  {
464  Eigen::Vector4f pt ((*input_)[index].x,
465  (*input_)[index].y,
466  (*input_)[index].z,
467  1.0f);
468  if (std::abs (model_coefficients.dot (pt)) > threshold)
469  {
470  return (false);
471  }
472  }
473 
474  return (true);
475 }
476 
477 #define PCL_INSTANTIATE_SampleConsensusModelPlane(T) template class PCL_EXPORTS pcl::SampleConsensusModelPlane<T>;
478 
479 #endif // PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_PLANE_H_
480 
Define methods for centroid estimation and covariance matrix calculus.
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: point_cloud.h:173
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:403
void resize(std::size_t count)
Resizes the container to contain count elements.
Definition: point_cloud.h:462
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:398
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:392
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:400
SampleConsensusModelPlane defines a model for 3D plane segmentation.
void optimizeModelCoefficients(const Indices &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) const override
Recompute the plane coefficients using the given inlier set and return them to the user.
void getDistancesToModel(const Eigen::VectorXf &model_coefficients, std::vector< double > &distances) const override
Compute all distances from the cloud data to a given plane model.
bool doSamplesVerifyModel(const std::set< index_t > &indices, const Eigen::VectorXf &model_coefficients, const double threshold) const override
Verify whether a subset of indices verifies the given plane model coefficients.
void selectWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold, Indices &inliers) override
Select all the points which respect the given model coefficients as inliers.
void projectPoints(const Indices &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields=true) const override
Create a new point cloud with inliers projected onto the plane model.
bool computeModelCoefficients(const Indices &samples, Eigen::VectorXf &model_coefficients) const override
Check whether the given index samples can form a valid plane model, compute the model coefficients fr...
std::size_t countWithinDistanceStandard(const Eigen::VectorXf &model_coefficients, const double threshold, std::size_t i=0) const
This implementation uses no SIMD instructions.
std::size_t countWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold) const override
Count all the points which respect the given model coefficients as inliers.
unsigned int computeMeanAndCovarianceMatrix(const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix, Eigen::Matrix< Scalar, 4, 1 > &centroid)
Compute the normalized 3x3 covariance matrix and the centroid of a given set of points in a single lo...
Definition: centroid.hpp:509
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:295
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
Eigen::Map< Eigen::Vector4f, Eigen::Aligned > Vector4fMap
const Eigen::Map< const Eigen::Vector3f > Vector3fMapConst
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
Helper functor structure for concatenate.
Definition: concatenate.h:50