Point Cloud Library (PCL)  1.11.0
concave_hull.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  * $Id$
37  *
38  */
39 
40 #include <pcl/pcl_config.h>
41 #ifdef HAVE_QHULL
42 
43 #ifndef PCL_SURFACE_IMPL_CONCAVE_HULL_H_
44 #define PCL_SURFACE_IMPL_CONCAVE_HULL_H_
45 
46 #include <map>
47 #include <pcl/surface/concave_hull.h>
48 #include <pcl/common/common.h>
49 #include <pcl/common/eigen.h>
50 #include <pcl/common/centroid.h>
51 #include <pcl/common/transforms.h>
52 #include <pcl/common/io.h>
53 #include <cstdio>
54 #include <cstdlib>
55 #include <pcl/surface/qhull.h>
56 
57 //////////////////////////////////////////////////////////////////////////
58 template <typename PointInT> void
60 {
61  output.header = input_->header;
62  if (alpha_ <= 0)
63  {
64  PCL_ERROR ("[pcl::%s::reconstruct] Alpha parameter must be set to a positive number!\n", getClassName ().c_str ());
65  output.points.clear ();
66  return;
67  }
68 
69  if (!initCompute ())
70  {
71  output.points.clear ();
72  return;
73  }
74 
75  // Perform the actual surface reconstruction
76  std::vector<pcl::Vertices> polygons;
77  performReconstruction (output, polygons);
78 
79  output.width = static_cast<std::uint32_t> (output.points.size ());
80  output.height = 1;
81  output.is_dense = true;
82 
83  deinitCompute ();
84 }
85 
86 //////////////////////////////////////////////////////////////////////////
87 template <typename PointInT> void
88 pcl::ConcaveHull<PointInT>::reconstruct (PointCloud &output, std::vector<pcl::Vertices> &polygons)
89 {
90  output.header = input_->header;
91  if (alpha_ <= 0)
92  {
93  PCL_ERROR ("[pcl::%s::reconstruct] Alpha parameter must be set to a positive number!\n", getClassName ().c_str ());
94  output.points.clear ();
95  return;
96  }
97 
98  if (!initCompute ())
99  {
100  output.points.clear ();
101  return;
102  }
103 
104  // Perform the actual surface reconstruction
105  performReconstruction (output, polygons);
106 
107  output.width = static_cast<std::uint32_t> (output.points.size ());
108  output.height = 1;
109  output.is_dense = true;
110 
111  deinitCompute ();
112 }
113 
114 #ifdef __GNUC__
115 #pragma GCC diagnostic ignored "-Wold-style-cast"
116 #endif
117 //////////////////////////////////////////////////////////////////////////
118 template <typename PointInT> void
119 pcl::ConcaveHull<PointInT>::performReconstruction (PointCloud &alpha_shape, std::vector<pcl::Vertices> &polygons)
120 {
121  Eigen::Vector4d xyz_centroid;
122  compute3DCentroid (*input_, *indices_, xyz_centroid);
123  EIGEN_ALIGN16 Eigen::Matrix3d covariance_matrix = Eigen::Matrix3d::Zero ();
124  computeCovarianceMatrixNormalized (*input_, *indices_, xyz_centroid, covariance_matrix);
125 
126  // Check if the covariance matrix is finite or not.
127  for (int i = 0; i < 3; ++i)
128  for (int j = 0; j < 3; ++j)
129  if (!std::isfinite (covariance_matrix.coeffRef (i, j)))
130  return;
131 
132  EIGEN_ALIGN16 Eigen::Vector3d eigen_values;
133  EIGEN_ALIGN16 Eigen::Matrix3d eigen_vectors;
134  pcl::eigen33 (covariance_matrix, eigen_vectors, eigen_values);
135 
136  Eigen::Affine3d transform1;
137  transform1.setIdentity ();
138 
139  // If no input dimension is specified, determine automatically
140  if (dim_ == 0)
141  {
142  PCL_DEBUG ("[pcl::%s] WARNING: Input dimension not specified. Automatically determining input dimension.\n", getClassName ().c_str ());
143  if (std::abs (eigen_values[0]) < std::numeric_limits<double>::epsilon () || std::abs (eigen_values[0] / eigen_values[2]) < 1.0e-3)
144  dim_ = 2;
145  else
146  dim_ = 3;
147  }
148 
149  if (dim_ == 2)
150  {
151  // we have points laying on a plane, using 2d convex hull
152  // compute transformation bring eigen_vectors.col(i) to z-axis
153 
154  transform1 (2, 0) = eigen_vectors (0, 0);
155  transform1 (2, 1) = eigen_vectors (1, 0);
156  transform1 (2, 2) = eigen_vectors (2, 0);
157 
158  transform1 (1, 0) = eigen_vectors (0, 1);
159  transform1 (1, 1) = eigen_vectors (1, 1);
160  transform1 (1, 2) = eigen_vectors (2, 1);
161  transform1 (0, 0) = eigen_vectors (0, 2);
162  transform1 (0, 1) = eigen_vectors (1, 2);
163  transform1 (0, 2) = eigen_vectors (2, 2);
164  }
165  else
166  {
167  transform1.setIdentity ();
168  }
169 
170  PointCloud cloud_transformed;
171  pcl::demeanPointCloud (*input_, *indices_, xyz_centroid, cloud_transformed);
172  pcl::transformPointCloud (cloud_transformed, cloud_transformed, transform1);
173 
174  // True if qhull should free points in qh_freeqhull() or reallocation
175  boolT ismalloc = True;
176  // option flags for qhull, see qh_opt.htm
177  char flags[] = "qhull d QJ";
178  // output from qh_produce_output(), use NULL to skip qh_produce_output()
179  FILE *outfile = nullptr;
180  // error messages from qhull code
181  FILE *errfile = stderr;
182  // 0 if no error from qhull
183  int exitcode;
184 
185  // Array of coordinates for each point
186  coordT *points = reinterpret_cast<coordT*> (calloc (cloud_transformed.points.size () * dim_, sizeof(coordT)));
187 
188  for (std::size_t i = 0; i < cloud_transformed.points.size (); ++i)
189  {
190  points[i * dim_ + 0] = static_cast<coordT> (cloud_transformed.points[i].x);
191  points[i * dim_ + 1] = static_cast<coordT> (cloud_transformed.points[i].y);
192 
193  if (dim_ > 2)
194  points[i * dim_ + 2] = static_cast<coordT> (cloud_transformed.points[i].z);
195  }
196 
197  // Compute concave hull
198  exitcode = qh_new_qhull (dim_, static_cast<int> (cloud_transformed.points.size ()), points, ismalloc, flags, outfile, errfile);
199 
200  if (exitcode != 0)
201  {
202  PCL_ERROR ("[pcl::%s::performReconstrution] ERROR: qhull was unable to compute a concave hull for the given point cloud (%lu)!\n", getClassName ().c_str (), cloud_transformed.points.size ());
203 
204  //check if it fails because of NaN values...
205  if (!cloud_transformed.is_dense)
206  {
207  bool NaNvalues = false;
208  for (std::size_t i = 0; i < cloud_transformed.size (); ++i)
209  {
210  if (!std::isfinite (cloud_transformed.points[i].x) ||
211  !std::isfinite (cloud_transformed.points[i].y) ||
212  !std::isfinite (cloud_transformed.points[i].z))
213  {
214  NaNvalues = true;
215  break;
216  }
217  }
218 
219  if (NaNvalues)
220  PCL_ERROR ("[pcl::%s::performReconstruction] ERROR: point cloud contains NaN values, consider running pcl::PassThrough filter first to remove NaNs!\n", getClassName ().c_str ());
221  }
222 
223  alpha_shape.points.resize (0);
224  alpha_shape.width = alpha_shape.height = 0;
225  polygons.resize (0);
226 
227  qh_freeqhull (!qh_ALL);
228  int curlong, totlong;
229  qh_memfreeshort (&curlong, &totlong);
230 
231  return;
232  }
233 
234  qh_setvoronoi_all ();
235 
236  int num_vertices = qh num_vertices;
237  alpha_shape.points.resize (num_vertices);
238 
239  vertexT *vertex;
240  // Max vertex id
241  int max_vertex_id = 0;
242  FORALLvertices
243  {
244  if (vertex->id + 1 > unsigned (max_vertex_id))
245  max_vertex_id = vertex->id + 1;
246  }
247 
248  facetT *facet; // set by FORALLfacets
249 
250  ++max_vertex_id;
251  std::vector<int> qhid_to_pcidx (max_vertex_id);
252 
253  int num_facets = qh num_facets;
254 
255  if (dim_ == 3)
256  {
257  setT *triangles_set = qh_settemp (4 * num_facets);
258  if (voronoi_centers_)
259  voronoi_centers_->points.resize (num_facets);
260 
261  int non_upper = 0;
262  FORALLfacets
263  {
264  // Facets are tetrahedrons (3d)
265  if (!facet->upperdelaunay)
266  {
267  vertexT *anyVertex = static_cast<vertexT*> (facet->vertices->e[0].p);
268  double *center = facet->center;
269  double r = qh_pointdist (anyVertex->point,center,dim_);
270 
271  if (voronoi_centers_)
272  {
273  voronoi_centers_->points[non_upper].x = static_cast<float> (facet->center[0]);
274  voronoi_centers_->points[non_upper].y = static_cast<float> (facet->center[1]);
275  voronoi_centers_->points[non_upper].z = static_cast<float> (facet->center[2]);
276  }
277 
278  non_upper++;
279 
280  if (r <= alpha_)
281  {
282  // all triangles in tetrahedron are good, add them all to the alpha shape (triangles_set)
283  qh_makeridges (facet);
284  facet->good = true;
285  facet->visitid = qh visit_id;
286  ridgeT *ridge, **ridgep;
287  FOREACHridge_ (facet->ridges)
288  {
289  facetT *neighb = otherfacet_ (ridge, facet);
290  if ((neighb->visitid != qh visit_id))
291  qh_setappend (&triangles_set, ridge);
292  }
293  }
294  else
295  {
296  // consider individual triangles from the tetrahedron...
297  facet->good = false;
298  facet->visitid = qh visit_id;
299  qh_makeridges (facet);
300  ridgeT *ridge, **ridgep;
301  FOREACHridge_ (facet->ridges)
302  {
303  facetT *neighb;
304  neighb = otherfacet_ (ridge, facet);
305  if ((neighb->visitid != qh visit_id))
306  {
307  // check if individual triangle is good and add it to triangles_set
308 
309  PointInT a, b, c;
310  a.x = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[0].p))->point[0]);
311  a.y = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[0].p))->point[1]);
312  a.z = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[0].p))->point[2]);
313  b.x = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[1].p))->point[0]);
314  b.y = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[1].p))->point[1]);
315  b.z = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[1].p))->point[2]);
316  c.x = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[2].p))->point[0]);
317  c.y = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[2].p))->point[1]);
318  c.z = static_cast<float> ((static_cast<vertexT*>(ridge->vertices->e[2].p))->point[2]);
319 
320  double r = pcl::getCircumcircleRadius (a, b, c);
321  if (r <= alpha_)
322  qh_setappend (&triangles_set, ridge);
323  }
324  }
325  }
326  }
327  }
328 
329  if (voronoi_centers_)
330  voronoi_centers_->points.resize (non_upper);
331 
332  // filter, add points to alpha_shape and create polygon structure
333 
334  int num_good_triangles = 0;
335  ridgeT *ridge, **ridgep;
336  FOREACHridge_ (triangles_set)
337  {
338  if (ridge->bottom->upperdelaunay || ridge->top->upperdelaunay || !ridge->top->good || !ridge->bottom->good)
339  num_good_triangles++;
340  }
341 
342  polygons.resize (num_good_triangles);
343 
344  int vertices = 0;
345  std::vector<bool> added_vertices (max_vertex_id, false);
346 
347  int triangles = 0;
348  FOREACHridge_ (triangles_set)
349  {
350  if (ridge->bottom->upperdelaunay || ridge->top->upperdelaunay || !ridge->top->good || !ridge->bottom->good)
351  {
352  polygons[triangles].vertices.resize (3);
353  int vertex_n, vertex_i;
354  FOREACHvertex_i_ ((*ridge).vertices) //3 vertices per ridge!
355  {
356  if (!added_vertices[vertex->id])
357  {
358  alpha_shape.points[vertices].x = static_cast<float> (vertex->point[0]);
359  alpha_shape.points[vertices].y = static_cast<float> (vertex->point[1]);
360  alpha_shape.points[vertices].z = static_cast<float> (vertex->point[2]);
361 
362  qhid_to_pcidx[vertex->id] = vertices; //map the vertex id of qhull to the point cloud index
363  added_vertices[vertex->id] = true;
364  vertices++;
365  }
366 
367  polygons[triangles].vertices[vertex_i] = qhid_to_pcidx[vertex->id];
368 
369  }
370 
371  triangles++;
372  }
373  }
374 
375  alpha_shape.points.resize (vertices);
376  alpha_shape.width = static_cast<std::uint32_t> (alpha_shape.points.size ());
377  alpha_shape.height = 1;
378  }
379  else
380  {
381  // Compute the alpha complex for the set of points
382  // Filters the delaunay triangles
383  setT *edges_set = qh_settemp (3 * num_facets);
384  if (voronoi_centers_)
385  voronoi_centers_->points.resize (num_facets);
386 
387  int dd = 0;
388  FORALLfacets
389  {
390  // Facets are the delaunay triangles (2d)
391  if (!facet->upperdelaunay)
392  {
393  // Check if the distance from any vertex to the facet->center
394  // (center of the voronoi cell) is smaller than alpha
395  vertexT *anyVertex = static_cast<vertexT*>(facet->vertices->e[0].p);
396  double r = (sqrt ((anyVertex->point[0] - facet->center[0]) *
397  (anyVertex->point[0] - facet->center[0]) +
398  (anyVertex->point[1] - facet->center[1]) *
399  (anyVertex->point[1] - facet->center[1])));
400  if (r <= alpha_)
401  {
402  pcl::Vertices facet_vertices; //TODO: is not used!!
403  qh_makeridges (facet);
404  facet->good = true;
405 
406  ridgeT *ridge, **ridgep;
407  FOREACHridge_ (facet->ridges)
408  qh_setappend (&edges_set, ridge);
409 
410  if (voronoi_centers_)
411  {
412  voronoi_centers_->points[dd].x = static_cast<float> (facet->center[0]);
413  voronoi_centers_->points[dd].y = static_cast<float> (facet->center[1]);
414  voronoi_centers_->points[dd].z = 0.0f;
415  }
416 
417  ++dd;
418  }
419  else
420  facet->good = false;
421  }
422  }
423 
424  int vertices = 0;
425  std::vector<bool> added_vertices (max_vertex_id, false);
426  std::map<int, std::vector<int> > edges;
427 
428  ridgeT *ridge, **ridgep;
429  FOREACHridge_ (edges_set)
430  {
431  if (ridge->bottom->upperdelaunay || ridge->top->upperdelaunay || !ridge->top->good || !ridge->bottom->good)
432  {
433  int vertex_n, vertex_i;
434  int vertices_in_ridge=0;
435  std::vector<int> pcd_indices;
436  pcd_indices.resize (2);
437 
438  FOREACHvertex_i_ ((*ridge).vertices) //in 2-dim, 2 vertices per ridge!
439  {
440  if (!added_vertices[vertex->id])
441  {
442  alpha_shape.points[vertices].x = static_cast<float> (vertex->point[0]);
443  alpha_shape.points[vertices].y = static_cast<float> (vertex->point[1]);
444 
445  if (dim_ > 2)
446  alpha_shape.points[vertices].z = static_cast<float> (vertex->point[2]);
447  else
448  alpha_shape.points[vertices].z = 0;
449 
450  qhid_to_pcidx[vertex->id] = vertices; //map the vertex id of qhull to the point cloud index
451  added_vertices[vertex->id] = true;
452  pcd_indices[vertices_in_ridge] = vertices;
453  vertices++;
454  }
455  else
456  {
457  pcd_indices[vertices_in_ridge] = qhid_to_pcidx[vertex->id];
458  }
459 
460  vertices_in_ridge++;
461  }
462 
463  // make edges bidirectional and pointing to alpha_shape pointcloud...
464  edges[pcd_indices[0]].push_back (pcd_indices[1]);
465  edges[pcd_indices[1]].push_back (pcd_indices[0]);
466  }
467  }
468 
469  alpha_shape.points.resize (vertices);
470 
471  PointCloud alpha_shape_sorted;
472  alpha_shape_sorted.points.resize (vertices);
473 
474  // iterate over edges until they are empty!
475  std::map<int, std::vector<int> >::iterator curr = edges.begin ();
476  int next = - 1;
477  std::vector<bool> used (vertices, false); // used to decide which direction should we take!
478  std::vector<int> pcd_idx_start_polygons;
479  pcd_idx_start_polygons.push_back (0);
480 
481  // start following edges and removing elements
482  int sorted_idx = 0;
483  while (!edges.empty ())
484  {
485  alpha_shape_sorted.points[sorted_idx] = alpha_shape.points[(*curr).first];
486  // check where we can go from (*curr).first
487  for (const int &i : (*curr).second)
488  {
489  if (!used[i])
490  {
491  // we can go there
492  next = i;
493  break;
494  }
495  }
496 
497  used[(*curr).first] = true;
498  edges.erase (curr); // remove edges starting from curr
499 
500  sorted_idx++;
501 
502  if (edges.empty ())
503  break;
504 
505  // reassign current
506  curr = edges.find (next); // if next is not found, then we have unconnected polygons.
507  if (curr == edges.end ())
508  {
509  // set current to any of the remaining in edge!
510  curr = edges.begin ();
511  pcd_idx_start_polygons.push_back (sorted_idx);
512  }
513  }
514 
515  pcd_idx_start_polygons.push_back (sorted_idx);
516 
517  alpha_shape.points = alpha_shape_sorted.points;
518 
519  polygons.reserve (pcd_idx_start_polygons.size () - 1);
520 
521  for (std::size_t poly_id = 0; poly_id < pcd_idx_start_polygons.size () - 1; poly_id++)
522  {
523  // Check if we actually have a polygon, and not some degenerated output from QHull
524  if (pcd_idx_start_polygons[poly_id + 1] - pcd_idx_start_polygons[poly_id] >= 3)
525  {
526  pcl::Vertices vertices;
527  vertices.vertices.resize (pcd_idx_start_polygons[poly_id + 1] - pcd_idx_start_polygons[poly_id]);
528  // populate points in the corresponding polygon
529  for (int j = pcd_idx_start_polygons[poly_id]; j < pcd_idx_start_polygons[poly_id + 1]; ++j)
530  vertices.vertices[j - pcd_idx_start_polygons[poly_id]] = static_cast<std::uint32_t> (j);
531 
532  polygons.push_back (vertices);
533  }
534  }
535 
536  if (voronoi_centers_)
537  voronoi_centers_->points.resize (dd);
538  }
539 
540  qh_freeqhull (!qh_ALL);
541  int curlong, totlong;
542  qh_memfreeshort (&curlong, &totlong);
543 
544  Eigen::Affine3d transInverse = transform1.inverse ();
545  pcl::transformPointCloud (alpha_shape, alpha_shape, transInverse);
546  xyz_centroid[0] = - xyz_centroid[0];
547  xyz_centroid[1] = - xyz_centroid[1];
548  xyz_centroid[2] = - xyz_centroid[2];
549  pcl::demeanPointCloud (alpha_shape, xyz_centroid, alpha_shape);
550 
551  // also transform voronoi_centers_...
552  if (voronoi_centers_)
553  {
554  pcl::transformPointCloud (*voronoi_centers_, *voronoi_centers_, transInverse);
555  pcl::demeanPointCloud (*voronoi_centers_, xyz_centroid, *voronoi_centers_);
556  }
557 
558  if (keep_information_)
559  {
560  // build a tree with the original points
561  pcl::KdTreeFLANN<PointInT> tree (true);
562  tree.setInputCloud (input_, indices_);
563 
564  std::vector<int> neighbor;
565  std::vector<float> distances;
566  neighbor.resize (1);
567  distances.resize (1);
568 
569  // for each point in the concave hull, search for the nearest neighbor in the original point cloud
570  hull_indices_.header = input_->header;
571  hull_indices_.indices.clear ();
572  hull_indices_.indices.reserve (alpha_shape.points.size ());
573 
574  for (std::size_t i = 0; i < alpha_shape.points.size (); i++)
575  {
576  tree.nearestKSearch (alpha_shape.points[i], 1, neighbor, distances);
577  hull_indices_.indices.push_back (neighbor[0]);
578  }
579 
580  // replace point with the closest neighbor in the original point cloud
581  pcl::copyPointCloud (*input_, hull_indices_.indices, alpha_shape);
582  }
583 }
584 #ifdef __GNUC__
585 #pragma GCC diagnostic warning "-Wold-style-cast"
586 #endif
587 
588 //////////////////////////////////////////////////////////////////////////////////////////
589 template <typename PointInT> void
591 {
592  // Perform reconstruction
593  pcl::PointCloud<PointInT> hull_points;
594  performReconstruction (hull_points, output.polygons);
595 
596  // Convert the PointCloud into a PCLPointCloud2
597  pcl::toPCLPointCloud2 (hull_points, output.cloud);
598 }
599 
600 //////////////////////////////////////////////////////////////////////////////////////////
601 template <typename PointInT> void
602 pcl::ConcaveHull<PointInT>::performReconstruction (std::vector<pcl::Vertices> &polygons)
603 {
604  pcl::PointCloud<PointInT> hull_points;
605  performReconstruction (hull_points, polygons);
606 }
607 
608 //////////////////////////////////////////////////////////////////////////////////////////
609 template <typename PointInT> void
611 {
612  hull_point_indices = hull_indices_;
613 }
614 
615 #define PCL_INSTANTIATE_ConcaveHull(T) template class PCL_EXPORTS pcl::ConcaveHull<T>;
616 
617 #endif // PCL_SURFACE_IMPL_CONCAVE_HULL_H_
618 #endif
pcl::PolygonMesh::cloud
::pcl::PCLPointCloud2 cloud
Definition: PolygonMesh.h:22
pcl::uint32_t
std::uint32_t uint32_t
Definition: types.h:58
pcl::PointCloud::height
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415
common.h
pcl::PointCloud::points
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
pcl::ConcaveHull::reconstruct
void reconstruct(PointCloud &points, std::vector< pcl::Vertices > &polygons)
Compute a concave hull for all points given.
Definition: concave_hull.hpp:88
pcl::Vertices::vertices
std::vector< std::uint32_t > vertices
Definition: Vertices.h:20
pcl::computeCovarianceMatrixNormalized
unsigned int computeCovarianceMatrixNormalized(const pcl::PointCloud< PointT > &cloud, const Eigen::Matrix< Scalar, 4, 1 > &centroid, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix)
Compute normalized the 3x3 covariance matrix of a given set of points.
Definition: centroid.hpp:251
pcl::getCircumcircleRadius
double getCircumcircleRadius(const PointT &pa, const PointT &pb, const PointT &pc)
Compute the radius of a circumscribed circle for a triangle formed of three points pa,...
Definition: common.hpp:390
pcl::demeanPointCloud
void demeanPointCloud(ConstCloudIterator< PointT > &cloud_iterator, const Eigen::Matrix< Scalar, 4, 1 > &centroid, pcl::PointCloud< PointT > &cloud_out, int npts=0)
Subtract a centroid from a point cloud and return the de-meaned representation.
Definition: centroid.hpp:631
pcl::PointCloud< PointInT >
pcl::eigen33
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
pcl::ConcaveHull::getHullPointIndices
void getHullPointIndices(pcl::PointIndices &hull_point_indices) const
Retrieve the indices of the input point cloud that for the convex hull.
Definition: concave_hull.hpp:610
pcl::copyPointCloud
void copyPointCloud(const pcl::PointCloud< PointInT > &cloud_in, pcl::PointCloud< PointOutT > &cloud_out)
Copy all the fields from a given point cloud into a new point cloud.
Definition: io.hpp:121
pcl::transformPointCloud
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Transform< Scalar, 3, Eigen::Affine > &transform, bool copy_all_fields)
Apply an affine transform defined by an Eigen Transform.
Definition: transforms.hpp:221
pcl::PointCloud::width
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
pcl::KdTreeFLANN
KdTreeFLANN is a generic type of 3D spatial locator using kD-tree structures.
Definition: kdtree_flann.h:67
pcl::PolygonMesh
Definition: PolygonMesh.h:15
pcl::PointCloud::is_dense
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
pcl::PointIndices
Definition: PointIndices.h:13
pcl::PointCloud::header
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:407
pcl::PointCloud::size
std::size_t size() const
Definition: point_cloud.h:448
pcl::Vertices
Describes a set of vertices in a polygon mesh, by basically storing an array of indices.
Definition: Vertices.h:15
pcl::PolygonMesh::polygons
std::vector< ::pcl::Vertices > polygons
Definition: PolygonMesh.h:24
pcl::compute3DCentroid
unsigned int compute3DCentroid(ConstCloudIterator< PointT > &cloud_iterator, Eigen::Matrix< Scalar, 4, 1 > &centroid)
Compute the 3D (X-Y-Z) centroid of a set of points and return it as a 3D vector.
Definition: centroid.hpp:56
pcl::toPCLPointCloud2
void toPCLPointCloud2(const pcl::PointCloud< PointT > &cloud, pcl::PCLPointCloud2 &msg)
Convert a pcl::PointCloud<T> object to a PCLPointCloud2 binary data blob.
Definition: conversions.h:241
pcl::ConcaveHull::performReconstruction
void performReconstruction(PointCloud &points, std::vector< pcl::Vertices > &polygons)
The actual reconstruction method.
Definition: concave_hull.hpp:119
pcl::KdTreeFLANN::setInputCloud
void setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices=IndicesConstPtr()) override
Provide a pointer to the input dataset.
Definition: kdtree_flann.hpp:94
centroid.h
pcl::KdTreeFLANN::nearestKSearch
int nearestKSearch(const PointT &point, int k, std::vector< int > &k_indices, std::vector< float > &k_sqr_distances) const override
Search for k-nearest neighbors for the given query point.
Definition: kdtree_flann.hpp:134