iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test-PointCloud2.C
Go to the documentation of this file.
1 /*! @file
2  @author Shane Grant
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 #include <nrt/config.h>
35 #ifdef NRT_HAVE_CLOUD
36 
40 
41 #define BOOST_TEST_DYN_LINK
42 #define BOOST_TEST_MODULE PointCloudTest
43 #include <boost/test/unit_test.hpp>
44 
45 using namespace nrt;
46 
47 namespace
48 {
49  bool isAligned( const void * __restrict__ pointer, size_t byte_count )
50  {
51  return (uintptr_t)pointer % byte_count == 0;
52  }
53 }
54 
55 // ######################################################################
56 BOOST_AUTO_TEST_CASE( PointSSETest )
57 {
58  char unused = 2; // to help with alignment test
59  PointCloud2::Geometry aPoint( 3 );
60 
61  BOOST_CHECK_EQUAL( aPoint.x(), 3 );
62  BOOST_CHECK_EQUAL( aPoint.y(), 3 );
63  BOOST_CHECK_EQUAL( aPoint.z(), 3 );
64  BOOST_CHECK_EQUAL( aPoint.w(), 0 );
65 
66  aPoint.w() = 3;
67  BOOST_CHECK_EQUAL( aPoint.w(), 3 );
68 
69  BOOST_CHECK_EQUAL( isAligned( &aPoint, 16 ), true );
70 
71  auto eigenVec4 = aPoint.getVectorMap();
72  eigenVec4[3] = 3;
73 
74  auto eigenVec3 = aPoint.getVector3Map();
75  eigenVec3[2] = 2;
76 
77  BOOST_CHECK_EQUAL( aPoint.w(), 3 );
78  BOOST_CHECK_EQUAL( aPoint.z(), 2 );
79  assert(unused == 2);
80 
81  aPoint.x() = 1;
82  aPoint.y() = 2;
83  aPoint.z() = 3;
84  aPoint.w() = 4;
85 
86  BOOST_CHECK_EQUAL( aPoint.x(), 1 );
87  BOOST_CHECK_EQUAL( aPoint.y(), 2 );
88  BOOST_CHECK_EQUAL( aPoint.z(), 3 );
89  BOOST_CHECK_EQUAL( aPoint.w(), 4 );
90 }
91 
92 // ######################################################################
93 BOOST_AUTO_TEST_CASE( PointCloud2DataTest )
94 {
95  PointCloud2Data<> data;
96  BOOST_CHECK_EQUAL( isAligned( &data.geometry(), 16 ), true );
97 
98  data.geometry().x() = 1;
99  data.geometry().y() = 2;
100  data.geometry().z() = 3;
101  data.geometry().w() = 4;
102 
103  PointCloud2::Geometry someGeo(3);
104  PointCloud2DataRef<> simpleDataRef(someGeo);
105 
106  simpleDataRef = data;
107 
108  BOOST_CHECK_EQUAL( someGeo.x(), 1 );
109  BOOST_CHECK_EQUAL( someGeo.y(), 2 );
110  BOOST_CHECK_EQUAL( someGeo.z(), 3 );
111  BOOST_CHECK_EQUAL( someGeo.w(), 4 );
112 
113  PointCloud2Data<int, float> dataWithFields;
114  BOOST_CHECK_EQUAL( isAligned( &dataWithFields.geometry(), 16 ), true );
115  BOOST_CHECK_EQUAL( dataWithFields.hasType<int>(), true );
116  BOOST_CHECK_EQUAL( dataWithFields.hasType<float>(), true );
117  BOOST_CHECK_EQUAL( dataWithFields.hasType<char>(), false );
118 
119  dataWithFields = {{1, 2, 3, 4}, 5, 6.0f};
120  BOOST_CHECK_EQUAL( dataWithFields.geometry().x(), 1 );
121  BOOST_CHECK_EQUAL( dataWithFields.geometry().y(), 2 );
122  BOOST_CHECK_EQUAL( dataWithFields.geometry().z(), 3 );
123  BOOST_CHECK_EQUAL( dataWithFields.geometry().w(), 4 );
124  BOOST_CHECK_EQUAL( dataWithFields.get<int>(), 5 );
125  BOOST_CHECK_EQUAL( dataWithFields.get<float>(), 6.0f );
126 
127  PointCloud2DataRef<int, float> dataRef( dataWithFields );
128 
129  dataRef.geometry().x() = 33;
130  BOOST_CHECK_EQUAL( dataWithFields.geometry().x(), 33 );
131  BOOST_CHECK_EQUAL( dataWithFields.geometry().x(), dataRef.geometry().x() );
132 
133  dataRef.get<float>() = 4.2f;
134  BOOST_CHECK_EQUAL( dataWithFields.get<float>(), 4.2f );
135  BOOST_CHECK_EQUAL( dataWithFields.get<float>(), dataRef.get<float>() );
136 
137  PointCloud2ConstDataRef<int, float> dataConstRef( dataRef );
138  BOOST_CHECK_EQUAL( dataWithFields.get<float>(), dataConstRef.get<float>() );
139 
140  dataWithFields.geometry().y() = 33;
141  BOOST_CHECK_EQUAL( dataConstRef.geometry().y(), 33 );
142  BOOST_CHECK_EQUAL( dataConstRef.geometry().y(), dataWithFields.geometry().y() );
143 
144  PointCloud2Data<int, double> testInitializerList = {{3.0f}, 1, 2.0};
145  BOOST_CHECK_EQUAL( testInitializerList.geometry().y(), 3.0f );
146  BOOST_CHECK_EQUAL( testInitializerList.get<int>(), 1 );
147  BOOST_CHECK_EQUAL( testInitializerList.get<double>(), 2.0 );
148 
149  testInitializerList = {{2.0f}, 3, 4.0};
150  BOOST_CHECK_EQUAL( testInitializerList.geometry().y(), 2.0f );
151  BOOST_CHECK_EQUAL( testInitializerList.get<int>(), 3 );
152  BOOST_CHECK_EQUAL( testInitializerList.get<double>(), 4.0 );
153 }
154 
155 // ######################################################################
156 BOOST_AUTO_TEST_CASE( FieldPointCloudTests )
157 {
158  // Test adding fields
159  PointCloud2 cloud1;
160  cloud1.addField<>();
161 
162  BOOST_CHECK_EQUAL( cloud1.hasSameFields( PointCloud2() ), true );
163 
164  cloud1.addField<int, bool, char>();
165  cloud1.addField<SparseField<int>>();
167  cloud1.addField<SparseField<double>>();
168 
169  BOOST_CHECK_EQUAL( cloud1.hasDenseField<int>(), true );
170  BOOST_CHECK_EQUAL( cloud1.hasDenseField<bool>(), true );
171  BOOST_CHECK_EQUAL( cloud1.hasDenseField<char>(), true );
172  BOOST_CHECK_EQUAL( cloud1.hasSparseField<int>(), false );
173  BOOST_CHECK_EQUAL( cloud1.hasDenseField<double>(), false );
174  BOOST_CHECK_EQUAL( cloud1.hasSparseField<double>(), true );
175 
176  // Removing fields
177  cloud1.removeField<int, bool, char, double>();
178  BOOST_CHECK_EQUAL( cloud1.hasSameFields( PointCloud2() ), true );
179 
180  // Static ctor
181  auto cloudFromStatic = PointCloud2::create<int, SparseField<bool>>();
182  BOOST_CHECK_EQUAL( cloudFromStatic.hasDenseField<int>(), true );
183  BOOST_CHECK_EQUAL( cloudFromStatic.hasSparseField<bool>(), true );
184 }
185 
186 // ######################################################################
187 BOOST_AUTO_TEST_CASE( AssignmentAndMovingTests )
188 {
189  PointCloud2 cloud1;
190  cloud1.insert( {3} );
191  cloud1.insert( {4} );
192  cloud1.insert( {5} );
193 
194  PointCloud2 cloud2( cloud1 );
195 
196  BOOST_CHECK_EQUAL( cloud2[0].x(), cloud1[0].x() );
197  BOOST_CHECK_EQUAL( cloud2[1].y(), cloud1[1].y() );
198  BOOST_CHECK_EQUAL( cloud2[2].z(), cloud1[2].z() );
199 
200  cloud1 = cloud2;
201 
202  BOOST_CHECK_EQUAL( cloud2[0].x(), cloud1[0].x() );
203  BOOST_CHECK_EQUAL( cloud2[1].y(), cloud1[1].y() );
204  BOOST_CHECK_EQUAL( cloud2[2].z(), cloud1[2].z() );
205 
206  PointCloud2 cloud3 = PointCloud2::create<int>(1);
207 
209 
210  cloud3.get<int>( 0 ) = data;
211 
212  BOOST_CHECK_EQUAL( cloud3[0].x(), 1 );
213  BOOST_CHECK_EQUAL( cloud3.at<int>(0).get<int>(), 5 );
214 
215  cloud3.get<int>( 0 ) = PointCloud2Data<int>({2}, 4);
216 
217  BOOST_CHECK_EQUAL( cloud3[0].x(), 2 );
218  BOOST_CHECK_EQUAL( cloud3.at<int>(0).get<int>(), 4 );
219 
220  PointCloud2 cloud4( std::move( cloud3 ) ); // cloud3 no longer valid, attempting to access will likely crash
221  BOOST_CHECK_EQUAL( cloud4[0].x(), 2 );
222  BOOST_CHECK_EQUAL( cloud4.at<int>(0).get<int>(), 4 );
223 }
224 
225 struct dummyStruct
226 {
227  int x;
228 };
229 
230 // ######################################################################
231 BOOST_AUTO_TEST_CASE( InsertingStuffTests )
232 {
233  PointCloud2 cloudInsert = PointCloud2::create<int, bool, SparseField<double>>();
234 
235  // Insert valid stuff
236  cloudInsert.insert<int, bool, double>( {{3.0f}, 1, true, 3.2} );
237 
238  auto cloudInsertRef1 = cloudInsert.at<int, bool, double>( 0 );
239  BOOST_CHECK_EQUAL( cloudInsertRef1.geometry().x(), 3.0f );
240  BOOST_CHECK_EQUAL( cloudInsertRef1.get<int>(), 1 );
241  BOOST_CHECK_EQUAL( cloudInsertRef1.get<bool>(), true );
242  BOOST_CHECK_EQUAL( cloudInsertRef1.get<double>(), 3.2 );
243 
244  // Insert a non fully dense point
245  cloudInsert.insert( {2.9f} );
246  auto cloudInsertRef2 = cloudInsert.at<int, bool>( 1 );
247 
248  BOOST_CHECK_EQUAL( cloudInsertRef2.geometry().x(), 2.9f );
249  BOOST_CHECK_EQUAL( cloudInsertRef2.get<int>(), 0 );
250  BOOST_CHECK_EQUAL( cloudInsertRef2.get<bool>(), false );
251 
252  cloudInsert.addField<dummyStruct>();
253  cloudInsert.get<dummyStruct>( 0 ).get<dummyStruct>().x = 3;
254  BOOST_CHECK_EQUAL( cloudInsert.at<dummyStruct>( 0 ).get<dummyStruct>().x, 3 );
255 
256  bool tryResult = false;
257  try
258  {
259  // Should throw as there is no data here for sparse
260  cloudInsert.at<double>( 1 );
261  }
262  catch( std::exception const & e )
263  {
264  tryResult = true;
265  }
266 
267  BOOST_CHECK_EQUAL( tryResult, true );
268 
269  // add sparse data and check it
270  cloudInsert.insertSparse<double>( 1, {29.2} );
271  BOOST_CHECK_EQUAL( cloudInsert.at<double>( 1 ).get<double>(), 29.2 );
272 
273  // delete all data from a field
274  try
275  {
276  cloudInsert.at( 1 );
277  tryResult = false;
278  }
279  catch( std::exception const & e )
280  {
281  tryResult = true;
282  }
283 
284  BOOST_CHECK_EQUAL( cloudInsert.at<double>( 1 ).get<double>(), 29.2 );
285 
286  cloudInsert.resize( 0 );
287 
288  for( size_t i = 0; i < 100; ++i )
289  cloudInsert.insert({});
290 
291  BOOST_CHECK_EQUAL( cloudInsert.size(), 100 );
292  BOOST_CHECK_EQUAL( cloudInsert.size<double>(), 0 );
293 
294  cloudInsert.resize( 0 );
295 
296  BOOST_CHECK_EQUAL( cloudInsert.empty(), true );
297 
298  cloudInsert.insert( {1, 2, 3, 4} );
299  BOOST_CHECK_EQUAL( cloudInsert[0], cloudInsert.at( 0 ).geometry() );
300  BOOST_CHECK_EQUAL( PointCloud2::Geometry(1, 2, 3, 4), cloudInsert.get( 0 ).geometry() );
301 }
302 
303 //// bug in g++, the following should work but does not:
304 //template <bool Whatever>
305 //void testFunction( nrt::PointCloud2 const & cloud )
306 //{
307 // for( auto i : cloud.range<int>() )
308 // i.get<int>() = 0;
309 //}
310 
311 // ######################################################################
312 BOOST_AUTO_TEST_CASE( IteratorSchmiterator )
313 {
314  PointCloud2 cloud = PointCloud2::create<int, SparseField<double>>();
315 
316  // Populate with junk geometry
317  for( size_t i = 0; i < 1000; ++i )
318  cloud.insert<int>( {{(float)i}, (int)i} );
319 
320  int index = 0;
321  for( auto i = cloud.geometry_begin(), end = cloud.geometry_end(); i != end; ++i, ++index )
322  BOOST_CHECK_EQUAL( *i, PointCloud2::Geometry((float)index) );
323 
324  index = 0;
325  for( auto i = cloud.geometry_const_begin(), end = cloud.geometry_const_end(); i != end; ++i, ++index )
326  BOOST_CHECK_EQUAL( *i, PointCloud2::Geometry((float)index) );
327 
328  index = 0;
329  for( auto i = cloud.begin(), end = cloud.end(); i != end; ++i, ++index )
330  {
331  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry((float)index) );
332  BOOST_CHECK_EQUAL( i.index(), index );
333  }
334 
335  index = 0;
336  for( auto i = cloud.const_begin(), end = cloud.const_end(); i != end; ++i, ++index )
337  {
338  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry((float)index) );
339  BOOST_CHECK_EQUAL( i.index(), index );
340  }
341 
342  index = 0;
343  for( auto i : cloud.range() )
344  {
345  BOOST_CHECK_EQUAL( i.geometry(), PointCloud2::Geometry((float)index) );
346  index++;
347  }
348 
349  // iterating over a dense field
350  index = 0;
351  for( auto i = cloud.begin<int>(), end = cloud.end<int>(); i != end; ++i, ++index )
352  {
353  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry((float)index) );
354  BOOST_CHECK_EQUAL( i->get<int>(), index );
355  BOOST_CHECK_EQUAL( i.index(), index );
356  }
357 
358  index = 0;
359  for( auto i = cloud.const_begin<int>(), end = cloud.const_end<int>(); i != end; ++i, ++index )
360  {
361  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry((float)index) );
362  BOOST_CHECK_EQUAL( i->get<int>(), index );
363  BOOST_CHECK_EQUAL( i.index(), index );
364  }
365 
366  index = 0;
367  for( auto i : cloud.range<int>() )
368  {
369  BOOST_CHECK_EQUAL( i.geometry(), PointCloud2::Geometry((float)index) );
370  BOOST_CHECK_EQUAL( i.get<int>(), index );
371  index++;
372  }
373 
374  index = 0;
375  for( auto i : cloud.const_range<int>() )
376  {
377  BOOST_CHECK_EQUAL( i.geometry(), PointCloud2::Geometry((float)index) );
378  BOOST_CHECK_EQUAL( i.get<int>(), index );
379  index++;
380  }
381 
382  // error if field not there
383  bool ok = false;
384  try
385  {
386  cloud.begin<char>();
387  }
388  catch( ... )
389  {
390  ok = true;
391  }
392 
393  BOOST_CHECK_EQUAL( ok, true );
394 
395  // iterate over sparse data
396  cloud.insertSparse<double>( 5, {3.2} );
397  cloud.insertSparse<double>( 17, {4.2} );
398  cloud.insertSparse<double>( 33, {5.2} );
399  cloud.insertSparse<double>( 944, {6.2} );
400 
401  std::array<int, 4> indicesSparse = {{5, 17, 33, 944}};
402  std::array<double, 4> dataSparse = {{3.2, 4.2, 5.2, 6.2}};
403  index = 0;
404  for( auto i = cloud.begin<int, double>(), end = cloud.end<int, double>(); i != end; ++i, ++index )
405  {
406  BOOST_CHECK_EQUAL( i->get<double>(), dataSparse[index] );
407  BOOST_CHECK_EQUAL( i->get<int>(), indicesSparse[index] );
408  BOOST_CHECK_EQUAL( i.index(), indicesSparse[index] );
409  }
410 
411  index = 0;
412  for( auto i = cloud.const_begin<int, double>(), end = cloud.const_end<int, double>(); i != end; ++i, ++index )
413  {
414  BOOST_CHECK_EQUAL( i->get<double>(), dataSparse[index] );
415  BOOST_CHECK_EQUAL( i->get<int>(), indicesSparse[index] );
416  BOOST_CHECK_EQUAL( i.index(), indicesSparse[index] );
417  }
418 
419  index = 0;
420  for( auto i : cloud.range<int, double>() )
421  {
422  BOOST_CHECK_EQUAL( i.get<double>(), dataSparse[index] );
423  BOOST_CHECK_EQUAL( i.get<int>(), indicesSparse[index] );
424  ++index;
425  }
426 
427  index = 0;
428  for( auto i : cloud.const_range<int, double>() )
429  {
430  BOOST_CHECK_EQUAL( i.get<double>(), dataSparse[index] );
431  BOOST_CHECK_EQUAL( i.get<int>(), indicesSparse[index] );
432  ++index;
433  }
434 
435  Indices subset;
436  subset.push_back( 17 );
437  subset.push_back( 33 );
438 
439  index = 0;
440  for( auto i = cloud.subset_begin( subset ), end = cloud.subset_end( subset ); i != end; ++i, ++index )
441  {
442  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry( subset[index] ) );
443  BOOST_CHECK_EQUAL( i.index(), subset[index] );
444  }
445 
446  index = 0;
447  for( auto i = cloud.subset_const_begin( subset ), end = cloud.subset_const_end( subset ); i != end; ++i, ++index )
448  {
449  BOOST_CHECK_EQUAL( i->geometry(), PointCloud2::Geometry( subset[index] ) );
450  BOOST_CHECK_EQUAL( i.index(), subset[index] );
451  }
452 
453  index = 0;
454  for( auto i : cloud.subset_range( subset ) )
455  {
456  BOOST_CHECK_EQUAL( i.geometry(), PointCloud2::Geometry( subset[index] ) );
457  ++index;
458  }
459 
460  index = 0;
461  for( auto i : cloud.subset_const_range( subset ) )
462  {
463  BOOST_CHECK_EQUAL( i.geometry(), PointCloud2::Geometry( subset[index] ) );
464  ++index;
465  }
466 
467  index = 1;
468  for( auto i = cloud.subset_begin<int, double>( subset ), end = cloud.subset_end<int, double>( subset ); i != end; ++i, ++index )
469  {
470  BOOST_CHECK_EQUAL( i->get<double>(), dataSparse[index] );
471  BOOST_CHECK_EQUAL( i->get<int>(), indicesSparse[index] );
472  BOOST_CHECK_EQUAL( i.index(), indicesSparse[index] );
473  }
474 
475  index = 1;
476  for( auto i = cloud.subset_const_begin<int, double>( subset ), end = cloud.subset_const_end<int, double>( subset ); i != end; ++i, ++index )
477  {
478  BOOST_CHECK_EQUAL( i->get<double>(), dataSparse[index] );
479  BOOST_CHECK_EQUAL( i->get<int>(), indicesSparse[index] );
480  BOOST_CHECK_EQUAL( i.index(), indicesSparse[index] );
481  }
482 
483  index = 1;
484  for( auto i : cloud.subset_range<int, double>( subset ) )
485  {
486  BOOST_CHECK_EQUAL( i.get<double>(), dataSparse[index] );
487  BOOST_CHECK_EQUAL( i.get<int>(), indicesSparse[index] );
488  ++index;
489  }
490 
491  index = 1;
492  for( auto i : cloud.subset_const_range<int, double>( subset ) )
493  {
494  BOOST_CHECK_EQUAL( i.get<double>(), dataSparse[index] );
495  BOOST_CHECK_EQUAL( i.get<int>(), indicesSparse[index] );
496  ++index;
497  }
498 }
499 
500 // ######################################################################
501 BOOST_AUTO_TEST_CASE( ReferenceCountingStuff )
502 {
503  PointCloud2 cloud;
504  cloud.insert({1, 2, 3, 4});
505 
506  PointCloud2 cloud2 = cloud;
507 
508  BOOST_CHECK_EQUAL( cloud == cloud2, true );
509 
510  // const access
511  cloud2.at(0);
512  BOOST_CHECK_EQUAL( cloud == cloud2, true );
513 
514  // non const access triggers deep copy
515  cloud2.get(0);
516  BOOST_CHECK_EQUAL( cloud != cloud2, true );
517 
518  cloud2.get(0) = PointCloud2Data<>{{2, 3, 4, 5}};
519 
520  BOOST_CHECK_NE( cloud[0].x(), cloud2[0].x() );
521  BOOST_CHECK_EQUAL( cloud2[0].z(), 4 );
522  BOOST_CHECK_EQUAL( cloud[0].z(), 3 );
523 
524  PointCloud2 cloud3 = cloud2;
525  BOOST_CHECK_EQUAL( cloud3 == cloud2, true );
526  cloud3.deepCopy();
527  BOOST_CHECK_EQUAL( cloud3 != cloud2, true );
528 }
529 
530 // ######################################################################
531 BOOST_AUTO_TEST_CASE( AppendageTest )
532 {
533  PointCloud2 cloud1(10);
534 
535  float i = 0.0f;
536  for( auto & p : cloud1.geometry_range() )
537  {
538  p = {i};
539  i += 1.0f;
540  }
541 
542  PointCloud2 cloud2(11);
543  for( auto & p : cloud2.geometry_range() )
544  {
545  p = {i};
546  i += 1.0f;
547  }
548 
549  cloud1.append( cloud2 );
550 
551  i = 0.0f;
552  for( auto const & p : cloud1.geometry_const_range() )
553  {
554  BOOST_CHECK_EQUAL( p, PointCloud2::Geometry(i) );
555  i += 1.0f;
556  }
557 
558  cloud2.clear();
559  cloud2.resize(10);
560  cloud2.addField<int, SparseField<bool>>();
561  i = 0.0f;
562  for( auto p : cloud2.range<int>() )
563  {
564  p.geometry() = {i};
565  p.get<int>() = i;
566  i += 1.0f;
567  }
568 
569  cloud2.insertSparse<bool>( 0, {false} );
570  cloud2.insertSparse<bool>( 6, {true} );
571 
572  cloud2 = cloud2.append(cloud2);
573 
574  i = 0.0f;
575  for( auto p : cloud2.const_range<int>() )
576  {
577  BOOST_CHECK_EQUAL( p.geometry(), PointCloud2::Geometry{i} );
578  BOOST_CHECK_EQUAL( p.get<int>(), int(i) );
579  i += 1.0f;
580  if( i > 9.9f )
581  i = 0.0f;
582  }
583 
584  std::array<size_t, 4> goodIndices = {{0, 6, 10, 16}};
585  size_t index = 0;
586  for( auto i = cloud2.const_begin<bool>(), end = cloud2.const_end<bool>(); i != end; ++i )
587  BOOST_CHECK_EQUAL( i.index(), goodIndices[index++] );
588 }
589 
590 // ######################################################################
591 BOOST_AUTO_TEST_CASE( sadf )
592 {
593  nrt::PointCloud2 cloud;
594 
595  nrt::PointCloud2::Geometry geo( 0, 1, 2 );
596 
597  cloud.insert( geo );
598  cloud.insert( {1, 2, 3} );
599  cloud.insert( nrt::PointCloud2::Geometry( 4, 5, 6 ) );
600 }
601 
602 #else
603 int main( int argc, char ** argv )
604 {
605  return 1;
606 }
607 #endif // NRT_HAVE_CLOUD