lasreader_qfit.cpp
Go to the documentation of this file.
1 /*
2 ===============================================================================
3 
4  FILE: lasreader_qfit.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) 2007-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 #include "lasreader_qfit.hpp"
32 
33 #include "bytestreamin.hpp"
34 #include "bytestreamin_file.hpp"
35 
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #ifdef _WIN32
40 #include <windows.h>
41 #endif
42 
43 BOOL LASreaderQFIT::open(const char* file_name)
44 {
45  if (file_name == 0)
46  {
47  fprintf(stderr,"ERROR: fine name pointer is zero\n");
48  return FALSE;
49  }
50 
51  // open file
52 
53  file = fopen(file_name, "rb");
54  if (file == 0)
55  {
56  fprintf(stderr, "ERROR: cannot open file '%s'\n", file_name);
57  return FALSE;
58  }
59 
60  // create input stream
61 
62  ByteStreamIn* in;
63  if (IS_LITTLE_ENDIAN())
64  in = new ByteStreamInFileLE(file);
65  else
66  in = new ByteStreamInFileBE(file);
67 
68  // clean header
69 
70  header.clean();
71 
72  // set projection
73 
74  LASvlr_key_entry geo_keys[4];
75 
76  // projected coordinates
77  geo_keys[0].key_id = 1024; // GTModelTypeGeoKey
78  geo_keys[0].tiff_tag_location = 0;
79  geo_keys[0].count = 1;
80  geo_keys[0].value_offset = 2; // ModelTypeGeographic
81 
82  // ellipsoid used with latitude/longitude coordinates
83  geo_keys[1].key_id = 2048; // GeographicTypeGeoKey
84  geo_keys[1].tiff_tag_location = 0;
85  geo_keys[1].count = 1;
86  geo_keys[1].value_offset = 4326; // GCS_WGS_84
87 
88  // vertical units
89  geo_keys[2].key_id = 4099; // VerticalUnitsGeoKey
90  geo_keys[2].tiff_tag_location = 0;
91  geo_keys[2].count = 1;
92  geo_keys[2].value_offset = 9001; // meter
93 
94  // vertical datum
95  geo_keys[3].key_id = 4096; // VerticalCSTypeGeoKey
96  geo_keys[3].tiff_tag_location = 0;
97  geo_keys[3].count = 1;
98  geo_keys[3].value_offset = 5030; // VertCS_WGS_84_ellipsoid
99 
100  header.set_geo_keys(4, geo_keys);
101 
102  // maybe set creation date
103 
104 #ifdef _WIN32
105  WIN32_FILE_ATTRIBUTE_DATA attr;
106  SYSTEMTIME creation;
107  GetFileAttributesEx(file_name, GetFileExInfoStandard, &attr);
108  FileTimeToSystemTime(&attr.ftCreationTime, &creation);
109  int startday[13] = {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
110  header.file_creation_day = startday[creation.wMonth] + creation.wDay;
111  header.file_creation_year = creation.wYear;
112  // leap year handling
113  if ((((creation.wYear)%4) == 0) && (creation.wMonth > 2)) header.file_creation_day++;
114 #else
116  header.file_creation_year = 2011;
117 #endif
118 
119  return open(in);
120 }
121 
123 {
124  U32 i;
125 
126  if (stream == 0)
127  {
128  fprintf(stderr,"ERROR: ByteStreamIn* pointer is zero\n");
129  return FALSE;
130  }
131 
132  this->stream = stream;
133 
134  // read the QFIT header
135 
136  try { stream->get32bitsLE((U8*)&version); } catch(...)
137  {
138  fprintf(stderr,"ERROR: reading QFIT header\n");
139  return FALSE;
140  }
141 
142  // is QFIT file little-endian
143 
144  if (version == 40 || version == 48 || version == 56)
145  {
148  }
149  else
150  {
152  if (version == 40 || version == 48 || version == 56)
153  {
156  }
157  else
158  {
159  fprintf(stderr,"ERROR: corrupt QFIT header.\n");
160  return FALSE;
161  }
162  }
163 
164  // read version bytes until point start offset
165 
166  try { stream->getBytes((U8*)buffer, version); } catch(...)
167  {
168  fprintf(stderr,"ERROR: reading %d bytes until point start offset from QFIT header\n", version);
169  return FALSE;
170  }
171 
172  // read point start offset
173 
174  try { if (little_endian) stream->get32bitsLE((U8*)&offset); else stream->get32bitsBE((U8*)&offset); } catch(...)
175  {
176  fprintf(stderr,"ERROR: reading point start offset from QFIT header\n");
177  return FALSE;
178  }
179 
180  // seek to end of file find out number of points
181 
182  stream->seekEnd();
183  npoints = (stream->tell() - offset) / version;
184 
185  // seek back to start of points
186 
187  stream->seek(offset);
188 
189  // populate the header as much as possible
190 
191  for (i = 0; i < 32; i++)
192  {
193  header.system_identifier[i] = '\0';
194  header.generating_software[i] = '\0';
195  }
196  sprintf(header.system_identifier, "LAStools (c) by Martin Isenburg");
197  sprintf(header.generating_software, "via LASreaderQFIT (%d)", LAS_TOOLS_VERSION);
198 
201 
204 
205  header.x_scale_factor = 0.000001;
206  header.y_scale_factor = 0.000001;
207  header.z_scale_factor = 0.001;
208  header.x_offset = 0;
209  header.y_offset = 0;
210  header.z_offset = 0;
211 
212  LASattribute scan_azimuth(LAS_ATTRIBUTE_I32, "scan azimuth", "Scan Azimuth (degrees X 1,000)");
213  scan_azimuth.set_scale(0.001);
214  scan_azimuth.set_min(0);
215  scan_azimuth.set_max(360000);
216 
217  header.add_extra_attribute(scan_azimuth);
218 
219  LASattribute pitch(LAS_ATTRIBUTE_I32, "pitch", "Pitch (degrees X 1,000)");
220  pitch.set_scale(0.001);
221  pitch.set_min(-90000);
222  pitch.set_max(90000);
223 
225 
226  LASattribute roll(LAS_ATTRIBUTE_I32, "roll", "Roll (degrees X 1,000)");
227  roll.set_scale(0.001);
228  roll.set_min(-90000);
229  roll.set_max(90000);
230 
232 
233  if (version == 48)
234  {
235  LASattribute pulse_width(LAS_ATTRIBUTE_U8, "pulse width", "Pulse Width (digitizer samples)");
236  header.add_extra_attribute(pulse_width);
237  }
238 
240 
241  // set point type
242 
245 
246  // initialize point
247 
249 
250  // initialize extra attribute offsets
251 
255  if (version == 48)
256  {
258  }
259 
260  // set point count to zero
261 
262  p_count = 0;
263 
264  // approximate bounding box init
265 
267 
268  if (!read_point()) return FALSE;
269 
273 
275  {
276  if (!seek(i)) return FALSE;
277  if (!read_point()) return FALSE;
278  }
279 
280  return seek(0);
281 }
282 
284 {
285  if (p_index < npoints)
286  {
287  p_count = p_index;
288  return stream->seek(p_index*version+offset);
289  }
290  return FALSE;
291 }
292 
294 {
295  if (p_count < npoints)
296  {
297  try { stream->getBytes((U8*)buffer, version); } catch(...)
298  {
299  fprintf(stderr,"ERROR: reading QFIT point after %u of %u\n", (U32)p_count, (U32)npoints);
300  return FALSE;
301  }
302 
303  if (endian_swap)
304  {
305  ENDIAN_SWAP_32((U8*)&buffer[0]);
306  ENDIAN_SWAP_32((U8*)&buffer[1]);
307  ENDIAN_SWAP_32((U8*)&buffer[2]);
308  ENDIAN_SWAP_32((U8*)&buffer[3]);
309  ENDIAN_SWAP_32((U8*)&buffer[5]);
310  ENDIAN_SWAP_32((U8*)&buffer[6]);
311  ENDIAN_SWAP_32((U8*)&buffer[7]);
312  ENDIAN_SWAP_32((U8*)&buffer[8]);
313  ENDIAN_SWAP_32((U8*)&buffer[9]);
314  if (version >= 48)
315  {
316  ENDIAN_SWAP_32((U8*)&buffer[10]);
317  ENDIAN_SWAP_32((U8*)&buffer[11]);
318  }
319  if (version >= 56)
320  {
321  ENDIAN_SWAP_32((U8*)&buffer[12]);
322  ENDIAN_SWAP_32((U8*)&buffer[13]);
323  }
324  }
325 
326  point.gps_time = 0.001*buffer[0];
327  point.x = buffer[2];
328  if (point.x > 180000000) point.x -= 360000000; // convert LARGE positive east longitude to negative
329  point.y = buffer[1];
330  point.z = buffer[3];
331  point.intensity = buffer[5];
332  point.scan_angle_rank = I8_CLAMP(I16_QUANTIZE((0.001*buffer[6])-180.0));
333 
338 
339  if (!populated_header)
340  {
342  // update bounding box
349  }
350 
351  p_count++;
352  return TRUE;
353  }
355  return FALSE;
356 }
357 
359 {
360  return stream;
361 }
362 
363 void LASreaderQFIT::close(BOOL close_stream)
364 {
365  if (close_stream)
366  {
367  if (stream)
368  {
369  delete stream;
370  stream = 0;
371  }
372  if (file)
373  {
374  fclose(file);
375  file = 0;
376  }
377  }
378 }
379 
380 BOOL LASreaderQFIT::reopen(const char* file_name)
381 {
382  if (file_name == 0)
383  {
384  fprintf(stderr,"ERROR: fine name pointer is zero\n");
385  return FALSE;
386  }
387 
388  // open file
389 
390  file = fopen(file_name, "rb");
391  if (file == 0)
392  {
393  fprintf(stderr, "ERROR: cannot open file '%s'\n", file_name);
394  return FALSE;
395  }
396 
397  // create input stream
398 
399  if (IS_LITTLE_ENDIAN())
401  else
403 
404  p_count = 0;
405 
406  return stream->seek(offset);
407 }
408 
410 {
411  file = 0;
412  stream = 0;
413  version = 0;
415  endian_swap = FALSE;
416  offset = 0;
419  pitch_array_offset = -1;
420  roll_array_offset = -1;
422 }
423 
425 {
426  if (stream) close();
427 }
428 
429 LASreaderQFITrescale::LASreaderQFITrescale(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor) : LASreaderQFIT()
430 {
431  scale_factor[0] = x_scale_factor;
432  scale_factor[1] = y_scale_factor;
433  scale_factor[2] = z_scale_factor;
434 }
435 
437 {
438  if (!LASreaderQFIT::open(stream)) return FALSE;
439  // do we need to change anything
441  {
443  }
445  {
447  }
449  {
451  }
452  return TRUE;
453 }
454 
456 {
457  this->offset[0] = x_offset;
458  this->offset[1] = y_offset;
459  this->offset[2] = z_offset;
460 }
461 
463 {
464  if (!LASreaderQFIT::open(stream)) return FALSE;
465  // do we need to change anything
466  if (header.x_offset != offset[0])
467  {
468  header.x_offset = offset[0];
469  }
470  if (header.y_offset != offset[1])
471  {
472  header.y_offset = offset[1];
473  }
474  if (header.z_offset != offset[2])
475  {
476  header.z_offset = offset[2];
477  }
478  return TRUE;
479 }
480 
481 LASreaderQFITrescalereoffset::LASreaderQFITrescalereoffset(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor, F64 x_offset, F64 y_offset, F64 z_offset) : LASreaderQFITrescale(x_scale_factor, y_scale_factor, z_scale_factor), LASreaderQFITreoffset(x_offset, y_offset, z_offset)
482 {
483 }
484 
486 {
487  if (!LASreaderQFIT::open(stream)) return FALSE;
488  // do we need to change anything
490  {
492  }
494  {
496  }
498  {
500  }
501  if (header.x_offset != offset[0])
502  {
503  header.x_offset = offset[0];
504  }
505  if (header.y_offset != offset[1])
506  {
507  header.y_offset = offset[1];
508  }
509  if (header.z_offset != offset[2])
510  {
511  header.z_offset = offset[2];
512  }
513  return TRUE;
514 }
BOOL IS_LITTLE_ENDIAN()
Definition: mydefs.hpp:144
#define LAS_ATTRIBUTE_U8
int BOOL
Definition: mydefs.hpp:57
#define FALSE
Definition: mydefs.hpp:133
U32 number_of_point_records
virtual I64 tell() const =0
U16 point_data_record_length
BOOL read_point()
Definition: lasreader.hpp:74
void close(BOOL close_stream=TRUE)
LASheader header
Definition: lasreader.hpp:52
void update_extra_bytes_vlr()
virtual ~LASreaderQFIT()
BOOL open(ByteStreamIn *stream)
ByteStreamIn * stream
LASpoint point
Definition: lasreader.hpp:53
void ENDIAN_SWAP_32(U8 *field)
Definition: mydefs.hpp:167
unsigned int U32
Definition: mydefs.hpp:39
I64 p_count
Definition: lasreader.hpp:56
#define LAS_ATTRIBUTE_I32
U64 extended_number_of_point_records
U16 key_id
virtual void get32bitsBE(U8 *bytes)=0
F64 get_y() const
I16 get_total_extra_attributes_size() const
void set_min(U8 *min, I32 dim=0)
I64 npoints
Definition: lasreader.hpp:55
const LASattributer * attributer
virtual BOOL seek(const I64 position)=0
BOOL init(const LASquantizer *quantizer, const U8 point_type, const U16 point_size, const LASattributer *attributer=0)
#define I8_CLAMP(n)
Definition: mydefs.hpp:96
long long I64
Definition: mydefs.hpp:48
F64 coordinates[3]
U64 extended_number_of_points_by_return[15]
U32 number_of_points_by_return[5]
I32 pulse_width_array_offset
unsigned char U8
Definition: mydefs.hpp:41
F64 get_x() const
BOOL read_point_default()
ByteStreamIn * get_stream() const
void set_extra_attribute(I32 index, const U8 *data)
virtual void getBytes(U8 *bytes, const U32 num_bytes)=0
I8 system_identifier[32]
U16 file_creation_year
U16 count
I32 scan_azimuth_array_offset
int I32
Definition: mydefs.hpp:35
void compute_coordinates()
BOOL set_scale(F64 scale, I32 dim=0)
virtual BOOL open(ByteStreamIn *stream)
LASreaderQFITrescale(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor)
void set_max(U8 *max, I32 dim=0)
BOOL seek(const I64 p_index)
#define I16_QUANTIZE(n)
Definition: mydefs.hpp:108
F64 get_z() const
virtual void get32bitsLE(U8 *bytes)=0
I32 add_extra_attribute(const LASattribute extra_attribute)
#define LAS_TOOLS_VERSION
U16 tiff_tag_location
LASreaderQFITrescalereoffset(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor, F64 x_offset, F64 y_offset, F64 z_offset)
#define TRUE
Definition: mydefs.hpp:137
void set_geo_keys(const I32 number_of_keys, const LASvlr_key_entry *geo_keys)
BOOL open(const char *file_name)
I32 get_extra_attribute_array_offset(const char *name) const
U16 value_offset
virtual BOOL seekEnd(const I64 distance=0)=0
LASreaderQFITreoffset(F64 x_offset, F64 y_offset, F64 z_offset)
virtual BOOL open(ByteStreamIn *stream)
BOOL reopen(const char *file_name)
I8 generating_software[32]
double F64
Definition: mydefs.hpp:52


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 Mon Feb 28 2022 22:46:07