1 // $Id$
2 //
3 // (C) Copyright Mateusz Loskot 2008, mateusz@loskot.net
4 // Distributed under the BSD License
5 // (See accompanying file LICENSE.txt or copy at
6 // http://www.opensource.org/licenses/bsd-license.php)
7 //
8 #include <liblas/liblas.hpp>
9 #include <liblas/detail/private_utility.hpp>
10 #include <tut/tut.hpp>
11 #include <algorithm>
12 #include <fstream>
13 #include <iterator>
14 #include <list>
15 #include "liblas_test.hpp"
16 #include "common.hpp"
17 using namespace liblas;
18 
19 namespace tut
20 {
21     struct lasreader_iterator_data
22     {
23         std::string file10_;
24         std::ifstream ifs_;
25         Reader reader_;
26 
lasreader_iterator_datatut::lasreader_iterator_data27         lasreader_iterator_data() :
28             file10_(g_test_data_path + "//TO_core_last_clip.las"),
29             ifs_(file10_.c_str(), std::ios::in | std::ios::binary),
30             reader_(ifs_)
31         {}
32     };
33 
34     typedef test_group<lasreader_iterator_data> tg;
35     typedef tg::object to;
36 
37     tg test_group_lasreader_iterator("liblas::lasreader_iterator");
38 
39     // Test default constructor
40     template<>
41     template<>
test()42     void to::test<1>()
43     {
44         lasreader_iterator it;
45     }
46 
47     // Test user-defined constructor
48     template<>
49     template<>
test()50     void to::test<2>()
51     {
52         lasreader_iterator it(reader_);
53     }
54 
55     // Test copy constructor with default initialized iterator
56     template<>
57     template<>
test()58     void to::test<3>()
59     {
60         lasreader_iterator it1;
61         lasreader_iterator it2(it1);
62 
63         ensure(it1 == it2);
64     }
65 
66     // Test copy constructor with initialized iterator
67     template<>
68     template<>
test()69     void to::test<4>()
70     {
71         lasreader_iterator it1(reader_);
72         lasreader_iterator it2(it1);
73 
74         ensure(it1 == it2);
75     }
76 
77     // Test assignment operator with default initialized iterator
78     template<>
79     template<>
test()80     void to::test<5>()
81     {
82         lasreader_iterator it1;
83         lasreader_iterator it2;
84         it1 = it2;
85 
86         ensure(it1 == it2);
87     }
88 
89     // Test assignment operator with initialized iterator
90     template<>
91     template<>
test()92     void to::test<6>()
93     {
94         lasreader_iterator it1(reader_);
95         lasreader_iterator it2;
96         it1 = it2;
97 
98         ensure(it1 == it2);
99     }
100 
101     // Test dereference operator
102     template<>
103     template<>
test()104     void to::test<7>()
105     {
106         lasreader_iterator it(reader_);
107 
108         test_file10_point1(*it);
109     }
110 
111     // Test pointer-to-member operator
112     template<>
113     template<>
test()114     void to::test<8>()
115     {
116         lasreader_iterator it(reader_);
117 
118         // test 1st point data record
119         ensure_distance(it->GetX(), double(630262.30), 0.0001);
120         ensure_distance(it->GetY(), double(4834500), 0.0001);
121         ensure_distance(it->GetZ(), double(51.53), 0.0001);
122         ensure_equals(it->GetIntensity(), 670);
123         ensure_equals(it->GetScanAngleRank(), 0);
124         ensure_equals(it->GetUserData(), 3);
125         ensure_equals(it->GetScanFlags(), 9);
126         ensure_distance(it->GetTime(), double(413665.23360000004), 0.0001);
127 
128         liblas::Classification c(1);
129         ensure_equals(it->GetClassification(), c);
130     }
131 
132     // Test pre-increment operator
133     template<>
134     template<>
test()135     void to::test<9>()
136     {
137         lasreader_iterator it(reader_); // move to 1st point
138         ++it; // move to 2nd record
139 
140         test_file10_point2(*it);
141     }
142 
143     // Test post-increment operator
144     template<>
145     template<>
test()146     void to::test<10>()
147     {
148         lasreader_iterator it(reader_); // move to 1st point
149         it++; // move to 2nd record
150 
151         test_file10_point2(*it);
152     }
153 
154     // Test equal-to operator
155     template<>
156     template<>
test()157     void to::test<11>()
158     {
159         lasreader_iterator it(reader_); // move to 1st point
160         lasreader_iterator end;
161 
162         ensure_not(end == it);
163     }
164 
165     // Test not-equal-to operator
166     template<>
167     template<>
test()168     void to::test<12>()
169     {
170         lasreader_iterator it(reader_); // move to 1st point
171         lasreader_iterator end;
172 
173         ensure(end != it);
174     }
175 
176     // Test iteration
177     template<>
178     template<>
test()179     void to::test<13>()
180     {
181         boost::uint32_t const cnt = reader_.GetHeader().GetPointRecordsCount();
182         lasreader_iterator it(reader_); // move to 1st point
183         lasreader_iterator end;
184 
185         boost::uint32_t s = 0;
186         while (end != it)
187         {
188             s++;
189             ++it;
190         }
191 
192         ensure_equals(cnt, s);
193     }
194 
195     // Test std::distance operation
196     template<>
197     template<>
test()198     void to::test<14>()
199     {
200         boost::uint32_t const cnt = reader_.GetHeader().GetPointRecordsCount();
201         lasreader_iterator it(reader_); // move to 1st point
202         lasreader_iterator end;
203 
204         typedef lasreader_iterator::difference_type difference_type;
205         difference_type const d = std::distance(it, end);
206         ensure_equals(d, static_cast<difference_type>(cnt));
207     }
208 
209     // Test std::distance operation
210     template<>
211     template<>
test()212     void to::test<15>()
213     {
214         typedef lasreader_iterator::difference_type difference_type;
215 
216         difference_type a = std::distance(lasreader_iterator(reader_), lasreader_iterator());
217 
218         // Reader state is set to "past-the-end-of-file"
219         // So, reset is needed
220         reader_.Reset();
221 
222         difference_type b = std::distance(lasreader_iterator(reader_), lasreader_iterator());
223 
224         ensure_equals(a, b);
225     }
226 
227     // Test std::advance operation
228     template<>
229     template<>
test()230     void to::test<16>()
231     {
232         lasreader_iterator it(reader_); // move to 1st point
233 
234         std::advance(it, 1); // move to 2nd record
235         test_file10_point2(*it);
236 
237         std::advance(it, 2); // move to 4th record
238         test_file10_point4(*it);
239     }
240 
241     // Test std::copy algorithm
242     template<>
243     template<>
test()244     void to::test<17>()
245     {
246         boost::uint32_t const size = reader_.GetHeader().GetPointRecordsCount();
247         lasreader_iterator it(reader_);
248         lasreader_iterator end;
249 
250         typedef std::list<Point> list_t;
251         typedef std::back_insert_iterator<list_t> inserter_t;
252         list_t cache;
253 
254         // Test copying LAS records to std::list based cache
255         std::copy(it, end, inserter_t(cache));
256         ensure_equals(cache.size(), size);
257 
258         // Test copied data
259         list_t::const_iterator cit = cache.begin(); // 1st element
260         std::advance(cit, 1); // move to 2nd element in cache
261         test_file10_point2(*cit);
262         std::advance(cit, 2); // move to 4th element in cache
263         test_file10_point4(*cit);
264     }
265 
266     // Test std::count algorithm
267     template<>
268     template<>
test()269     void to::test<18>()
270     {
271         // Construct copy of 2nd point record from tested file
272         Header h;
273         Point pt(&h);
274         h.SetScale(0.01, 0.01, 0.01);
275         pt.SetHeader(&h);
276         pt.SetCoordinates(630282.45, 4834500, 51.63);
277         pt.SetIntensity(350);
278         pt.SetClassification(1);
279         pt.SetScanAngleRank(0);
280         pt.SetUserData(3);
281         pt.SetScanFlags(9);
282         pt.SetTime(413665.52880000003);
283         ensure(pt.IsValid());
284         test_file10_point2(pt);
285 
286         lasreader_iterator it(reader_);
287         lasreader_iterator end;
288 
289         // Count records equal to given point object
290         typedef lasreader_iterator::difference_type difference_type;
291         difference_type const expected = 1;
292         difference_type n = std::count(it, end, pt);
293         ensure_equals(n, expected);
294     }
295 
296     // Test std::equal algorithm
297     template<>
298     template<>
test()299     void to::test<19>()
300     {
301         std::ifstream ifs(file10_.c_str(), std::ios::in | std::ios::binary);
302         Reader reader(ifs);
303 
304         // Copy LAS records to std::list based cache
305         typedef std::list<Point> list_t;
306         typedef std::back_insert_iterator<list_t> inserter_t;
307         list_t cache;
308         {
309             lasreader_iterator it(reader);
310             lasreader_iterator end;
311             ensure(it != end);
312 
313             std::copy(it, end, inserter_t(cache));
314             ensure_equals(cache.size(), reader.GetHeader().GetPointRecordsCount());
315         }
316 
317         // Reset reader to the beginning of LAS file
318         reader.Reset();
319 
320         // Compare LAS file with cache
321         {
322             lasreader_iterator it(reader);
323             lasreader_iterator end;
324             ensure(it != end);
325 
326             bool eq = std::equal(it, end, cache.begin());
327             ensure(eq);
328         }
329     }
330 
331     // Test std::find algorithm
332     template<>
333     template<>
test()334     void to::test<20>()
335     {
336         // Construct copy of 2nd point record from tested file
337         Header h;
338         Point pt(&h);
339         h.SetScale(0.01, 0.01, 0.01);
340         pt.SetHeader(&h);
341         pt.SetCoordinates(630282.45, 4834500, 51.63);
342         pt.SetIntensity(350);
343         pt.SetClassification(1);
344         pt.SetScanAngleRank(0);
345         pt.SetUserData(3);
346         pt.SetScanFlags(9);
347         pt.SetTime(413665.52880000003);
348         ensure(pt.IsValid());
349         test_file10_point2(pt);
350 
351         lasreader_iterator it(reader_);
352         lasreader_iterator end;
353 
354         // find 2nd point data record
355         lasreader_iterator fit;
356         fit = std::find(it, end, pt);
357         ensure(fit != end);
358         test_file10_point2(*fit);
359     }
360 
361     // Test std::find_if algorithm
362     template<>
363     template<>
test()364     void to::test<21>()
365     {
366         lasreader_iterator it(reader_);
367         lasreader_iterator end;
368 
369         // find 2nd point data record comparing XY coordinates
370         lasreader_iterator fit;
371         fit = std::find_if(it, end, is_xy(630282.45, 4834500, 0.0001));
372         ensure(fit != end);
373         test_file10_point2(*fit);
374     }
375 
376     // Test std::for_each algorithm
377     template<>
378     template<>
test()379     void to::test<22>()
380     {
381         lasreader_iterator it(reader_);
382         lasreader_iterator end;
383 
384         typedef liblas::Bounds<double> bbox_t;
385 
386         Header const& h = reader_.GetHeader();
387         bbox_t lasbbox = h.GetExtent();
388 
389         // Accumulate points extents to common bounding box
390         bbox_t accumulated;
391         std::for_each(it, end, bbox_calculator(accumulated));
392 
393         ensure(lasbbox == accumulated);
394     }
395 }
396