PointCloud.cpp
Go to the documentation of this file.
1 #include "PointCloud.h"
2 #include <MiscLib/Vector.h>
3 #include <iostream>
4 #include <iterator>
5 #include <fstream>
6 #include <limits>
7 #include <algorithm>
8 #ifndef _USE_MATH_DEFINES
9 #define _USE_MATH_DEFINES
10 #endif
11 #include <cmath>
12 #include "Plane.h"
13 #include <GfxTL/KdTree.h>
16 #include <GfxTL/VectorKernel.h>
17 #include <GfxTL/NullTreeStrategy.h>
25 #include <GfxTL/L2Norm.h>
26 #include <GfxTL/Plane.h>
27 #include <GfxTL/VectorXD.h>
28 #include <GfxTL/IndexedIterator.h>
30 #include <MiscLib/NoShrinkVector.h>
31 
32 typedef GfxTL::KdTree
33 <
35 <
37 <
39 <
41 <
43 <
45 <
47 <
49 <
52  <
55  >
56  >
57  >
58  >
59  >
60  >
61  >
62  >
63  >,
67 
68 //#define LMS_NORMALS
69 #define PCA_NORMALS
70 
71 using namespace std;
72 
73 /*
74  * * This Quickselect routine is based on the algorithm described in
75  * * "Numerical recipes in C", Second Edition,
76  * * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
77  * * This code by Nicolas Devillard - 1998. Public domain.
78  * */
79 #define ELEM_SWAP(a,b) { float t=(a);(a)=(b);(b)=t; }
80 float quick_select(float arr[], int n)
81 {
82  int low, high ;
83  int median;
84  int middle, ll, hh;
85  low = 0 ;
86  high = n - 1 ;
87  median = (low + high) / 2;
88  for (;;)
89  {
90  if (high <= low) /* One element only */
91  {
92  return arr[median] ;
93  }
94  if (high == low + 1) /* Two elements only */
95  {
96  if (arr[low] > arr[high])
97  {
98  ELEM_SWAP(arr[low], arr[high]) ;
99  }
100  return arr[median] ;
101  }
102  /* Find median of low, middle and high items; swap into position low */
103  middle = (low + high) / 2;
104  if (arr[middle] > arr[high])
105  {
106  ELEM_SWAP(arr[middle], arr[high]) ;
107  }
108  if (arr[low] > arr[high])
109  {
110  ELEM_SWAP(arr[low], arr[high]) ;
111  }
112  if (arr[middle] > arr[low])
113  {
114  ELEM_SWAP(arr[middle], arr[low]) ;
115  }
116  /* Swap low item (now in position middle) into position (low+1) */
117  ELEM_SWAP(arr[middle], arr[low + 1]) ;
118  /* Nibble from each end towards middle, swapping items when stuck */
119  ll = low + 1;
120  hh = high;
121  for (;;)
122  {
123  do
124  {
125  ll++;
126  }
127  while (arr[low] > arr[ll]) ;
128  do
129  {
130  hh--;
131  }
132  while (arr[hh] > arr[low]) ;
133  if (hh < ll)
134  {
135  break;
136  }
137  ELEM_SWAP(arr[ll], arr[hh]) ;
138  }
139  /* Swap middle item (in position low) back into correct position */
140  ELEM_SWAP(arr[low], arr[hh]) ;
141  /* Re-set active partition */
142  if (hh <= median)
143  {
144  low = ll;
145  }
146  if (hh >= median)
147  {
148  high = hh - 1;
149  }
150  }
151 }
152 #undef ELEM_SWAP
153 
155 {
156  float fmax = numeric_limits<float>::max();
157  float fmin = -fmax;
158  m_min = Vec3f(fmax, fmax, fmax);
159  m_max = Vec3f(fmin, fmin, fmin);
160 }
161 
162 PointCloud::PointCloud(Point* points, unsigned int s)
163 {
164  float fmax = numeric_limits<float>::max();
165  float fmin = -fmax;
166  m_min = Vec3f(fmax, fmax, fmax);
167  m_max = Vec3f(fmin, fmin, fmin);
168  std::copy(points, points + s, std::back_inserter(*this));
169 }
170 
171 void PointCloud::reset(size_t s)
172 {
173  resize(s);
174  float fmax = numeric_limits<float>::max();
175  float fmin = -fmax;
176  m_min = Vec3f(fmax, fmax, fmax);
177  m_max = Vec3f(fmin, fmin, fmin);
178 }
179 
180 float* PointCloud::getBbox() const
181 {
182  float* bbox = new float[6];
183  m_min.getValue(bbox[0], bbox[2], bbox[4]);
184  m_max.getValue(bbox[1], bbox[3], bbox[5]);
185 
186  return bbox;
187 }
188 
190 {
191  *min = m_min;
192  *max = m_max;
193 }
194 
195 void PointCloud::Translate(const Vec3f& trans)
196 {
197  for (size_t i = 0; i < size(); ++i)
198  {
199  at(i).pos += trans;
200  }
201  m_min += trans;
202  m_max += trans;
203 }
204 
205 void PointCloud::calcNormals(float radius, unsigned int kNN, unsigned int maxTries)
206 {
207  // cerr << "Begin calcNormals " << endl << flush;
208 
209  KdTree3Df kd;
210  kd.IndexedData(begin(), end());
211  kd.Build();
212 
215  //GfxTL::AssumeUniqueLimitedHeap< GfxTL::NN< float > > nn;
217 
218  vector<int> stats(91, 0);
219 #ifdef PCA_NORMALS
221 #endif
222  for (unsigned int i = 0; i < size(); i ++)
223  {
224  //kd.PointsInBall(at(i), radius, &nn);
225  //if(nn.size() > kNN)
226  //{
227  // std::sort(nn.begin(), nn.end());
228  // nn.resize(kNN);
229  //}
230  kd.NearestNeighbors(at(i), kNN, &nn, &nnAux);
231  unsigned int num = (unsigned int)nn.size();
232 
233  //if(i%1000 == 0)
234  // cerr << num << " ";
235 
236  if (num > kNN)
237  {
238  num = kNN;
239  }
240 
241  at(i).normal = Vec3f(0, 0, 0);
242  if (num < 8)
243  {
244 
245  continue;
246  }
247 
248 #ifdef PCA_NORMALS
249  weights.resize(nn.size());
250  if (nn.front().sqrDist > 0)
251  {
252  float h = nn.front().sqrDist / 2;
253  for (unsigned int i = 0; i < nn.size(); ++i)
254  {
255  weights[i] = std::exp(-nn[i].sqrDist / h);
256  }
257  }
258  else
259  {
260  std::fill(weights.begin(), weights.end(), 1.f);
261  }
262  plane.Fit(GfxTL::IndexIterate(nn.begin(), begin()),
263  GfxTL::IndexIterate(nn.end(), begin()), weights.begin());
264  at(i).normal = Vec3f(plane.Normal().Data());
265 #endif
266 
267 #ifdef LMS_NORMALS
268  float score, bestScore = -1.f;
269  for (unsigned int tries = 0; tries < maxTries; tries++)
270  {
271  //choose candidate
272  int i0, i1, i2;
273  i0 = rand() % num;
274  do
275  {
276  i1 = rand() % num;
277  }
278  while (i1 == i0);
279  do
280  {
281  i2 = rand() % num;
282  }
283  while (i2 == i0 || i2 == i1);
284 
285  Plane plane;
286  if (!plane.Init(at(nn[i0]), at(nn[i1]), at(nn[i2])))
287  {
288  continue;
289  }
290 
291  //evaluate metric
292  float* dist = new float[num];
293  for (unsigned int j = 0; j < num; j++)
294  {
295  dist[j] = plane.getDistance(at(nn[j]));
296  }
297  // sort(dist, dist+num);
298  // score = dist[num/2]; // evaluate median
299  score = quick_select(dist, num); // evaluate median
300  delete[] dist;
301 
302  if (score < bestScore || bestScore < 0.f)
303  {
304  if (tries > maxTries / 2)
305  {
306  // let us see how good the first half of candidates are...
307  int index = std::floor(180 / M_PI * std::acos(std::min(1.f, abs(plane.getNormal().dot(at(i).normal)))));
308  stats[index]++;
309  }
310  at(i).normal = plane.getNormal();
311  bestScore = score;
312  }
313 
314  }
315 
316 #endif
317 
318  }
319 
320  //cerr << "End calcNormals " << endl << flush;
321  //copy(stats.begin(), stats.end(), ostream_iterator<int>(cerr, " "));
322 }
CellBBoxBuildInformationKdTreeStrategy.h
IndexedTreeDataKernels.h
CellLevelTreeStrategy.h
IncrementalDistanceKdTreeStrategy.h
ELEM_SWAP
#define ELEM_SWAP(a, b)
Definition: PointCloud.cpp:79
PointCloud::Translate
void Translate(const Vec3f &trans)
Definition: PointCloud.cpp:195
GfxTL::Plane
Definition: Plane.h:14
Vector.h
quick_select
float quick_select(float arr[], int n)
Definition: PointCloud.cpp:80
Vec3f
Definition: basic.h:16
index
uint8_t index
Definition: EtherCATFrame.h:59
GfxTL::KdTree
Definition: KdTree.h:152
PointCloud::calcNormals
void calcNormals(float radius, unsigned int kNN=20, unsigned int maxTries=100)
Definition: PointCloud.cpp:205
MiscLib::NoShrinkVector::end
T * end()
Definition: NoShrinkVector.h:395
GfxTL::VectorKernelD::VectorKernelType
Definition: VectorKernel.h:130
GfxTL::CellBBoxBuildInformationKdTreeStrategy
Definition: CellBBoxBuildInformationKdTreeStrategy.h:7
NullTreeStrategy.h
Plane.h
MiscLib::Vector< size_t >
VectorXD.h
GfxTL::IndexedIteratorTreeDataKernel
Definition: IndexedTreeDataKernels.h:273
GfxTL::Plane::Normal
void Normal(PointType *normal) const
Definition: Plane.hpp:44
MiscLib::Vector< Point >::const_iterator
const typedef Point * const_iterator
Definition: Vector.h:26
PointCloud::PointCloud
PointCloud()
Definition: PointCloud.cpp:154
MiscLib::NoShrinkVector
Definition: NoShrinkVector.h:17
NoShrinkVector.h
GfxTL::KdTree::NearestNeighborsAuxData
Definition: KdTree.h:425
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
copy
Use of this software is granted under one of the following two to be chosen freely by the user Boost Software License Version Marcin Kalicinski Permission is hereby free of to any person or organization obtaining a copy of the software and accompanying documentation covered by this and transmit the and to prepare derivative works of the and to permit third parties to whom the Software is furnished to do all subject to the including the above license this restriction and the following must be included in all copies of the in whole or in and all derivative works of the unless such copies or derivative works are solely in the form of machine executable object code generated by a source language processor THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR TITLE AND NON INFRINGEMENT IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN TORT OR ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE The MIT Marcin Kalicinski Permission is hereby free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to copy
Definition: license.txt:39
M_PI
#define M_PI
Definition: MathTools.h:17
KdTree.h
PointCloud::reset
void reset(size_t s=0)
Definition: PointCloud.cpp:171
Point
Definition: PointCloud.h:21
MiscLib::NoShrinkVector::resize
void resize(size_type s, const value_type &v)
Definition: NoShrinkVector.h:228
CellRangeDataTreeStrategy.h
GfxTL::IndexIterate
IndexedIterator< IndexIteratorT, IteratorT > IndexIterate(IndexIteratorT idxIt, IteratorT it)
Definition: IndexedIterator.h:154
GfxTL::BucketSizeMaxLevelSubdivisionTreeStrategy
Definition: BucketSizeMaxLevelSubdivisionTreeStrategy.h:7
GfxTL::KdTree::Build
void Build()
Definition: KdTree.h:240
max
T max(T t1, T t2)
Definition: gdiam.h:48
BBoxDistanceKdTreeStrategy.h
GfxTL::CellRangeDataTreeStrategy
Definition: CellRangeDataTreeStrategy.h:8
BucketSizeMaxLevelSubdivisionTreeStrategy.h
IndexedIterator.h
Plane::Init
bool Init(Vec3f p1, Vec3f p2, Vec3f p3)
Definition: Plane.cpp:29
BBoxBuildInformationTreeStrategy.h
PointCloud::GetCurrentBBox
void GetCurrentBBox(Vec3f *min, Vec3f *max) const
Definition: PointCloud.cpp:189
Vec3f::dot
float dot(const Vec3f &v) const
Definition: basic.h:92
L2Norm.h
VectorKernel.h
Plane::getNormal
const Vec3f & getNormal() const
Definition: Plane.h:51
std
Definition: Application.h:66
GfxTL::BaseKdTreeStrategy
Definition: KdTree.h:103
GfxTL::L2Norm
Definition: L2Norm.h:623
GfxTL::BBoxBuildInformationTreeStrategy
Definition: BBoxBuildInformationTreeStrategy.h:8
GfxTL::LimitedHeap
Definition: LimitedHeap.h:14
MiscLib::NoShrinkVector::begin
T * begin()
Definition: NoShrinkVector.h:385
GfxTL::CellLevelTreeStrategy
Definition: CellLevelTreeStrategy.h:7
PointCloud.h
Plane
Definition: Plane.h:16
GfxTL::Vec3f
VectorXD< 3, float > Vec3f
Definition: VectorXD.h:691
GfxTL::IncrementalDistanceKdTreeStrategy
Definition: IncrementalDistanceKdTreeStrategy.h:7
GfxTL::MaxIntervalSplittingKdTreeStrategy
Definition: MaxIntervalSplittingKdTreeStrategy.h:9
min
T min(T t1, T t2)
Definition: gdiam.h:42
KdTree3Df
GfxTL::KdTree< GfxTL::IncrementalDistanceKdTreeStrategy< GfxTL::MaxIntervalSplittingKdTreeStrategy< GfxTL::CellBBoxBuildInformationKdTreeStrategy< GfxTL::BBoxBuildInformationTreeStrategy< GfxTL::BucketSizeMaxLevelSubdivisionTreeStrategy< GfxTL::CellLevelTreeStrategy< GfxTL::BaseKdTreeStrategy< GfxTL::CellRangeDataTreeStrategy< GfxTL::NullTreeStrategy, GfxTL::IndexedIteratorTreeDataKernel< PointCloud::const_iterator, MiscLib::Vector< size_t > > > > > > > > > >, GfxTL::L2Norm, GfxTL::VectorKernelD< 3 >::VectorKernelType > KdTree3Df
Definition: PointCloud.cpp:66
Plane::getDistance
float getDistance(const Vec3f &pos) const
Definition: Plane.h:30
MaxIntervalSplittingKdTreeStrategy.h
GfxTL::Plane::Fit
bool Fit(const PointType &origin, PointsForwardIt begin, PointsForwardIt end, WeightsForwardIt weights)
Definition: Plane.h:64
GfxTL::NullTreeStrategy
Definition: NullTreeStrategy.h:6
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
AlignedAllocator.h
PointCloud::getBbox
float * getBbox() const
Definition: PointCloud.cpp:180
GfxTL::KdTree::NearestNeighbors
void NearestNeighbors(const PointT &p, unsigned int k, LimitedHeapT *neighbors) const
Definition: KdTree.h:380