PointCloud.cpp
Go to the documentation of this file.
1 #include "PointCloud.h"
2 
3 #include <algorithm>
4 #include <fstream>
5 #include <iostream>
6 #include <iterator>
7 #include <limits>
8 
9 #include <MiscLib/Vector.h>
10 #ifndef _USE_MATH_DEFINES
11 #define _USE_MATH_DEFINES
12 #endif
13 #include <cmath>
14 
15 #include "Plane.h"
23 #include <GfxTL/IndexedIterator.h>
25 #include <GfxTL/KdTree.h>
26 #include <GfxTL/L2Norm.h>
28 #include <GfxTL/NullTreeStrategy.h>
29 #include <GfxTL/Plane.h>
30 #include <GfxTL/VectorKernel.h>
31 #include <GfxTL/VectorXD.h>
33 #include <MiscLib/NoShrinkVector.h>
34 
35 typedef GfxTL::KdTree<
42  MiscLib::Vector<size_t>>>>>>>>>>,
46 
47 //#define LMS_NORMALS
48 #define PCA_NORMALS
49 
50 using namespace std;
51 
52 /*
53  * * This Quickselect routine is based on the algorithm described in
54  * * "Numerical recipes in C", Second Edition,
55  * * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
56  * * This code by Nicolas Devillard - 1998. Public domain.
57  * */
58 #define ELEM_SWAP(a, b) \
59  { \
60  float t = (a); \
61  (a) = (b); \
62  (b) = t; \
63  }
64 
65 float
66 quick_select(float arr[], int n)
67 {
68  int low, high;
69  int median;
70  int middle, ll, hh;
71  low = 0;
72  high = n - 1;
73  median = (low + high) / 2;
74  for (;;)
75  {
76  if (high <= low) /* One element only */
77  {
78  return arr[median];
79  }
80  if (high == low + 1) /* Two elements only */
81  {
82  if (arr[low] > arr[high])
83  {
84  ELEM_SWAP(arr[low], arr[high]);
85  }
86  return arr[median];
87  }
88  /* Find median of low, middle and high items; swap into position low */
89  middle = (low + high) / 2;
90  if (arr[middle] > arr[high])
91  {
92  ELEM_SWAP(arr[middle], arr[high]);
93  }
94  if (arr[low] > arr[high])
95  {
96  ELEM_SWAP(arr[low], arr[high]);
97  }
98  if (arr[middle] > arr[low])
99  {
100  ELEM_SWAP(arr[middle], arr[low]);
101  }
102  /* Swap low item (now in position middle) into position (low+1) */
103  ELEM_SWAP(arr[middle], arr[low + 1]);
104  /* Nibble from each end towards middle, swapping items when stuck */
105  ll = low + 1;
106  hh = high;
107  for (;;)
108  {
109  do
110  {
111  ll++;
112  } while (arr[low] > arr[ll]);
113  do
114  {
115  hh--;
116  } while (arr[hh] > arr[low]);
117  if (hh < ll)
118  {
119  break;
120  }
121  ELEM_SWAP(arr[ll], arr[hh]);
122  }
123  /* Swap middle item (in position low) back into correct position */
124  ELEM_SWAP(arr[low], arr[hh]);
125  /* Re-set active partition */
126  if (hh <= median)
127  {
128  low = ll;
129  }
130  if (hh >= median)
131  {
132  high = hh - 1;
133  }
134  }
135 }
136 
137 #undef ELEM_SWAP
138 
140 {
141  float fmax = numeric_limits<float>::max();
142  float fmin = -fmax;
143  m_min = Vec3f(fmax, fmax, fmax);
144  m_max = Vec3f(fmin, fmin, fmin);
145 }
146 
147 PointCloud::PointCloud(Point* points, unsigned int s)
148 {
149  float fmax = numeric_limits<float>::max();
150  float fmin = -fmax;
151  m_min = Vec3f(fmax, fmax, fmax);
152  m_max = Vec3f(fmin, fmin, fmin);
153  std::copy(points, points + s, std::back_inserter(*this));
154 }
155 
156 void
158 {
159  resize(s);
160  float fmax = numeric_limits<float>::max();
161  float fmin = -fmax;
162  m_min = Vec3f(fmax, fmax, fmax);
163  m_max = Vec3f(fmin, fmin, fmin);
164 }
165 
166 float*
168 {
169  float* bbox = new float[6];
170  m_min.getValue(bbox[0], bbox[2], bbox[4]);
171  m_max.getValue(bbox[1], bbox[3], bbox[5]);
172 
173  return bbox;
174 }
175 
176 void
178 {
179  *min = m_min;
180  *max = m_max;
181 }
182 
183 void
185 {
186  for (size_t i = 0; i < size(); ++i)
187  {
188  at(i).pos += trans;
189  }
190  m_min += trans;
191  m_max += trans;
192 }
193 
194 void
195 PointCloud::calcNormals(float radius, unsigned int kNN, unsigned int maxTries)
196 {
197  // cerr << "Begin calcNormals " << endl << flush;
198 
199  KdTree3Df kd;
200  kd.IndexedData(begin(), end());
201  kd.Build();
202 
205  //GfxTL::AssumeUniqueLimitedHeap< GfxTL::NN< float > > nn;
207 
208  vector<int> stats(91, 0);
209 #ifdef PCA_NORMALS
211 #endif
212  for (unsigned int i = 0; i < size(); i++)
213  {
214  //kd.PointsInBall(at(i), radius, &nn);
215  //if(nn.size() > kNN)
216  //{
217  // std::sort(nn.begin(), nn.end());
218  // nn.resize(kNN);
219  //}
220  kd.NearestNeighbors(at(i), kNN, &nn, &nnAux);
221  unsigned int num = (unsigned int)nn.size();
222 
223  //if(i%1000 == 0)
224  // cerr << num << " ";
225 
226  if (num > kNN)
227  {
228  num = kNN;
229  }
230 
231  at(i).normal = Vec3f(0, 0, 0);
232  if (num < 8)
233  {
234 
235  continue;
236  }
237 
238 #ifdef PCA_NORMALS
239  weights.resize(nn.size());
240  if (nn.front().sqrDist > 0)
241  {
242  float h = nn.front().sqrDist / 2;
243  for (unsigned int i = 0; i < nn.size(); ++i)
244  {
245  weights[i] = std::exp(-nn[i].sqrDist / h);
246  }
247  }
248  else
249  {
250  std::fill(weights.begin(), weights.end(), 1.f);
251  }
252  plane.Fit(GfxTL::IndexIterate(nn.begin(), begin()),
253  GfxTL::IndexIterate(nn.end(), begin()),
254  weights.begin());
255  at(i).normal = Vec3f(plane.Normal().Data());
256 #endif
257 
258 #ifdef LMS_NORMALS
259  float score, bestScore = -1.f;
260  for (unsigned int tries = 0; tries < maxTries; tries++)
261  {
262  //choose candidate
263  int i0, i1, i2;
264  i0 = rand() % num;
265  do
266  {
267  i1 = rand() % num;
268  } while (i1 == i0);
269  do
270  {
271  i2 = rand() % num;
272  } while (i2 == i0 || i2 == i1);
273 
274  Plane plane;
275  if (!plane.Init(at(nn[i0]), at(nn[i1]), at(nn[i2])))
276  {
277  continue;
278  }
279 
280  //evaluate metric
281  float* dist = new float[num];
282  for (unsigned int j = 0; j < num; j++)
283  {
284  dist[j] = plane.getDistance(at(nn[j]));
285  }
286  // sort(dist, dist+num);
287  // score = dist[num/2]; // evaluate median
288  score = quick_select(dist, num); // evaluate median
289  delete[] dist;
290 
291  if (score < bestScore || bestScore < 0.f)
292  {
293  if (tries > maxTries / 2)
294  {
295  // let us see how good the first half of candidates are...
296  int index = std::floor(
297  180 / M_PI *
298  std::acos(std::min(1.f, abs(plane.getNormal().dot(at(i).normal)))));
299  stats[index]++;
300  }
301  at(i).normal = plane.getNormal();
302  bestScore = score;
303  }
304  }
305 
306 #endif
307  }
308 
309  //cerr << "End calcNormals " << endl << flush;
310  //copy(stats.begin(), stats.end(), ostream_iterator<int>(cerr, " "));
311 }
CellBBoxBuildInformationKdTreeStrategy.h
IndexedTreeDataKernels.h
CellLevelTreeStrategy.h
IncrementalDistanceKdTreeStrategy.h
ELEM_SWAP
#define ELEM_SWAP(a, b)
Definition: PointCloud.cpp:58
PointCloud::Translate
void Translate(const Vec3f &trans)
Definition: PointCloud.cpp:184
GfxTL::Vec3f
VectorXD< 3, float > Vec3f
Definition: VectorXD.h:733
GfxTL::Plane
Definition: Plane.h:14
Vector.h
quick_select
float quick_select(float arr[], int n)
Definition: PointCloud.cpp:66
Vec3f
Definition: basic.h:17
index
uint8_t index
Definition: EtherCATFrame.h:59
GfxTL::KdTree
Definition: KdTree.h:169
PointCloud::calcNormals
void calcNormals(float radius, unsigned int kNN=20, unsigned int maxTries=100)
Definition: PointCloud.cpp:195
MiscLib::NoShrinkVector::end
T * end()
Definition: NoShrinkVector.h:412
GfxTL::VectorKernelD::VectorKernelType
Definition: VectorKernel.h:126
GfxTL::CellBBoxBuildInformationKdTreeStrategy
Definition: CellBBoxBuildInformationKdTreeStrategy.h:7
NullTreeStrategy.h
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:418
Plane.h
MiscLib::Vector< size_t >
VectorXD.h
GfxTL::IndexedIteratorTreeDataKernel
Definition: IndexedTreeDataKernels.h:315
GfxTL::Plane::Normal
void Normal(PointType *normal) const
Definition: Plane.hpp:48
MiscLib::Vector< Point >::const_iterator
const typedef Point * const_iterator
Definition: Vector.h:25
PointCloud::PointCloud
PointCloud()
Definition: PointCloud.cpp:139
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:45
MiscLib::NoShrinkVector
Definition: NoShrinkVector.h:17
NoShrinkVector.h
GfxTL::KdTree::NearestNeighborsAuxData
Definition: KdTree.h:456
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
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:157
Point
Definition: PointCloud.h:21
MiscLib::NoShrinkVector::resize
void resize(size_type s, const value_type &v)
Definition: NoShrinkVector.h:235
CellRangeDataTreeStrategy.h
GfxTL::BucketSizeMaxLevelSubdivisionTreeStrategy
Definition: BucketSizeMaxLevelSubdivisionTreeStrategy.h:7
GfxTL::KdTree::Build
void Build()
Definition: KdTree.h:246
GfxTL::IndexIterate
IndexedIterator< IndexIteratorT, IteratorT > IndexIterate(IndexIteratorT idxIt, IteratorT it)
Definition: IndexedIterator.h:173
max
T max(T t1, T t2)
Definition: gdiam.h:51
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:30
BBoxBuildInformationTreeStrategy.h
PointCloud::GetCurrentBBox
void GetCurrentBBox(Vec3f *min, Vec3f *max) const
Definition: PointCloud.cpp:177
Vec3f::dot
float dot(const Vec3f &v) const
Definition: basic.h:104
L2Norm.h
VectorKernel.h
Plane::getNormal
const Vec3f & getNormal() const
Definition: Plane.h:72
std
Definition: Application.h:66
GfxTL::BaseKdTreeStrategy
Definition: KdTree.h:115
GfxTL::L2Norm
Definition: L2Norm.h:608
GfxTL::BBoxBuildInformationTreeStrategy
Definition: BBoxBuildInformationTreeStrategy.h:8
GfxTL::LimitedHeap
Definition: LimitedHeap.h:15
MiscLib::NoShrinkVector::begin
T * begin()
Definition: NoShrinkVector.h:400
GfxTL::CellLevelTreeStrategy
Definition: CellLevelTreeStrategy.h:7
PointCloud.h
Plane
Definition: Plane.h:18
GfxTL::IncrementalDistanceKdTreeStrategy
Definition: IncrementalDistanceKdTreeStrategy.h:7
GfxTL::MaxIntervalSplittingKdTreeStrategy
Definition: MaxIntervalSplittingKdTreeStrategy.h:9
min
T min(T t1, T t2)
Definition: gdiam.h:44
Plane::getDistance
float getDistance(const Vec3f &pos) const
Definition: Plane.h:41
MaxIntervalSplittingKdTreeStrategy.h
GfxTL::Plane::Fit
bool Fit(const PointType &origin, PointsForwardIt begin, PointsForwardIt end, WeightsForwardIt weights)
Definition: Plane.h:71
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:167
GfxTL::KdTree::NearestNeighbors
void NearestNeighbors(const PointT &p, unsigned int k, LimitedHeapT *neighbors) const
Definition: KdTree.h:403