OctreeGrid.cpp
Go to the documentation of this file.
1 // kate: replace-tabs off; indent-width 4; indent-mode normal
2 // vim: ts=4:sw=4:noexpandtab
3 /*
4 
5 Copyright (c) 2010--2018,
6 François Pomerleau and Stephane Magnenat, ASL, ETHZ, Switzerland
7 You can contact the authors at <f dot pomerleau at gmail dot com> and
8 <stephane at magnenat dot net>
9 
10 All rights reserved.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
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 copyright
17  notice, this list of conditions and the following disclaimer in the
18  documentation and/or other materials provided with the distribution.
19  * Neither the name of the <organization> nor the
20  names of its contributors may be used to endorse or promote products
21  derived from this software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 #include "OctreeGrid.h"
36 
37 #include <limits>
38 
39 //Define Visitor classes to apply processing
40 template<typename T>
42  : idx{0}, pts(dp)
43 {
44 }
45 
46 template <typename T>
47 template<std::size_t dim>
49 {
50  if(oc.isLeaf() and not oc.isEmpty())
51  {
52  auto* data = oc.getData();
53  const auto& d = (*data)[0];
54 
55  std::size_t j = d;
56 
57  //retrieve index from lookup table if sampling in already switched element
58  if(std::size_t(d)<idx)
59  j = mapidx[d];
60 
61  //Switch columns j and idx
62  pts.swapCols(idx, j);
63 
64  //Maintain new index position
65  mapidx[idx] = j;
66  //Update index
67  ++idx;
68  }
69 
70  return true;
71 }
72 
73 template <typename T>
75 {
76  //Resize point cloud
78  //Reset param
79  idx=0;
80  return true;
81 }
82 
83 
84 template<typename T>
87 {
88  std::srand(seed);
89 }
90 template<typename T>
92  DataPoints& dp, const std::size_t seed_
94 {
95  std::srand(seed);
96 }
97 template<typename T>
98 template<std::size_t dim>
100 {
101  if(oc.isLeaf() and not oc.isEmpty())
102  {
103  auto* data = oc.getData();
104  const std::size_t nbData = (*data).size() - 1;
105  const std::size_t randId =
106  static_cast<std::size_t>( nbData *
107  (static_cast<float>(std::rand()/static_cast<float>(RAND_MAX))));
108 
109  const auto& d = (*data)[randId];
110 
111  std::size_t j = d;
112 
113  //retrieve index from lookup table if sampling in already switched element
114  if(std::size_t(d)<idx)
115  j = mapidx[d];
116 
117  //Switch columns j and idx
118  pts.swapCols(idx, j);
119 
120  //Maintain new index position
121  mapidx[idx] = j;
122  //Update index
123  ++idx;
124  }
125 
126  return true;
127 }
128 
129 template<typename T>
131 {
132  bool ret = FirstPtsSampler::finalize();
133  //Reset seed
134  std::srand(seed);
135 
136  return ret;
137 }
138 
139 template<typename T>
142 {
143 }
144 
145 template<typename T>
146 template<std::size_t dim>
148 {
149  if(oc.isLeaf() and not oc.isEmpty())
150  {
151  const int featDim(pts.features.rows());
152  const int descDim(pts.descriptors.rows());
153  const int timeDim(pts.times.rows());
154 
155  auto* data = oc.getData();
156  const std::size_t nbData = (*data).size();
157 
158  const auto& d = (*data)[0]; //get first data
159  std::size_t j = d; //j contains real index of first point
160 
161  //retrieve index from lookup table if sampling in already switched element
162  if(std::size_t(d)<idx)
163  j = mapidx[d];
164 
165  //We sum all the data in the first data
166  for(std::size_t id=1;id<nbData;++id)
167  {
168  //get current idx
169  const auto& curId = (*data)[id];
170  std::size_t i = curId; //i contains real index
171 
172  //retrieve index from lookup table if sampling in already switched element
173  if(std::size_t(curId)<idx)
174  i = mapidx[curId];
175 
176  for (int f = 0; f < (featDim - 1); ++f)
177  pts.features(f,j) += pts.features(f,i);
178 
179  if (pts.descriptors.cols() > 0)
180  for (int d = 0; d < descDim; ++d)
181  pts.descriptors(d,j) += pts.descriptors(d,i);
182 
183  if (pts.times.cols() > 0)
184  for (int t = 0; t < timeDim; ++t)
185  pts.times(t,j) += pts.times(t,i);
186  }
187 
188  // Normalize sums to get centroid (average)
189  for (int f = 0; f < (featDim - 1); ++f)
190  pts.features(f,j) /= T(nbData);
191 
192  if (pts.descriptors.cols() > 0)
193  for (int d = 0; d < descDim; ++d)
194  pts.descriptors(d,j) /= T(nbData);
195 
196  if (pts.times.cols() > 0)
197  for (int t = 0; t < timeDim; ++t)
198  pts.times(t,j) /= T(nbData);
199 
200  //Switch columns j and idx
201  pts.swapCols(idx, j);
202 
203  //Maintain new index position
204  mapidx[idx] = j;
205  //Update index
206  ++idx;
207  }
208 
209  return true;
210 }
211 template<typename T>
214 {
215 }
216 
217 template<typename T>
218 template<std::size_t dim>
220 {
221  if(oc.isLeaf() and not oc.isEmpty())
222  {
223  auto* data = oc.getData();
224  const std::size_t nbData = (*data).size();
225 
226  auto dist = [](const typename Octree_<T,dim>::Point& p1, const typename Octree_<T,dim>::Point& p2) -> T {
227  return (p1 - p2).norm();
228  };
229 
230  //Build centroid
231  typename Octree_<T,dim>::Point center;
232  for(std::size_t i=0;i<dim;++i) center(i)=T(0.);
233 
234  for(std::size_t id=0;id<nbData;++id)
235  {
236  //get current idx
237  const auto& curId = (*data)[id];
238  std::size_t i = curId; //i contains real index
239 
240  //retrieve index from lookup table if sampling in already switched element
241  if(std::size_t(curId)<idx)
242  i = mapidx[curId];
243 
244  for (std::size_t f = 0; f < dim; ++f)
245  center(f) += pts.features(f,i);
246  }
247  for(std::size_t i=0;i<dim;++i) center(i)/=T(nbData);
248 
249  //Get the closest point from the center
250  T minDist = std::numeric_limits<T>::max();
251  std::size_t medId = 0;
252 
253  for(std::size_t id=0;id<nbData;++id)
254  {
255  //get current idx
256  const auto curId = (*data)[id];
257  std::size_t i = curId; //i contains real index
258 
259  //retrieve index from lookup table if sampling in already switched element
260  if(std::size_t(curId)<idx)
261  i = mapidx[curId];
262 
263  const T curDist = dist(pts.features.col(i).head(dim), center);
264  if(curDist<minDist)
265  {
266  minDist = curDist;
267  medId=i;
268  }
269  }
270 
271  //Switch columns j and idx
272  pts.swapCols(idx, medId);
273 
274  //Maintain new index position
275  mapidx[idx] = medId;
276 
277  //Update index
278  ++idx;
279  }
280 
281  return true;
282 }
283 
284 // OctreeGridDataPointsFilter
285 template <typename T>
287  PointMatcher<T>::DataPointsFilter("OctreeGridDataPointsFilter",
289  buildParallel{Parametrizable::get<bool>("buildParallel")},
290  maxPointByNode{Parametrizable::get<std::size_t>("maxPointByNode")},
291  maxSizeByNode{Parametrizable::get<T>("maxSizeByNode")}
292 {
293  try
294  {
295  const int sm = this->template get<int>("samplingMethod");
297  }
298  catch (const InvalidParameter&)
299  {
300  samplingMethod = SamplingMethod::FIRST_PTS;
301  }
302 }
303 
304 template <typename T>
307 {
308  DataPoints output(input);
309  inPlaceFilter(output);
310  return output;
311 }
312 
313 template <typename T>
315 {
316  const std::size_t featDim = cloud.features.rows();
317 
318  assert(featDim == 4 or featDim == 3);
319 
320  if(featDim==3) //2D case
321  this->sample<2>(cloud);
322 
323  else if(featDim==4) //3D case
324  this->sample<3>(cloud);
325 }
326 
327 template<typename T>
328 template<std::size_t dim>
330 {
331  Octree_<T,dim> oc;
332 
334 
335  switch(samplingMethod)
336  {
337  case SamplingMethod::FIRST_PTS:
338  {
339  FirstPtsSampler sampler(cloud);
340  oc.visit(sampler);
341  sampler.finalize();
342  break;
343  }
344  case SamplingMethod::RAND_PTS:
345  {
346  RandomPtsSampler sampler(cloud); //FIXME: add seed parameter
347  oc.visit(sampler);
348  sampler.finalize();
349  break;
350  }
351  case SamplingMethod::CENTROID:
352  {
353  CentroidSampler sampler(cloud);
354  oc.visit(sampler);
355  sampler.finalize();
356  break;
357  }
358  case SamplingMethod::MEDOID:
359  {
360  MedoidSampler sampler(cloud);
361  oc.visit(sampler);
362  sampler.finalize();
363  break;
364  }
365  }
366 }
367 
368 
369 template struct OctreeGridDataPointsFilter<float>;
370 template struct OctreeGridDataPointsFilter<double>;
Matrix descriptors
descriptors of points in the cloud, might be empty
Definition: PointMatcher.h:333
data
Definition: icp.py:50
SamplingMethod samplingMethod
Definition: OctreeGrid.h:161
Definition: octree.h:78
virtual DataPoints filter(const DataPoints &input)
Apply filters to input point cloud. This is the non-destructive version and returns a copy...
Definition: OctreeGrid.cpp:306
static const ParametersDoc availableParameters()
Definition: OctreeGrid.h:77
DataContainer * getData()
Definition: octree.hpp:212
Functions and classes that are dependant on scalar type are defined in this templatized class...
Definition: PointMatcher.h:130
A data filter takes a point cloud as input, transforms it, and produces another point cloud as output...
Definition: PointMatcher.h:440
Parametrizable::Parameters Parameters
Definition: OctreeGrid.h:63
void swapCols(Index iCol, Index jCol)
Swap column i and j in the point cloud, swap also features and descriptors if any. Assumes sizes are similar.
Data Filter based on Octree representation.
Definition: OctreeGrid.h:54
bool operator()(Octree_< T, dim > &oc)
Definition: OctreeGrid.cpp:219
An exception thrown when one tries to fetch the value of an unexisting parameter. ...
void conservativeResize(Index pointCount)
Resize the cloud to pointCount points, conserving existing ones.
Eigen::Matrix< T, dim, 1 > Point
Definition: octree.h:88
bool visit(Callback &cb)
Definition: octree.hpp:373
virtual void inPlaceFilter(DataPoints &cloud)
Apply these filters to a point cloud without copying.
Definition: OctreeGrid.cpp:314
bool operator()(Octree_< T, dim > &oc)
Definition: OctreeGrid.cpp:99
bool operator()(Octree_< T, dim > &oc)
Definition: OctreeGrid.cpp:48
std::unordered_map< std::size_t, std::size_t > mapidx
Definition: OctreeGrid.h:97
Int64Matrix times
time associated to each points, might be empty
Definition: PointMatcher.h:335
bool operator()(Octree_< T, dim > &oc)
Definition: OctreeGrid.cpp:147
Matrix features
features of points in the cloud
Definition: PointMatcher.h:331
void sample(DataPoints &cloud)
Definition: OctreeGrid.cpp:329
bool isLeaf() const
Definition: octree.hpp:166
bool isEmpty() const
Definition: octree.hpp:176
bool build(const DP &pts, size_t maxDataByNode=1, T maxSizeByNode=T(0.), bool parallelBuild=false)
Definition: octree.hpp:231


libpointmatcher
Author(s):
autogenerated on Sat May 27 2023 02:38:02