Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
common.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $Id: common.hpp 4927 2012-03-07 03:35:53Z rusu $
35  *
36  */
37 
38 #ifndef PCL_COMMON_IMPL_H_
39 #define PCL_COMMON_IMPL_H_
40 
41 #include <pcl/point_types.h>
42 
44 inline double
45 pcl::getAngle3D (const Eigen::Vector4f &v1, const Eigen::Vector4f &v2)
46 {
47  // Compute the actual angle
48  double rad = v1.dot (v2) / sqrt (v1.squaredNorm () * v2.squaredNorm ());
49  if (rad < -1.0) rad = -1.0;
50  if (rad > 1.0) rad = 1.0;
51  return (acos (rad));
52 }
53 
55 inline void
56 pcl::getMeanStd (const std::vector<float> &values, double &mean, double &stddev)
57 {
58  double sum = 0, sq_sum = 0;
59 
60  for (size_t i = 0; i < values.size (); ++i)
61  {
62  sum += values[i];
63  sq_sum += values[i] * values[i];
64  }
65  mean = sum / static_cast<double>(values.size ());
66  double variance = (sq_sum - sum * sum / static_cast<double>(values.size ())) / (static_cast<double>(values.size ()) - 1);
67  stddev = sqrt (variance);
68 }
69 
71 template <typename PointT> inline void
73  Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
74  std::vector<int> &indices)
75 {
76  indices.resize (cloud.points.size ());
77  int l = 0;
78 
79  // If the data is dense, we don't need to check for NaN
80  if (cloud.is_dense)
81  {
82  for (size_t i = 0; i < cloud.points.size (); ++i)
83  {
84  // Check if the point is inside bounds
85  if (cloud.points[i].x < min_pt[0] || cloud.points[i].y < min_pt[1] || cloud.points[i].z < min_pt[2])
86  continue;
87  if (cloud.points[i].x > max_pt[0] || cloud.points[i].y > max_pt[1] || cloud.points[i].z > max_pt[2])
88  continue;
89  indices[l++] = i;
90  }
91  }
92  // NaN or Inf values could exist => check for them
93  else
94  {
95  for (size_t i = 0; i < cloud.points.size (); ++i)
96  {
97  // Check if the point is invalid
98  if (!pcl_isfinite (cloud.points[i].x) ||
99  !pcl_isfinite (cloud.points[i].y) ||
100  !pcl_isfinite (cloud.points[i].z))
101  continue;
102  // Check if the point is inside bounds
103  if (cloud.points[i].x < min_pt[0] || cloud.points[i].y < min_pt[1] || cloud.points[i].z < min_pt[2])
104  continue;
105  if (cloud.points[i].x > max_pt[0] || cloud.points[i].y > max_pt[1] || cloud.points[i].z > max_pt[2])
106  continue;
107  indices[l++] = i;
108  }
109  }
110  indices.resize (l);
111 }
112 
114 template<typename PointT> inline void
115 pcl::getMaxDistance (const pcl::PointCloud<PointT> &cloud, const Eigen::Vector4f &pivot_pt, Eigen::Vector4f &max_pt)
116 {
117  float max_dist = -FLT_MAX;
118  float max_idx = -1;
119  float dist;
120 
121  // If the data is dense, we don't need to check for NaN
122  if (cloud.is_dense)
123  {
124  for (size_t i = 0; i < cloud.points.size (); ++i)
125  {
126  pcl::Vector4fMapConst pt = cloud.points[i].getVector4fMap ();
127  dist = (pivot_pt - pt).norm ();
128  if (dist > max_dist)
129  {
130  max_idx = i;
131  max_dist = dist;
132  }
133  }
134  }
135  // NaN or Inf values could exist => check for them
136  else
137  {
138  for (size_t i = 0; i < cloud.points.size (); ++i)
139  {
140  // Check if the point is invalid
141  if (!pcl_isfinite (cloud.points[i].x) || !pcl_isfinite (cloud.points[i].y) || !pcl_isfinite (cloud.points[i].z))
142  continue;
143  pcl::Vector4fMapConst pt = cloud.points[i].getVector4fMap ();
144  dist = (pivot_pt - pt).norm ();
145  if (dist > max_dist)
146  {
147  max_idx = i;
148  max_dist = dist;
149  }
150  }
151  }
152 
153  max_pt = cloud.points[max_idx].getVector4fMap ();
154 }
155 
157 template<typename PointT> inline void
158 pcl::getMaxDistance (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
159  const Eigen::Vector4f &pivot_pt, Eigen::Vector4f &max_pt)
160 {
161  float max_dist = -FLT_MAX;
162  int max_idx = -1;
163  float dist;
164 
165  // If the data is dense, we don't need to check for NaN
166  if (cloud.is_dense)
167  {
168  for (size_t i = 0; i < indices.size (); ++i)
169  {
170  pcl::Vector4fMapConst pt = cloud.points[indices[i]].getVector4fMap ();
171  dist = (pivot_pt - pt).norm ();
172  if (dist > max_dist)
173  {
174  max_idx = static_cast<int> (i);
175  max_dist = dist;
176  }
177  }
178  }
179  // NaN or Inf values could exist => check for them
180  else
181  {
182  for (size_t i = 0; i < indices.size (); ++i)
183  {
184  // Check if the point is invalid
185  if (!pcl_isfinite (cloud.points[indices[i]].x) || !pcl_isfinite (cloud.points[indices[i]].y)
186  ||
187  !pcl_isfinite (cloud.points[indices[i]].z))
188  continue;
189 
190  pcl::Vector4fMapConst pt = cloud.points[indices[i]].getVector4fMap ();
191  dist = (pivot_pt - pt).norm ();
192  if (dist > max_dist)
193  {
194  max_idx = static_cast<int> (i);
195  max_dist = dist;
196  }
197  }
198  }
199 
200  max_pt = cloud.points[indices[max_idx]].getVector4fMap ();
201 }
202 
204 template <typename PointT> inline void
205 pcl::getMinMax3D (const pcl::PointCloud<PointT> &cloud, PointT &min_pt, PointT &max_pt)
206 {
207  Eigen::Array4f min_p, max_p;
208  min_p.setConstant (FLT_MAX);
209  max_p.setConstant (-FLT_MAX);
210 
211  // If the data is dense, we don't need to check for NaN
212  if (cloud.is_dense)
213  {
214  for (size_t i = 0; i < cloud.points.size (); ++i)
215  {
216  pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
217  min_p = min_p.min (pt);
218  max_p = max_p.max (pt);
219  }
220  }
221  // NaN or Inf values could exist => check for them
222  else
223  {
224  for (size_t i = 0; i < cloud.points.size (); ++i)
225  {
226  // Check if the point is invalid
227  if (!pcl_isfinite (cloud.points[i].x) ||
228  !pcl_isfinite (cloud.points[i].y) ||
229  !pcl_isfinite (cloud.points[i].z))
230  continue;
231  pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
232  min_p = min_p.min (pt);
233  max_p = max_p.max (pt);
234  }
235  }
236  min_pt.x = min_p[0]; min_pt.y = min_p[1]; min_pt.z = min_p[2];
237  max_pt.x = max_p[0]; max_pt.y = max_p[1]; max_pt.z = max_p[2];
238 }
239 
241 template <typename PointT> inline void
242 pcl::getMinMax3D (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt)
243 {
244  Eigen::Array4f min_p, max_p;
245  min_p.setConstant (FLT_MAX);
246  max_p.setConstant (-FLT_MAX);
247 
248  // If the data is dense, we don't need to check for NaN
249  if (cloud.is_dense)
250  {
251  for (size_t i = 0; i < cloud.points.size (); ++i)
252  {
253  pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
254  min_p = min_p.min (pt);
255  max_p = max_p.max (pt);
256  }
257  }
258  // NaN or Inf values could exist => check for them
259  else
260  {
261  for (size_t i = 0; i < cloud.points.size (); ++i)
262  {
263  // Check if the point is invalid
264  if (!pcl_isfinite (cloud.points[i].x) ||
265  !pcl_isfinite (cloud.points[i].y) ||
266  !pcl_isfinite (cloud.points[i].z))
267  continue;
268  pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
269  min_p = min_p.min (pt);
270  max_p = max_p.max (pt);
271  }
272  }
273  min_pt = min_p;
274  max_pt = max_p;
275 }
276 
277 
279 template <typename PointT> inline void
281  Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt)
282 {
283  Eigen::Array4f min_p, max_p;
284  min_p.setConstant (FLT_MAX);
285  max_p.setConstant (-FLT_MAX);
286 
287  // If the data is dense, we don't need to check for NaN
288  if (cloud.is_dense)
289  {
290  for (size_t i = 0; i < indices.indices.size (); ++i)
291  {
292  pcl::Array4fMapConst pt = cloud.points[indices.indices[i]].getArray4fMap ();
293  min_p = min_p.min (pt);
294  max_p = max_p.max (pt);
295  }
296  }
297  // NaN or Inf values could exist => check for them
298  else
299  {
300  for (size_t i = 0; i < indices.indices.size (); ++i)
301  {
302  // Check if the point is invalid
303  if (!pcl_isfinite (cloud.points[indices.indices[i]].x) ||
304  !pcl_isfinite (cloud.points[indices.indices[i]].y) ||
305  !pcl_isfinite (cloud.points[indices.indices[i]].z))
306  continue;
307  pcl::Array4fMapConst pt = cloud.points[indices.indices[i]].getArray4fMap ();
308  min_p = min_p.min (pt);
309  max_p = max_p.max (pt);
310  }
311  }
312  min_pt = min_p;
313  max_pt = max_p;
314 }
315 
317 template <typename PointT> inline void
318 pcl::getMinMax3D (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
319  Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt)
320 {
321  min_pt.setConstant (FLT_MAX);
322  max_pt.setConstant (-FLT_MAX);
323 
324  // If the data is dense, we don't need to check for NaN
325  if (cloud.is_dense)
326  {
327  for (size_t i = 0; i < indices.size (); ++i)
328  {
329  pcl::Array4fMapConst pt = cloud.points[indices[i]].getArray4fMap ();
330  min_pt = min_pt.array ().min (pt);
331  max_pt = max_pt.array ().max (pt);
332  }
333  }
334  // NaN or Inf values could exist => check for them
335  else
336  {
337  for (size_t i = 0; i < indices.size (); ++i)
338  {
339  // Check if the point is invalid
340  if (!pcl_isfinite (cloud.points[indices[i]].x) ||
341  !pcl_isfinite (cloud.points[indices[i]].y) ||
342  !pcl_isfinite (cloud.points[indices[i]].z))
343  continue;
344  pcl::Array4fMapConst pt = cloud.points[indices[i]].getArray4fMap ();
345  min_pt = min_pt.array ().min (pt);
346  max_pt = max_pt.array ().max (pt);
347  }
348  }
349 }
350 
352 template <typename PointT> inline double
353 pcl::getCircumcircleRadius (const PointT &pa, const PointT &pb, const PointT &pc)
354 {
355  Eigen::Vector4f p1 (pa.x, pa.y, pa.z, 0);
356  Eigen::Vector4f p2 (pb.x, pb.y, pb.z, 0);
357  Eigen::Vector4f p3 (pc.x, pc.y, pc.z, 0);
358 
359  double p2p1 = (p2 - p1).norm (), p3p2 = (p3 - p2).norm (), p1p3 = (p1 - p3).norm ();
360  // Calculate the area of the triangle using Heron's formula
361  // (http://en.wikipedia.org/wiki/Heron's_formula)
362  double semiperimeter = (p2p1 + p3p2 + p1p3) / 2.0;
363  double area = sqrt (semiperimeter * (semiperimeter - p2p1) * (semiperimeter - p3p2) * (semiperimeter - p1p3));
364  // Compute the radius of the circumscribed circle
365  return ((p2p1 * p3p2 * p1p3) / (4.0 * area));
366 }
367 
369 template <typename PointT> inline void
370 pcl::getMinMax (const PointT &histogram, int len, float &min_p, float &max_p)
371 {
372  min_p = FLT_MAX;
373  max_p = -FLT_MAX;
374 
375  for (int i = 0; i < len; ++i)
376  {
377  min_p = (histogram[i] > min_p) ? min_p : histogram[i];
378  max_p = (histogram[i] < max_p) ? max_p : histogram[i];
379  }
380 }
381 
382 #endif //#ifndef PCL_COMMON_IMPL_H_
383