lasreader_txt.cpp
Go to the documentation of this file.
1 /*
2 ===============================================================================
3 
4  FILE: lasreader_txt.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_txt.hpp"
32 
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #ifdef _WIN32
37 #include <windows.h>
38 #endif
39 
40 extern "C" FILE* fopen_compressed(const char* filename, const char* mode, bool* piped);
41 
42 BOOL LASreaderTXT::open(const char* file_name, const char* parse_string, I32 skip_lines, BOOL populate_header)
43 {
44  int i;
45 
46  if (file_name == 0)
47  {
48  fprintf(stderr,"ERROR: fine name pointer is zero\n");
49  return FALSE;
50  }
51 
52  clean();
53 
54  file = fopen_compressed(file_name, "r", &piped);
55  if (file == 0)
56  {
57  fprintf(stderr, "ERROR: cannot open file '%s'\n", file_name);
58  return FALSE;
59  }
60 
61  header.clean();
62 
63  // add extra attributes
64 
66  {
67  for (i = 0; i < number_extra_attributes; i++)
68  {
69  I32 type = (extra_attributes_data_types[i]-1)%10;
70  I32 dim = (extra_attributes_data_types[i]-1)/10 + 1;
71  LASattribute extra_attribute(type, extra_attribute_names[i], extra_attribute_descriptions[i], dim);
72  if (extra_attribute_scales[i] != 1.0)
73  {
74  for (I32 d = 0; d < dim; d++)
75  extra_attribute.set_scale(extra_attribute_scales[i], d);
76  }
77  if (extra_attribute_offsets[i] != 0.0)
78  {
79  for (I32 d = 0; d < dim; d++)
80  extra_attribute.set_offset(extra_attribute_offsets[i], d);
81  }
82  header.add_extra_attribute(extra_attribute);
83  }
84  }
85 
86  if (parse_string && !check_parse_string(parse_string))
87  {
88  return FALSE;
89  }
90 
91  // populate the header as much as it makes sense
92 
93  for (i = 0; i < 32; i++)
94  {
95  header.system_identifier[i] = '\0';
96  header.generating_software[i] = '\0';
97  }
98  sprintf(header.system_identifier, "LAStools (c) by Martin Isenburg");
99  sprintf(header.generating_software, "via LASreaderTXT (%d)", LAS_TOOLS_VERSION);
100 
101  // maybe set creation date
102 
103 #ifdef _WIN32
104  WIN32_FILE_ATTRIBUTE_DATA attr;
105  SYSTEMTIME creation;
106  GetFileAttributesEx(file_name, GetFileExInfoStandard, &attr);
107  FileTimeToSystemTime(&attr.ftCreationTime, &creation);
108  int startday[13] = {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
109  header.file_creation_day = startday[creation.wMonth] + creation.wDay;
110  header.file_creation_year = creation.wYear;
111  // leap year handling
112  if ((((creation.wYear)%4) == 0) && (creation.wMonth > 2)) header.file_creation_day++;
113 #else
115  header.file_creation_year = 2011;
116 #endif
117  if (parse_string)
118  {
119  if (strstr(parse_string,"t"))
120  {
121  if (strstr(parse_string,"R") || strstr(parse_string,"G") || strstr(parse_string,"B"))
122  {
125  }
126  else
127  {
130  }
131  }
132  else
133  {
134  if (strstr(parse_string,"R") || strstr(parse_string,"G") || strstr(parse_string,"B"))
135  {
138  }
139  else
140  {
143  }
144  }
145  }
146  else
147  {
150  }
151 
152  // maybe extra attributes
153 
155  {
158  }
159 
160  // initialize point
161 
163 
164  // we do not know yet how many points to expect
165 
166  npoints = 0;
167 
168  // should we perform an extra pass to fully populate the header
169 
170  if (populate_header)
171  {
172  // create a cheaper parse string that only looks for 'x' 'y' 'z' 'r' and extra attributes
173 
174  char* parse_less;
175  if (parse_string == 0)
176  {
177  parse_less = strdup("xyz");
178  }
179  else
180  {
181  parse_less = strdup(parse_string);
182  for (i = 0; i < (int)strlen(parse_string); i++)
183  {
184  if (parse_less[i] != 'x' && parse_less[i] != 'y' && parse_less[i] != 'z' && parse_less[i] != 'r' && (parse_less[i] < '0' || parse_less[i] > '0'))
185  {
186  parse_less[i] = 's';
187  }
188  }
189  do
190  {
191  parse_less[i] = '\0';
192  i--;
193  } while (parse_less[i] == 's');
194  }
195 
196  // skip lines if we have to
197  char* fg_skip;
198  for (i = 0; i < skip_lines; i++) fg_skip = fgets(line, 512, file);
199 
200  // read the first line
201 
202  while (fgets(line, 512, file))
203  {
204  if (parse(parse_less))
205  {
206  // mark that we found the first point
207  npoints++;
208  // we can stop this loop
209  break;
210  }
211  else
212  {
213  line[strlen(line)-1] = '\0';
214  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, parse_less);
215  }
216  }
217 
218  // did we manage to parse a line
219 
220  if (npoints == 0)
221  {
222  fprintf(stderr, "ERROR: could not parse any lines with '%s'\n", parse_less);
223  fclose(file);
224  file = 0;
225  free(parse_less);
226  return FALSE;
227  }
228 
229  // init the bounding box
230 
234 
235  // create return histogram
236 
238 
239  // init the min and max of extra attributes
240 
242  {
243  for (i = 0; i < number_extra_attributes; i++)
244  {
247  }
248  }
249 
250  // loop over the remaining lines
251 
252  while (fgets(line, 512, file))
253  {
254  if (parse(parse_less))
255  {
256  // count points
257  npoints++;
258  // create return histogram
260  // update bounding box
267  // update the min and max of extra attributes
269  {
270  for (i = 0; i < number_extra_attributes; i++)
271  {
274  }
275  }
276  }
277  else
278  {
279  line[strlen(line)-1] = '\0';
280  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, parse_less);
281  }
282  }
284  free(parse_less);
285 
286  // close the input file
287 
288  fclose(file);
289 
290  // populate scale and offset
291 
293 
294  // populate bounding box
295 
297 
298  // mark that header is already populated
299 
301 
302  // reopen input file for the second pass
303 
304  file = fopen_compressed(file_name, "r", &piped);
305  if (file == 0)
306  {
307  fprintf(stderr, "ERROR: could not open '%s' for second pass\n", file_name);
308  return FALSE;
309  }
310  }
311 
312  if (parse_string == 0)
313  {
314  this->parse_string = strdup("xyz");
315  }
316  else
317  {
318  this->parse_string = strdup(parse_string);
319  }
320 
321  // skip lines if we have to
322  char* fg_skip;
323  for (i = 0; i < skip_lines; i++) fg_skip = fgets(line, 512, file);
324  this->skip_lines = skip_lines;
325 
326  // read the first line with full parse_string
327 
328  i = 0;
329  while (fgets(line, 512, file))
330  {
331  if (parse(this->parse_string))
332  {
333  // mark that we found the first point
334  i = 1;
335  break;
336  }
337  else
338  {
339  line[strlen(line)-1] = '\0';
340  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, this->parse_string);
341  }
342  }
343 
344  // did we manage to parse a line
345 
346  if (i != 1)
347  {
348  fprintf(stderr, "ERROR: could not parse any lines with '%s'\n", this->parse_string);
349  fclose(file);
350  file = 0;
351  free(this->parse_string);
352  this->parse_string = 0;
353  return FALSE;
354  }
355 
356  if (!populated_header)
357  {
358  // init the bounding box that we will incrementally compute
359 
363 
364  // init the min and max of extra attributes
365 
367  {
368  for (i = 0; i < number_extra_attributes; i++)
369  {
372  }
373  }
374 
375  // set scale and offset
376 
378  }
379 
380  p_count = 0;
381 
382  return TRUE;
383 }
384 
386 {
387  this->translate_intensity = translate_intensity;
388 }
389 
391 {
392  this->scale_intensity = scale_intensity;
393 }
394 
396 {
397  this->translate_scan_angle = translate_scan_angle;
398 }
399 
401 {
402  this->scale_scan_angle = scale_scan_angle;
403 }
404 
406 {
407  if (scale_factor)
408  {
409  if (this->scale_factor == 0) this->scale_factor = new F64[3];
410  this->scale_factor[0] = scale_factor[0];
411  this->scale_factor[1] = scale_factor[1];
412  this->scale_factor[2] = scale_factor[2];
413  }
414  else if (this->scale_factor)
415  {
416  delete [] this->scale_factor;
417  this->scale_factor = 0;
418  }
419 }
420 
422 {
423  if (offset)
424  {
425  if (this->offset == 0) this->offset = new F64[3];
426  this->offset[0] = offset[0];
427  this->offset[1] = offset[1];
428  this->offset[2] = offset[2];
429  }
430  else if (this->offset)
431  {
432  delete [] this->offset;
433  this->offset = 0;
434  }
435 }
436 
437 void LASreaderTXT::add_extra_attribute(I32 data_type, const char* name, const char* description, F64 scale, F64 offset)
438 {
440  if (name)
441  {
443  }
444  else
445  {
446  char temp[32];
447  sprintf(temp, "attribute %d", number_extra_attributes);
449  }
450  if (description)
451  {
453  }
454  else
455  {
457  }
461 }
462 
464 {
465  U32 delta = 0;
466  if (p_index > p_count)
467  {
468  delta = (U32)(p_index - p_count);
469  }
470  else if (p_index < p_count)
471  {
472  if (piped) return FALSE;
473  fseek(file, 0, SEEK_SET);
474  // skip lines if we have to
475  int i;
476  char* fg_skip;
477  for (i = 0; i < skip_lines; i++) fg_skip = fgets(line, 512, file);
478  // read the first line with full parse_string
479  i = 0;
480  while (fgets(line, 512, file))
481  {
482  if (parse(this->parse_string))
483  {
484  // mark that we found the first point
485  i = 1;
486  break;
487  }
488  else
489  {
490  line[strlen(line)-1] = '\0';
491  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, this->parse_string);
492  }
493  }
494  // did we manage to parse a line
495  if (i != 1)
496  {
497  fprintf(stderr, "ERROR: could not parse any lines with '%s'\n", this->parse_string);
498  fclose(file);
499  file = 0;
500  free(this->parse_string);
501  this->parse_string = 0;
502  return FALSE;
503  }
504  delta = (U32)p_index;
505  }
506  while (delta)
507  {
509  delta--;
510  }
511  p_count = p_index;
512  return TRUE;
513 }
514 
516 {
517  if (p_count)
518  {
519  while (true)
520  {
521  if (fgets(line, 512, file))
522  {
523  if (parse(parse_string))
524  {
525  break;
526  }
527  else
528  {
529  line[strlen(line)-1] = '\0';
530  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, this->parse_string);
531  }
532  }
533  else
534  {
535  if (npoints)
536  {
537  if (p_count != npoints)
538  {
539 #ifdef _WIN32
540  fprintf(stderr,"WARNING: end-of-file after %I64d of %I64d points\n", p_count, npoints);
541 #else
542  fprintf(stderr,"WARNING: end-of-file after %lld of %lld points\n", p_count, npoints);
543 #endif
544  }
545  }
546  else
547  {
548  npoints = p_count;
550  }
551  return FALSE;
552  }
553  }
554  }
555  // compute the quantized x, y, and z values
559  p_count++;
560  if (!populated_header)
561  {
562  // update number of point records
564  // create return histogram
566  // update bounding box
573  // update the min and max of extra attributes
575  {
576  for (I32 i = 0; i < number_extra_attributes; i++)
577  {
580  }
581  }
582  }
583  return TRUE;
584 }
585 
587 {
588  return 0;
589 }
590 
591 void LASreaderTXT::close(BOOL close_stream)
592 {
593  if (file)
594  {
595  if (piped) while(fgets(line, 512, file));
596  fclose(file);
597  file = 0;
598  }
599 }
600 
601 BOOL LASreaderTXT::reopen(const char* file_name)
602 {
603  int i;
604 
605  if (file_name == 0)
606  {
607  fprintf(stderr,"ERROR: fine name pointer is zero\n");
608  return FALSE;
609  }
610 
611  file = fopen_compressed(file_name, "r", &piped);
612  if (file == 0)
613  {
614  fprintf(stderr, "ERROR: cannot reopen file '%s'\n", file_name);
615  return FALSE;
616  }
617 
618  // skip lines if we have to
619  char* fg_res;
620  for (i = 0; i < skip_lines; i++) fg_res = fgets(line, 512, file);
621 
622  // read the first line with full parse_string
623 
624  i = 0;
625  while (fgets(line, 512, file))
626  {
627  if (parse(parse_string))
628  {
629  // mark that we found the first point
630  i = 1;
631  break;
632  }
633  else
634  {
635  line[strlen(line)-1] = '\0';
636  fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n", line, parse_string);
637  }
638  }
639 
640  // did we manage to parse a line
641 
642  if (i != 1)
643  {
644  fprintf(stderr, "ERROR: could not parse any lines with '%s'\n", parse_string);
645  fclose(file);
646  file = 0;
647  return FALSE;
648  }
649 
650  p_count = 0;
651 
652  return TRUE;
653 }
654 
656 {
657  if (file)
658  {
659  fclose(file);
660  file = 0;
661  }
662  if (parse_string)
663  {
664  free(parse_string);
665  parse_string = 0;
666  }
667  skip_lines = 0;
669 }
670 
672 {
673  file = 0;
674  piped = false;
675  parse_string = 0;
676  scale_factor = 0;
677  offset = 0;
678  translate_intensity = 0.0f;
679  scale_intensity = 1.0f;
680  translate_scan_angle = 0.0f;
681  scale_scan_angle = 1.0f;
683  clean();
684 }
685 
687 {
688  clean();
689  if (scale_factor)
690  {
691  delete [] scale_factor;
692  scale_factor = 0;
693  }
694  if (offset)
695  {
696  delete [] offset;
697  offset = 0;
698  }
699 }
700 
702 {
703  if (index >= header.number_extra_attributes)
704  {
705  return FALSE;
706  }
707  if (header.extra_attributes[index].data_type == 1)
708  {
709  I32 temp_i;
710  if (header.extra_attributes[index].has_scale())
711  {
712  F64 temp_d;
713  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
714  temp_i = I32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
715  }
716  else
717  {
718  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
719  }
720  if (temp_i < U8_MIN || temp_i > U8_MAX)
721  {
722  fprintf(stderr, "WARNING: extra attribute %d of type U8 is %d. clamped to [%d %d] range.\n", index, temp_i, U8_MIN, U8_MAX);
724  }
725  else
726  {
728  }
729  }
730  else if (header.extra_attributes[index].data_type == 2)
731  {
732  I32 temp_i;
733  if (header.extra_attributes[index].has_scale())
734  {
735  F64 temp_d;
736  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
737  temp_i = I32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
738  }
739  else
740  {
741  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
742  }
743  if (temp_i < I8_MIN || temp_i > I8_MAX)
744  {
745  fprintf(stderr, "WARNING: extra attribute %d of type I8 is %d. clamped to [%d %d] range.\n", index, temp_i, I8_MIN, I8_MAX);
747  }
748  else
749  {
751  }
752  }
753  else if (header.extra_attributes[index].data_type == 3)
754  {
755  I32 temp_i;
756  if (header.extra_attributes[index].has_scale())
757  {
758  F64 temp_d;
759  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
760  temp_i = I32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
761  }
762  else
763  {
764  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
765  }
766  if (temp_i < U16_MIN || temp_i > U16_MAX)
767  {
768  fprintf(stderr, "WARNING: extra attribute %d of type U16 is %d. clamped to [%d %d] range.\n", index, temp_i, U16_MIN, U16_MAX);
770  }
771  else
772  {
774  }
775  }
776  else if (header.extra_attributes[index].data_type == 4)
777  {
778  I32 temp_i;
779  if (header.extra_attributes[index].has_scale())
780  {
781  F64 temp_d;
782  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
783  temp_i = I32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
784  }
785  else
786  {
787  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
788  }
789  if (temp_i < I16_MIN || temp_i > I16_MAX)
790  {
791  fprintf(stderr, "WARNING: extra attribute %d of type I16 is %d. clamped to [%d %d] range.\n", index, temp_i, I16_MIN, I16_MAX);
793  }
794  else
795  {
797  }
798  }
799  else if (header.extra_attributes[index].data_type == 5)
800  {
801  U32 temp_u;
802  if (header.extra_attributes[index].has_scale())
803  {
804  F64 temp_d;
805  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
806  temp_u = U32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
807  }
808  else
809  {
810  if (sscanf(l, "%u", &temp_u) != 1) return FALSE;
811  }
813  }
814  else if (header.extra_attributes[index].data_type == 6)
815  {
816  I32 temp_i;
817  if (header.extra_attributes[index].has_scale())
818  {
819  F64 temp_d;
820  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
821  temp_i = I32_QUANTIZE(temp_d/header.extra_attributes[index].scale[0]);
822  }
823  else
824  {
825  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
826  }
827  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
829  }
830  else if (header.extra_attributes[index].data_type == 9)
831  {
832  F32 temp_f;
833  if (sscanf(l, "%f", &temp_f) != 1) return FALSE;
835  }
836  else if (header.extra_attributes[index].data_type == 10)
837  {
838  F64 temp_d;
839  if (sscanf(l, "%lf", &temp_d) != 1) return FALSE;
841  }
842  else
843  {
844  fprintf(stderr, "WARNING: extra attribute %d not (yet) implemented.\n", index);
845  return FALSE;
846  }
847  return TRUE;
848 }
849 
851 {
852  I32 temp_i;
853  F32 temp_f;
854  const char* p = parse_string;
855  const char* l = line;
856 
857  while (p[0])
858  {
859  if (p[0] == 'x') // we expect the x coordinate
860  {
861  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
862  if (l[0] == 0) return FALSE;
863  if (sscanf(l, "%lf", &(point.coordinates[0])) != 1) return FALSE;
864  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
865  }
866  else if (p[0] == 'y') // we expect the y coordinate
867  {
868  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
869  if (l[0] == 0) return FALSE;
870  if (sscanf(l, "%lf", &(point.coordinates[1])) != 1) return FALSE;
871  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
872  }
873  else if (p[0] == 'z') // we expect the x coordinate
874  {
875  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
876  if (l[0] == 0) return FALSE;
877  if (sscanf(l, "%lf", &(point.coordinates[2])) != 1) return FALSE;
878  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
879  }
880  else if (p[0] == 't') // we expect the gps time
881  {
882  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
883  if (l[0] == 0) return FALSE;
884  if (sscanf(l, "%lf", &(point.gps_time)) != 1) return FALSE;
885  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
886  }
887  else if (p[0] == 'R') // we expect the red channel of the RGB field
888  {
889  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
890  if (l[0] == 0) return FALSE;
891  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
892  point.rgb[0] = (short)temp_i;
893  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
894  }
895  else if (p[0] == 'G') // we expect the green channel of the RGB field
896  {
897  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
898  if (l[0] == 0) return FALSE;
899  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
900  point.rgb[1] = (short)temp_i;
901  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
902  }
903  else if (p[0] == 'B') // we expect the blue channel of the RGB field
904  {
905  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
906  if (l[0] == 0) return FALSE;
907  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
908  point.rgb[2] = (short)temp_i;
909  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
910  }
911  else if (p[0] == 's') // we expect a string or a number that we don't care about
912  {
913  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
914  if (l[0] == 0) return FALSE;
915  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
916  }
917  else if (p[0] == 'i') // we expect the intensity
918  {
919  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
920  if (l[0] == 0) return FALSE;
921  if (sscanf(l, "%f", &temp_f) != 1) return FALSE;
922  if (translate_intensity != 0.0f) temp_f = temp_f+translate_intensity;
923  if (scale_intensity != 1.0f) temp_f = temp_f*scale_intensity;
924  if (temp_f < 0.0f || temp_f >= 65535.5f) fprintf(stderr, "WARNING: intensity %g is out of range of unsigned short\n", temp_f);
925  point.intensity = (unsigned short)(temp_f+0.5f);
926  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
927  }
928  else if (p[0] == 'a') // we expect the scan angle
929  {
930  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
931  if (l[0] == 0) return FALSE;
932  if (sscanf(l, "%f", &temp_f) != 1) return FALSE;
933  if (translate_scan_angle != 0.0f) temp_f = temp_f+translate_scan_angle;
934  if (scale_scan_angle != 1.0f) temp_f = temp_f*scale_scan_angle;
935  if (temp_f < -128.0f || temp_f > 127.0f) fprintf(stderr, "WARNING: scan angle %g is out of range of char\n", temp_f);
936  point.scan_angle_rank = (char)temp_f;
937  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
938  }
939  else if (p[0] == 'n') // we expect the number of returns of given pulse
940  {
941  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
942  if (l[0] == 0) return FALSE;
943  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
944  if (temp_i < 0 || temp_i > 7) fprintf(stderr, "WARNING: return number %d is out of range of three bits\n", temp_i);
946  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
947  }
948  else if (p[0] == 'r') // we expect the number of the return
949  {
950  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
951  if (l[0] == 0) return FALSE;
952  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
953  if (temp_i < 0 || temp_i > 7) fprintf(stderr, "WARNING: return number %d is out of range of three bits\n", temp_i);
954  point.return_number = temp_i & 7;
955  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
956  }
957  else if (p[0] == 'c') // we expect the classification
958  {
959  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
960  if (l[0] == 0) return FALSE;
961  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
962  if (temp_i < 0 || temp_i > 255) fprintf(stderr, "WARNING: classification %d is out of range of unsigned char\n", temp_i);
963  point.classification = (unsigned char)temp_i;
964  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
965  }
966  else if (p[0] == 'u') // we expect the user data
967  {
968  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
969  if (l[0] == 0) return FALSE;
970  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
971  if (temp_i < 0 || temp_i > 255) fprintf(stderr, "WARNING: user data %d is out of range of unsigned char\n", temp_i);
972  point.user_data = temp_i & 255;
973  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
974  }
975  else if (p[0] == 'p') // we expect the point source ID
976  {
977  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
978  if (l[0] == 0) return FALSE;
979  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
980  if (temp_i < 0 || temp_i > 65535) fprintf(stderr, "WARNING: point source ID %d is out of range of unsigned short\n", temp_i);
981  point.point_source_ID = temp_i & 65535;
982  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
983  }
984  else if (p[0] == 'e') // we expect the edge of flight line flag
985  {
986  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
987  if (l[0] == 0) return FALSE;
988  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
989  if (temp_i < 0 || temp_i > 1) fprintf(stderr, "WARNING: edge of flight line flag %d is out of range of boolean flag\n", temp_i);
990  point.edge_of_flight_line = (temp_i ? 1 : 0);
991  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
992  }
993  else if (p[0] == 'd') // we expect the direction of scan flag
994  {
995  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
996  if (l[0] == 0) return FALSE;
997  if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
998  if (temp_i < 0 || temp_i > 1) fprintf(stderr, "WARNING: direction of scan flag %d is out of range of boolean flag\n", temp_i);
999  point.scan_direction_flag = (temp_i ? 1 : 0);
1000  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
1001  }
1002  else if (p[0] >= '0' && p[0] <= '9') // we expect extra attribute number 0 to 9
1003  {
1004  while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++; // first skip white spaces
1005  if (l[0] == 0) return FALSE;
1006  I32 index = (I32)(p[0] - '0');
1007  if (!parse_extra_attribute(l, index)) return FALSE;
1008  while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++; // then advance to next white space
1009  }
1010  else
1011  {
1012  fprintf(stderr, "ERROR: unknown symbol '%c' in parse string\n", p[0]);
1013  }
1014  p++;
1015  }
1016  return TRUE;
1017 }
1018 
1020 {
1021  const char* p = parse_string;
1022  while (p[0])
1023  {
1024  if ((p[0] != 'x') && // we expect the x coordinate
1025  (p[0] != 'y') && // we expect the y coordinate
1026  (p[0] != 'z') && // we expect the x coordinate
1027  (p[0] != 't') && // we expect the gps time
1028  (p[0] != 'R') && // we expect the red channel of the RGB field
1029  (p[0] != 'G') && // we expect the green channel of the RGB field
1030  (p[0] != 'B') && // we expect the blue channel of the RGB field
1031  (p[0] != 's') && // we expect a string or a number that we don't care about
1032  (p[0] != 'i') && // we expect the intensity
1033  (p[0] != 'a') && // we expect the scan angle
1034  (p[0] != 'n') && // we expect the number of returns of given pulse
1035  (p[0] != 'r') && // we expect the number of the return
1036  (p[0] != 'c') && // we expect the classification
1037  (p[0] != 'u') && // we expect the user data
1038  (p[0] != 'p') && // we expect the point source ID
1039  (p[0] != 'e') && // we expect the edge of flight line flag
1040  (p[0] != 'd')) // we expect the direction of scan flag
1041  {
1042  if (p[0] >= '0' && p[0] <= '9')
1043  {
1044  I32 index = (I32)(p[0] - '0');
1045  if (index >= header.number_extra_attributes)
1046  {
1047  fprintf(stderr, "ERROR: extra attribute '%d' was not described.\n", index);
1048  return FALSE;
1049  }
1051  }
1052  else
1053  {
1054  fprintf(stderr, "ERROR: unknown symbol '%c' in parse string. valid are\n", p[0]);
1055  fprintf(stderr, " 'x' : the x coordinate\n");
1056  fprintf(stderr, " 'y' : the y coordinate\n");
1057  fprintf(stderr, " 'z' : the x coordinate\n");
1058  fprintf(stderr, " 't' : the gps time\n");
1059  fprintf(stderr, " 'R' : the red channel of the RGB field\n");
1060  fprintf(stderr, " 'G' : the green channel of the RGB field\n");
1061  fprintf(stderr, " 'B' : the blue channel of the RGB field\n");
1062  fprintf(stderr, " 's' : a string or a number that we don't care about\n");
1063  fprintf(stderr, " 'i' : the intensity\n");
1064  fprintf(stderr, " 'a' : the scan angle\n");
1065  fprintf(stderr, " 'n' : the number of returns of that given pulse\n");
1066  fprintf(stderr, " 'r' : the number of the return\n");
1067  fprintf(stderr, " 'c' : the classification\n");
1068  fprintf(stderr, " 'u' : the user data\n");
1069  fprintf(stderr, " 'p' : the point source ID\n");
1070  fprintf(stderr, " 'e' : the edge of flight line flag\n");
1071  fprintf(stderr, " 'd' : the direction of scan flag\n");
1072  return FALSE;
1073  }
1074  }
1075  p++;
1076  }
1077  return TRUE;
1078 }
1079 
1081 {
1082  // if not specified in the command line, set a reasonable scale_factor
1083  if (scale_factor)
1084  {
1088  }
1089  else
1090  {
1091  if (-360 < header.min_x && -360 < header.min_y && header.max_x < 360 && header.max_y < 360) // do we have longitude / latitude coordinates
1092  {
1093  header.x_scale_factor = 1e-7;
1094  header.y_scale_factor = 1e-7;
1095  }
1096  else // then we assume utm or mercator / lambertian projections
1097  {
1098  header.x_scale_factor = 0.01;
1099  header.y_scale_factor = 0.01;
1100  }
1101  header.z_scale_factor = 0.01;
1102  }
1103 
1104  // if not specified in the command line, set a reasonable offset
1105  if (offset)
1106  {
1107  header.x_offset = offset[0];
1108  header.y_offset = offset[1];
1109  header.z_offset = offset[2];
1110  }
1111  else
1112  {
1113  if (-360 < header.min_x && -360 < header.min_y && header.max_x < 360 && header.max_y < 360) // do we have longitude / latitude coordinates
1114  {
1115  header.x_offset = 0;
1116  header.y_offset = 0;
1117  header.z_offset = 0;
1118  }
1119  else // then we assume utm or mercator / lambertian projections
1120  {
1121  header.x_offset = ((I32)((header.min_x + header.max_x)/200000))*100000;
1122  header.y_offset = ((I32)((header.min_y + header.max_y)/200000))*100000;
1123  header.z_offset = ((I32)((header.min_z + header.max_z)/200000))*100000;
1124  }
1125  }
1126 }
1127 
1129 {
1130  // compute quantized and then unquantized bounding box
1131 
1132  F64 dequant_min_x = header.get_x(header.get_x(header.min_x));
1133  F64 dequant_max_x = header.get_x(header.get_x(header.max_x));
1134  F64 dequant_min_y = header.get_y(header.get_y(header.min_y));
1135  F64 dequant_max_y = header.get_y(header.get_y(header.max_y));
1136  F64 dequant_min_z = header.get_z(header.get_z(header.min_z));
1137  F64 dequant_max_z = header.get_z(header.get_z(header.max_z));
1138 
1139  // make sure there is not sign flip
1140 
1141  if ((header.min_x > 0) != (dequant_min_x > 0))
1142  {
1143  fprintf(stderr, "WARNING: quantization sign flip for min_x from %g to %g.\n", header.min_x, dequant_min_x);
1144  fprintf(stderr, " set scale factor for x coarser than %g with '-scale'\n", header.x_scale_factor);
1145  }
1146  else
1147  {
1148  header.min_x = dequant_min_x;
1149  }
1150  if ((header.max_x > 0) != (dequant_max_x > 0))
1151  {
1152  fprintf(stderr, "WARNING: quantization sign flip for max_x from %g to %g.\n", header.max_x, dequant_max_x);
1153  fprintf(stderr, " set scale factor for x coarser than %g with '-scale'\n", header.x_scale_factor);
1154  }
1155  else
1156  {
1157  header.max_x = dequant_max_x;
1158  }
1159  if ((header.min_y > 0) != (dequant_min_y > 0))
1160  {
1161  fprintf(stderr, "WARNING: quantization sign flip for min_y from %g to %g.\n", header.min_y, dequant_min_y);
1162  fprintf(stderr, " set scale factor for y coarser than %g with '-scale'\n", header.y_scale_factor);
1163  }
1164  else
1165  {
1166  header.min_y = dequant_min_y;
1167  }
1168  if ((header.max_y > 0) != (dequant_max_y > 0))
1169  {
1170  fprintf(stderr, "WARNING: quantization sign flip for max_y from %g to %g.\n", header.max_y, dequant_max_y);
1171  fprintf(stderr, " set scale factor for y coarser than %g with '-scale'\n", header.y_scale_factor);
1172  }
1173  else
1174  {
1175  header.max_y = dequant_max_y;
1176  }
1177  if ((header.min_z > 0) != (dequant_min_z > 0))
1178  {
1179  fprintf(stderr, "WARNING: quantization sign flip for min_z from %g to %g.\n", header.min_z, dequant_min_z);
1180  fprintf(stderr, " set scale factor for z coarser than %g with '-scale'\n", header.z_scale_factor);
1181  }
1182  else
1183  {
1184  header.min_z = dequant_min_z;
1185  }
1186  if ((header.max_z > 0) != (dequant_max_z > 0))
1187  {
1188  fprintf(stderr, "WARNING: quantization sign flip for max_z from %g to %g.\n", header.max_z, dequant_max_z);
1189  fprintf(stderr, " set scale factor for z coarser than %g with '-scale'\n", header.z_scale_factor);
1190  }
1191  else
1192  {
1193  header.max_z = dequant_max_z;
1194  }
1195 }
1196 
1197 LASreaderTXTrescale::LASreaderTXTrescale(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor) : LASreaderTXT()
1198 {
1199  scale_factor[0] = x_scale_factor;
1200  scale_factor[1] = y_scale_factor;
1201  scale_factor[2] = z_scale_factor;
1202 }
1203 
1204 BOOL LASreaderTXTrescale::open(const char* file_name, const char* parse_string, I32 skip_lines, BOOL populate_header)
1205 {
1206  if (!LASreaderTXT::open(file_name, parse_string, skip_lines, populate_header)) return FALSE;
1207  // do we need to change anything
1209  {
1211  }
1213  {
1215  }
1217  {
1219  }
1220  return TRUE;
1221 }
1222 
1224 {
1225  this->offset[0] = x_offset;
1226  this->offset[1] = y_offset;
1227  this->offset[2] = z_offset;
1228 }
1229 
1230 BOOL LASreaderTXTreoffset::open(const char* file_name, const char* parse_string, I32 skip_lines, BOOL populate_header)
1231 {
1232  if (!LASreaderTXT::open(file_name, parse_string, skip_lines, populate_header)) return FALSE;
1233  // do we need to change anything
1234  if (header.x_offset != offset[0])
1235  {
1236  header.x_offset = offset[0];
1237  }
1238  if (header.y_offset != offset[1])
1239  {
1240  header.y_offset = offset[1];
1241  }
1242  if (header.z_offset != offset[2])
1243  {
1244  header.z_offset = offset[2];
1245  }
1246  return TRUE;
1247 }
1248 
1249 LASreaderTXTrescalereoffset::LASreaderTXTrescalereoffset(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor, F64 x_offset, F64 y_offset, F64 z_offset) : LASreaderTXTrescale(x_scale_factor, y_scale_factor, z_scale_factor), LASreaderTXTreoffset(x_offset, y_offset, z_offset)
1250 {
1251 }
1252 
1253 BOOL LASreaderTXTrescalereoffset::open(const char* file_name, const char* parse_string, I32 skip_lines, BOOL populate_header)
1254 {
1255  if (!LASreaderTXT::open(file_name, parse_string, skip_lines, populate_header)) return FALSE;
1256  // do we need to change anything
1258  {
1260  }
1262  {
1264  }
1266  {
1268  }
1269  if (header.x_offset != offset[0])
1270  {
1271  header.x_offset = offset[0];
1272  }
1273  if (header.y_offset != offset[1])
1274  {
1275  header.y_offset = offset[1];
1276  }
1277  if (header.z_offset != offset[2])
1278  {
1279  header.z_offset = offset[2];
1280  }
1281  return TRUE;
1282 }
U8 edge_of_flight_line
#define I32_QUANTIZE(n)
Definition: mydefs.hpp:111
int BOOL
Definition: mydefs.hpp:57
FILE * fopen_compressed(const char *filename, const char *mode, bool *piped)
void populate_bounding_box()
#define FALSE
Definition: mydefs.hpp:133
U32 number_of_point_records
F64 extra_attribute_offsets[10]
BOOL parse(const char *parse_string)
float F32
Definition: mydefs.hpp:51
virtual BOOL open(const char *file_name, const char *parse_string=0, I32 skip_lines=0, BOOL populate_header=FALSE)
void close(BOOL close_stream=TRUE)
U16 point_data_record_length
void set_translate_intensity(F32 translate_intensity)
char * parse_string
const char * extra_attribute_descriptions[10]
LASheader header
Definition: lasreader.hpp:52
BOOL seek(const I64 p_index)
BOOL read_point_default()
void update_extra_bytes_vlr()
LASindex * index
Definition: lasreader.hpp:106
F32 translate_scan_angle
LASpoint point
Definition: lasreader.hpp:53
void set_offset(const F64 *offset)
short I16
Definition: mydefs.hpp:36
const char * extra_attribute_names[10]
unsigned int U32
Definition: mydefs.hpp:39
virtual ~LASreaderTXT()
I64 p_count
Definition: lasreader.hpp:56
U8 scan_direction_flag
#define I16_MIN
Definition: mydefs.hpp:85
void set_scale_intensity(F32 scale_intensity)
I16 get_total_extra_attributes_size() const
void set_min(U8 *min, I32 dim=0)
I64 npoints
Definition: lasreader.hpp:55
unsigned short U16
Definition: mydefs.hpp:40
BOOL init(const LASquantizer *quantizer, const U8 point_type, const U16 point_size, const LASattributer *attributer=0)
LASreaderTXTrescale(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor)
void populate_scale_and_offset()
#define I8_CLAMP(n)
Definition: mydefs.hpp:96
long long I64
Definition: mydefs.hpp:48
F64 coordinates[3]
void update_min(U8 *min, I32 dim=0)
U32 number_of_points_by_return[5]
void set_scale_scan_angle(F32 scale_scan_angle)
unsigned char U8
Definition: mydefs.hpp:41
void add_extra_attribute(I32 data_type, const char *name, const char *description=0, F64 scale=1.0, F64 offset=0.0)
void set_extra_attribute(I32 index, const U8 *data)
#define U32_QUANTIZE(n)
Definition: mydefs.hpp:112
#define U8_MAX
Definition: mydefs.hpp:67
BOOL check_parse_string(const char *parse_string)
void set_translate_scan_angle(F32 translate_scan_angle)
SharedPointer p
#define U16_CLAMP(n)
Definition: mydefs.hpp:100
I8 system_identifier[32]
char I8
Definition: mydefs.hpp:37
BOOL open(const char *file_name, const char *parse_string=0, I32 skip_lines=0, BOOL populate_header=FALSE)
U16 file_creation_year
ByteStreamIn * get_stream() const
#define I16_MAX
Definition: mydefs.hpp:86
F64 get_y(const I32 y) const
void update_max(U8 *max, I32 dim=0)
int I32
Definition: mydefs.hpp:35
void set_scale_factor(const F64 *scale_factor)
virtual BOOL open(const char *file_name, const char *parse_string=0, I32 skip_lines=0, BOOL populate_header=FALSE)
I32 number_extra_attributes
#define U8_MIN
Definition: mydefs.hpp:66
#define I8_MAX
Definition: mydefs.hpp:83
I32 extra_attributes_data_types[10]
BOOL reopen(const char *file_name)
#define I8_MIN
Definition: mydefs.hpp:82
BOOL set_scale(F64 scale, I32 dim=0)
void set_max(U8 *max, I32 dim=0)
F64 get_z(const I32 z) const
I32 extra_attribute_array_offsets[10]
BOOL parse_extra_attribute(const char *l, I32 index)
BOOL has_scale() const
I32 add_extra_attribute(const LASattribute extra_attribute)
#define LAS_TOOLS_VERSION
#define U16_MIN
Definition: mydefs.hpp:70
#define TRUE
Definition: mydefs.hpp:137
I32 get_extra_attribute_array_offset(const char *name) const
LASreaderTXTrescalereoffset(F64 x_scale_factor, F64 y_scale_factor, F64 z_scale_factor, F64 x_offset, F64 y_offset, F64 z_offset)
#define I16_CLAMP(n)
Definition: mydefs.hpp:99
#define U16_MAX
Definition: mydefs.hpp:71
F64 get_x(const I32 x) const
BOOL set_offset(F64 offset, I32 dim=0)
I8 generating_software[32]
virtual BOOL open(const char *file_name, const char *parse_string=0, I32 skip_lines=0, BOOL populate_header=FALSE)
LASattribute * extra_attributes
#define U8_CLAMP(n)
Definition: mydefs.hpp:97
F64 extra_attribute_scales[10]
double F64
Definition: mydefs.hpp:52
U8 number_of_returns_of_given_pulse
LASreaderTXTreoffset(F64 x_offset, F64 y_offset, F64 z_offset)
char line[512]


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