lasreadpoint.cpp
Go to the documentation of this file.
1 /*
2 ===============================================================================
3 
4  FILE: lasreadpoint.cpp
5 
6  CONTENTS:
7 
8  see corresponding header file
9 
10  PROGRAMMERS:
11 
12  martin.isenburg@gmail.com
13 
14  COPYRIGHT:
15 
16  (c) 2011, Martin Isenburg, LASSO - tools to catch reality
17 
18  This is free software; you can redistribute and/or modify it under the
19  terms of the GNU Lesser General Licence as published by the Free Software
20  Foundation. See the COPYING file for more information.
21 
22  This software is distributed WITHOUT ANY WARRANTY and without even the
23  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 
25  CHANGE HISTORY:
26 
27  see corresponding header file
28 
29 ===============================================================================
30 */
31 
32 #include "lasreadpoint.hpp"
33 
34 #include "arithmeticdecoder.hpp"
35 #include "lasreaditemraw.hpp"
38 
39 #include <stdlib.h>
40 #include <string.h>
41 
43 {
44  point_size = 0;
45  instream = 0;
46  num_readers = 0;
47  readers = 0;
48  readers_raw = 0;
50  dec = 0;
51  // used for chunking
53  chunk_count = 0;
54  current_chunk = 0;
55  number_chunks = 0;
56  tabled_chunks = 0;
57  chunk_totals = 0;
58  chunk_starts = 0;
59  // used for seeking
60  point_start = 0;
61  seek_point = 0;
62 }
63 
64 BOOL LASreadPoint::setup(U32 num_items, const LASitem* items, const LASzip* laszip)
65 {
66  U32 i;
67 
68  // is laszip exists then we must use its items
69  if (laszip)
70  {
71  if (num_items != laszip->num_items) return FALSE;
72  if (items != laszip->items) return FALSE;
73  }
74 
75  // create entropy decoder (if requested)
76  dec = 0;
77  if (laszip && laszip->compressor)
78  {
79  switch (laszip->coder)
80  {
82  dec = new ArithmeticDecoder();
83  break;
84  default:
85  // entropy decoder not supported
86  return FALSE;
87  }
88  }
89 
90  // initizalize the readers
91  readers = 0;
92  num_readers = num_items;
93 
94  // disable chunking
96 
97  // always create the raw readers
99  for (i = 0; i < num_readers; i++)
100  {
101  switch (items[i].type)
102  {
103  case LASitem::POINT10:
104  if (IS_LITTLE_ENDIAN())
106  else
108  break;
109  case LASitem::GPSTIME11:
110  if (IS_LITTLE_ENDIAN())
112  else
114  break;
115  case LASitem::RGB12:
116  if (IS_LITTLE_ENDIAN())
118  else
120  break;
122  if (IS_LITTLE_ENDIAN())
124  else
126  break;
127  case LASitem::BYTE:
128  readers_raw[i] = new LASreadItemRaw_BYTE(items[i].size);
129  break;
130  case LASitem::POINT14:
131  if (IS_LITTLE_ENDIAN())
133  else
134  return FALSE;
135  break;
136  case LASitem::RGBNIR14:
137  if (IS_LITTLE_ENDIAN())
139  else
141  break;
142  default:
143  return FALSE;
144  }
145  point_size += items[i].size;
146  }
147 
148  if (dec)
149  {
151  // seeks with compressed data need a seek point
152  if (seek_point)
153  {
154  delete [] seek_point[0];
155  delete [] seek_point;
156  }
157  seek_point = new U8*[num_items];
158  if (!seek_point) return FALSE;
159  seek_point[0] = new U8[point_size];
160  if (!seek_point[0]) return FALSE;
161  for (i = 0; i < num_readers; i++)
162  {
163  switch (items[i].type)
164  {
165  case LASitem::POINT10:
166  if (items[i].version == 1)
168  else if (items[i].version == 2)
170  else
171  return FALSE;
172  break;
173  case LASitem::GPSTIME11:
174  if (items[i].version == 1)
176  else if (items[i].version == 2)
178  else
179  return FALSE;
180  break;
181  case LASitem::RGB12:
182  if (items[i].version == 1)
184  else if (items[i].version == 2)
186  else
187  return FALSE;
188  break;
190  if (items[i].version == 1)
192  else
193  return FALSE;
194  break;
195  case LASitem::BYTE:
196  if (items[i].version == 1)
197  readers_compressed[i] = new LASreadItemCompressed_BYTE_v1(dec, items[i].size);
198  else if (items[i].version == 2)
199  readers_compressed[i] = new LASreadItemCompressed_BYTE_v2(dec, items[i].size);
200  else
201  return FALSE;
202  break;
203  default:
204  return FALSE;
205  }
206  if (i) seek_point[i] = seek_point[i-1]+items[i-1].size;
207  }
209  {
210  if (laszip->chunk_size) chunk_size = laszip->chunk_size;
212  }
213  }
214  return TRUE;
215 }
216 
218 {
219  if (!instream) return FALSE;
220  this->instream = instream;
221 
222  // on very first init with chunking enabled
223  if (number_chunks == U32_MAX)
224  {
225  if (!read_chunk_table())
226  {
227  return FALSE;
228  }
229  current_chunk = 0;
231  }
232 
234 
235  U32 i;
236  for (i = 0; i < num_readers; i++)
237  {
239  }
240 
241  if (dec)
242  {
243  readers = 0;
244  }
245  else
246  {
248  }
249 
250  return TRUE;
251 }
252 
253 BOOL LASreadPoint::seek(const U32 current, const U32 target)
254 {
255  if (!instream->isSeekable()) return FALSE;
256  U32 delta = 0;
257  if (dec)
258  {
259  if (chunk_starts)
260  {
261  U32 target_chunk;
262  if (chunk_totals)
263  {
264  target_chunk = search_chunk_table(target, 0, number_chunks);
265  chunk_size = chunk_totals[target_chunk+1]-chunk_totals[target_chunk];
266  delta = target - chunk_totals[target_chunk];
267  }
268  else
269  {
270  target_chunk = target/chunk_size;
271  delta = target%chunk_size;
272  }
273  if (target_chunk >= tabled_chunks)
274  {
275  if (current_chunk < (tabled_chunks-1))
276  {
277  dec->done();
280  init(instream);
281  chunk_count = 0;
282  }
283  delta += (chunk_size*(target_chunk-current_chunk) - chunk_count);
284  }
285  else if (current_chunk != target_chunk || current > target)
286  {
287  dec->done();
288  current_chunk = target_chunk;
290  init(instream);
291  chunk_count = 0;
292  }
293  else
294  {
295  delta = target - current;
296  }
297  }
298  else if (current > target)
299  {
300  dec->done();
302  init(instream);
303  delta = target;
304  }
305  else if (current < target)
306  {
307  delta = target - current;
308  }
309  while (delta)
310  {
311  read(seek_point);
312  delta--;
313  }
314  }
315  else
316  {
317  if (current != target)
318  {
320  }
321  }
322  return TRUE;
323 }
324 
325 BOOL LASreadPoint::read(U8* const * point)
326 {
327  U32 i;
328 
329  try
330  {
331  if (dec)
332  {
333  if (chunk_count == chunk_size)
334  {
335  current_chunk++;
336  dec->done();
337  init(instream);
338  if (tabled_chunks == current_chunk) // no or incomplete chunk table?
339  {
341  {
342  number_chunks += 256;
343  chunk_starts = (I64*)realloc(chunk_starts, sizeof(I64)*number_chunks);
344  }
345  chunk_starts[tabled_chunks] = point_start; // needs fixing
346  tabled_chunks++;
347  }
348  else if (chunk_totals) // variable sized chunks?
349  {
351  }
352  chunk_count = 0;
353  }
354  chunk_count++;
355 
356  if (readers)
357  {
358  for (i = 0; i < num_readers; i++)
359  {
360  readers[i]->read(point[i]);
361  }
362  }
363  else
364  {
365  for (i = 0; i < num_readers; i++)
366  {
367  readers_raw[i]->read(point[i]);
368  ((LASreadItemCompressed*)(readers_compressed[i]))->init(point[i]);
369  }
371  dec->init(instream);
372  }
373  }
374  else
375  {
376  for (i = 0; i < num_readers; i++)
377  {
378  readers[i]->read(point[i]);
379  }
380  }
381  }
382  catch (...)
383  {
384  return FALSE;
385  }
386  return TRUE;
387 }
388 
390 {
392  {
393  if (dec) dec->done();
394  }
395  return TRUE;
396 }
397 
399 {
400  // read the 8 bytes that store the location of the chunk table
401  I64 chunk_table_start_position;
402  try { instream->get64bitsLE((U8*)&chunk_table_start_position); } catch(...)
403  {
404  return FALSE;
405  }
406 
407  // this is where the chunks start
408  I64 chunks_start = instream->tell();
409 
410  if ((chunk_table_start_position + 8) == chunks_start)
411  {
412  // then compressor was interrupted before getting a chance to write the chunk table
413  number_chunks = 256;
414  chunk_starts = (I64*)malloc(sizeof(I64)*number_chunks);
415  if (chunk_starts == 0)
416  {
417  return FALSE;
418  }
419  chunk_starts[0] = chunks_start;
420  tabled_chunks = 1;
421  return TRUE;
422  }
423 
424  if (!instream->isSeekable())
425  {
426  // if the stream is not seekable we cannot seek to the chunk table but won't need it anyways
427  tabled_chunks = 0;
428  return TRUE;
429  }
430 
431  if (chunk_table_start_position == -1)
432  {
433  // the compressor was writing to a non-seekable stream and wrote the chunk table start at the end
434  if (!instream->seekEnd(8))
435  {
436  return FALSE;
437  }
438  try { instream->get64bitsLE((U8*)&chunk_table_start_position); } catch(...)
439  {
440  return FALSE;
441  }
442  }
443 
444  // read the chunk table
445  try
446  {
447  instream->seek(chunk_table_start_position);
448  U32 version;
449  instream->get32bitsLE((U8*)&version);
450  if (version != 0)
451  {
452  throw;
453  }
455  if (chunk_totals) delete [] chunk_totals;
456  chunk_totals = 0;
457  if (chunk_starts) free(chunk_starts);
458  chunk_starts = 0;
459  if (chunk_size == U32_MAX)
460  {
461  chunk_totals = new U32[number_chunks+1];
462  if (chunk_totals == 0)
463  {
464  throw;
465  }
466  chunk_totals[0] = 0;
467  }
468  chunk_starts = (I64*)malloc(sizeof(I64)*(number_chunks+1));
469  if (chunk_starts == 0)
470  {
471  throw;
472  }
473  chunk_starts[0] = chunks_start;
474  tabled_chunks = 1;
475  if (number_chunks > 0)
476  {
477  U32 i;
478  dec->init(instream);
479  IntegerCompressor ic(dec, 32, 2);
480  ic.initDecompressor();
481  for (i = 1; i <= number_chunks; i++)
482  {
483  if (chunk_size == U32_MAX) chunk_totals[i] = ic.decompress((i>1 ? chunk_totals[i-1] : 0), 0);
484  chunk_starts[i] = ic.decompress((i>1 ? (U32)(chunk_starts[i-1]) : 0), 1);
485  tabled_chunks++;
486  }
487  dec->done();
488  for (i = 1; i <= number_chunks; i++)
489  {
490  if (chunk_size == U32_MAX) chunk_totals[i] += chunk_totals[i-1];
491  chunk_starts[i] += chunk_starts[i-1];
492  }
493  }
494  }
495  catch (...)
496  {
497  // something went wrong while reading the chunk table
498  if (chunk_totals) delete [] chunk_totals;
499  chunk_totals = 0;
500  // fix as many additional chunk_starts as possible
501  U32 i;
502  for (i = 1; i < tabled_chunks; i++)
503  {
504  chunk_starts[i] += chunk_starts[i-1];
505  }
506  }
507  if (!instream->seek(chunks_start))
508  {
509  return FALSE;
510  }
511  return TRUE;
512 }
513 
514 U32 LASreadPoint::search_chunk_table(const U32 index, const U32 lower, const U32 upper)
515 {
516  if (lower + 1 == upper) return lower;
517  U32 mid = (lower+upper)/2;
518  if (index >= chunk_totals[mid])
519  return search_chunk_table(index, mid, upper);
520  else
521  return search_chunk_table(index, lower, mid);
522 }
523 
525 {
526  U32 i;
527 
528  if (readers_raw)
529  {
530  for (i = 0; i < num_readers; i++)
531  {
532  delete readers_raw[i];
533  }
534  delete [] readers_raw;
535  }
536 
537  if (readers_compressed)
538  {
539  for (i = 0; i < num_readers; i++)
540  {
541  delete readers_compressed[i];
542  }
543  delete [] readers_compressed;
544  }
545 
546  if (dec)
547  {
548  delete dec;
549  }
550 
551  if (chunk_totals) delete [] chunk_totals;
552  if (chunk_starts) delete [] chunk_starts;
553 
554  if (seek_point)
555  {
556  delete [] seek_point[0];
557  delete [] seek_point;
558  }
559 }
LASreadPoint::LASreadPoint
LASreadPoint()
Definition: lasreadpoint.cpp:42
LASreadPoint::~LASreadPoint
~LASreadPoint()
Definition: lasreadpoint.cpp:524
ByteStreamIn::tell
virtual I64 tell() const =0
LASzip::num_items
unsigned short num_items
Definition: laszip.hpp:120
LASreadItemRaw_POINT14_LE
Definition: lasreaditemraw.hpp:201
LASreadPoint::chunk_starts
I64 * chunk_starts
Definition: lasreadpoint.hpp:75
LASreadItemCompressed_GPSTIME11_v1
Definition: lasreaditemcompressed_v1.hpp:69
ByteStreamIn::isSeekable
virtual BOOL isSeekable() const =0
LASreadPoint::seek
BOOL seek(const U32 current, const U32 target)
Definition: lasreadpoint.cpp:253
LASreadItemRaw_POINT10_LE
Definition: lasreaditemraw.hpp:39
LASreadItem::read
virtual void read(U8 *item)=0
EntropyDecoder::init
virtual BOOL init(ByteStreamIn *instream)=0
LASitem::POINT10
@ POINT10
Definition: laszip.hpp:73
ByteStreamIn::seekEnd
virtual BOOL seekEnd(const I64 distance=0)=0
LASreadItemRaw_WAVEPACKET13_BE
Definition: lasreaditemraw.hpp:125
LASreadPoint::instream
ByteStreamIn * instream
Definition: lasreadpoint.hpp:63
lasreaditemcompressed_v2.hpp
I64
long long I64
Definition: mydefs.hpp:48
LASreadPoint::dec
EntropyDecoder * dec
Definition: lasreadpoint.hpp:68
LASzip
Definition: laszip.hpp:80
LASreadItemRaw_POINT10_BE
Definition: lasreaditemraw.hpp:49
U32_MAX
#define U32_MAX
Definition: mydefs.hpp:75
LASreadPoint::seek_point
U8 ** seek_point
Definition: lasreadpoint.hpp:82
LASreadPoint::num_readers
U32 num_readers
Definition: lasreadpoint.hpp:64
LASZIP_COMPRESSOR_POINTWISE_CHUNKED
#define LASZIP_COMPRESSOR_POINTWISE_CHUNKED
Definition: laszip.hpp:55
TRUE
#define TRUE
Definition: mydefs.hpp:137
LASreadPoint::point_start
I64 point_start
Definition: lasreadpoint.hpp:80
lasreadpoint.hpp
LASreadItemCompressed
Definition: lasreaditem.hpp:65
LASZIP_CODER_ARITHMETIC
#define LASZIP_CODER_ARITHMETIC
Definition: laszip.hpp:63
LASzip::items
LASitem * items
Definition: laszip.hpp:121
LASitem::WAVEPACKET13
@ WAVEPACKET13
Definition: laszip.hpp:73
LASitem::POINT14
@ POINT14
Definition: laszip.hpp:73
LASreadItemRaw_GPSTIME11_BE
Definition: lasreaditemraw.hpp:77
lasreaditemraw.hpp
LASreadPoint::done
BOOL done()
Definition: lasreadpoint.cpp:389
ByteStreamIn::get64bitsLE
virtual void get64bitsLE(U8 *bytes)=0
LASreadPoint::tabled_chunks
U32 tabled_chunks
Definition: lasreadpoint.hpp:74
LASreadPoint::search_chunk_table
U32 search_chunk_table(const U32 index, const U32 lower, const U32 upper)
Definition: lasreadpoint.cpp:514
LASreadPoint::number_chunks
U32 number_chunks
Definition: lasreadpoint.hpp:73
LASreadItemCompressed_BYTE_v1
Definition: lasreaditemcompressed_v1.hpp:135
LASzip::chunk_size
unsigned int chunk_size
Definition: laszip.hpp:117
ArithmeticDecoder
Definition: arithmeticdecoder.hpp:39
LASreadItemRaw_RGBNIR14_LE
Definition: lasreaditemraw.hpp:252
LASreadPoint::setup
BOOL setup(const U32 num_items, const LASitem *items, const LASzip *laszip=0)
Definition: lasreadpoint.cpp:64
ByteStreamIn::seek
virtual BOOL seek(const I64 position)=0
LASreadPoint::readers
LASreadItem ** readers
Definition: lasreadpoint.hpp:65
LASzip::compressor
unsigned short compressor
Definition: laszip.hpp:111
LASitem
Definition: laszip.hpp:70
EntropyDecoder::done
virtual void done()=0
LASitem::RGB12
@ RGB12
Definition: laszip.hpp:73
ByteStreamIn::get32bitsLE
virtual void get32bitsLE(U8 *bytes)=0
LASreadItemRaw
Definition: lasreaditem.hpp:47
LASitem::size
unsigned short size
Definition: laszip.hpp:74
LASreadItemCompressed_WAVEPACKET13_v1
Definition: lasreaditemcompressed_v1.hpp:110
LASreadPoint::read
BOOL read(U8 *const *point)
Definition: lasreadpoint.cpp:325
LASreadPoint::read_chunk_table
BOOL read_chunk_table()
Definition: lasreadpoint.cpp:398
LASreadItemCompressed_POINT10_v2
Definition: lasreaditemcompressed_v2.hpp:40
ByteStreamIn
Definition: bytestreamin.hpp:36
LASreadItemRaw_GPSTIME11_LE
Definition: lasreaditemraw.hpp:67
LASreadPoint::readers_compressed
LASreadItem ** readers_compressed
Definition: lasreadpoint.hpp:67
LASreadItemCompressed_BYTE_v2
Definition: lasreaditemcompressed_v2.hpp:118
LASreadPoint::chunk_size
U32 chunk_size
Definition: lasreadpoint.hpp:70
LASreadPoint::readers_raw
LASreadItem ** readers_raw
Definition: lasreadpoint.hpp:66
U8
unsigned char U8
Definition: mydefs.hpp:41
BOOL
int BOOL
Definition: mydefs.hpp:57
LASreadItem
Definition: lasreaditem.hpp:39
FALSE
#define FALSE
Definition: mydefs.hpp:133
LASreadItemRaw_RGBNIR14_BE
Definition: lasreaditemraw.hpp:262
LASreadItemCompressed_RGB12_v2
Definition: lasreaditemcompressed_v2.hpp:94
LASreadPoint::current_chunk
U32 current_chunk
Definition: lasreadpoint.hpp:72
LASitem::GPSTIME11
@ GPSTIME11
Definition: laszip.hpp:73
LASitem::RGBNIR14
@ RGBNIR14
Definition: laszip.hpp:73
LASreadPoint::chunk_totals
U32 * chunk_totals
Definition: lasreadpoint.hpp:76
LASreadPoint::point_size
U32 point_size
Definition: lasreadpoint.hpp:81
LASreadPoint::init
BOOL init(ByteStreamIn *instream)
Definition: lasreadpoint.cpp:217
LASreadItemCompressed_POINT10_v1
Definition: lasreaditemcompressed_v1.hpp:39
LASitem::BYTE
@ BYTE
Definition: laszip.hpp:73
IS_LITTLE_ENDIAN
BOOL IS_LITTLE_ENDIAN()
Definition: mydefs.hpp:144
U32
unsigned int U32
Definition: mydefs.hpp:39
LASreadItemCompressed_GPSTIME11_v2
Definition: lasreaditemcompressed_v2.hpp:71
arithmeticdecoder.hpp
LASreadItemRaw_WAVEPACKET13_LE
Definition: lasreaditemraw.hpp:115
LASreadItemRaw_RGB12_BE
Definition: lasreaditemraw.hpp:100
LASreadPoint::chunk_count
U32 chunk_count
Definition: lasreadpoint.hpp:71
IntegerCompressor::decompress
I32 decompress(I32 iPred, U32 context=0)
Definition: integercompressor.cpp:319
IntegerCompressor::initDecompressor
void initDecompressor()
Definition: integercompressor.cpp:274
LASreadItemRaw_BYTE
Definition: lasreaditemraw.hpp:144
LASzip::coder
unsigned short coder
Definition: laszip.hpp:112
LASreadItemCompressed_RGB12_v1
Definition: lasreaditemcompressed_v1.hpp:91
lasreaditemcompressed_v1.hpp
LASreadItemRaw_RGB12_LE
Definition: lasreaditemraw.hpp:90
IntegerCompressor
Definition: integercompressor.hpp:53


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Wed Mar 2 2022 00:37:23