OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimLasReader.cpp
Go to the documentation of this file.
1 //---
2 //
3 // File: ossimLasReader.cpp
4 //
5 // License: MIT
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 // Author: David Burken
10 //
11 // Description: OSSIM LAS LIDAR reader.
12 //
13 //---
14 // $Id$
15 
18 #include <ossim/base/ossimCommon.h>
19 #include <ossim/base/ossimIpt.h>
20 #include <ossim/base/ossimGpt.h>
21 #include <ossim/base/ossimEndian.h>
24 #include <ossim/base/ossimString.h>
26 #include <ossim/base/ossimTrace.h>
40 
42 
43 #include <fstream>
44 #include <limits>
45 #include <sstream>
46 
47 RTTI_DEF1(ossimLasReader, "ossimLasReader", ossimImageHandler)
48 
49 static ossimTrace traceDebug("ossimLasReader:debug");
50 
51 static const char GSD_KW[] = "gsd";
52 static const char SCAN_KW[] = "scan"; // boolean
53 
56  m_str(),
57  m_hdr(0),
58  m_proj(0),
59  m_ul(),
60  m_lr(),
61  m_maxZ(0.0),
62  m_minZ(0.0),
63  m_gsd(),
64  m_tile(0),
65  m_entry(0),
66  m_mutex(),
67  m_scan(false), // ???
68  m_units(OSSIM_METERS),
69  m_unitConverter(0)
70 {
71  //---
72  // Nan out as can be set in several places, i.e. setProperty,
73  // loadState and initProjection.
74  //---
75  m_gsd.makeNan();
76 }
77 
79 {
80  close();
81 }
82 
84 {
85  static const char M[] = "ossimLasReader::open";
86  if (traceDebug())
87  {
89  << M << " entered...\nfile: " << theImageFile << "\n";
90  }
91 
92  bool result = false;
93 
94  close();
95 
96  m_str.open(theImageFile.c_str(), std::ios_base::in | std::ios_base::binary);
97  if ( m_str.good() )
98  {
99  m_hdr = new ossimLasHdr();
100  if ( m_hdr->checkSignature( m_str ) )
101  {
102  m_str.seekg(0, std::ios_base::beg);
104  ossim_uint32 dataFormatId = m_hdr->getPointDataFormatId();
105 
106  if ( (dataFormatId == 0) || (dataFormatId == 1) || (dataFormatId == 2) ||
107  (dataFormatId == 3) || (dataFormatId == 4) )
108  {
109  result = init();
110 
111  if ( result )
112  {
114 
115  if ( traceDebug() )
116  {
118  }
119  }
120  }
121  else
122  {
123  if ( traceDebug() )
124  {
126  << "Unhandled point type: " << int(m_hdr->getPointDataFormatId()) << "\n";
127  }
128  }
129 
130  if ( traceDebug() && result )
131  {
133  }
134 
135  } // if ( m_hdr->checkSignature( m_str ) )
136 
137  } // if ( m_str.good() )
138 
139  if ( !result ) close();
140 
141  if (traceDebug())
142  {
143  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
144  }
145 
146  return result;
147 }
148 
150 {
152 }
153 
155 {
156  if ( isOpen() )
157  {
158  m_str.close();
159  delete m_hdr;
160  m_hdr = 0;
161  m_entry = 0;
162  m_tile = 0;
163  m_proj = 0;
165  }
166 }
167 
169  const ossimIrect& tile_rect, ossim_uint32 resLevel)
170 {
171  if ( m_tile.valid() == false )
172  {
173  initTile(); // First time through.
174  }
175 
176  if ( m_tile.valid() )
177  {
178  // Image rectangle must be set prior to calling getTile.
179  m_tile->setImageRectangle(tile_rect);
180 
181  if ( getTile( m_tile.get(), resLevel ) == false )
182  {
184  {
185  m_tile->makeBlank();
186  }
187  }
188  }
189 
190  return m_tile;
191 }
192 
194 {
195  // static const char MODULE[] = "ossimLibLasReader::getTile(ossimImageData*, level)";
196 
197  bool status = false;
198 
199 
200  if ( m_hdr && result && (result->getScalarType() == OSSIM_FLOAT32||result->getScalarType() == OSSIM_UINT16) &&
201  (result->getDataObjectStatus() != OSSIM_NULL) &&
202  !m_ul.hasNans() && !m_gsd.hasNans() )
203  {
204  status = true;
205 
206  const ossimIrect TILE_RECT = result->getImageRectangle();
207  const ossim_int32 TILE_HEIGHT = static_cast<ossim_int32>(TILE_RECT.height());
208  const ossim_int32 TILE_WIDTH = static_cast<ossim_int32>(TILE_RECT.width());
209  const ossim_int32 TILE_SIZE = static_cast<ossim_int32>(TILE_RECT.area());
210 
211  // Get the scale for this resLevel:
212  ossimDpt scale;
213  getScale(scale, resLevel);
214 
215  // Set the starting upper left of upper left pixel for this tile.
216  const ossimDpt UL_PROG_PT( m_ul.x - scale.x / 2.0 + TILE_RECT.ul().x * scale.x,
217  m_ul.y + scale.y / 2.0 - TILE_RECT.ul().y * scale.y);
218  //const ossimDpt UL_PROG_PT( m_ul.x + TILE_RECT.ul().x * scale.x,
219  // m_ul.y + scale.y / 2.0 - TILE_RECT.ul().y * scale.y);
220 
221  //---
222  // Set the lower right to the edge of the tile boundary. This looks like an
223  // "off by one" error but it's not. We want the ossimDrect::pointWithin to
224  // catch any points in the last line sample.
225  //---
226  const ossimDpt LR_PROG_PT( UL_PROG_PT.x + TILE_WIDTH * scale.x,
227  UL_PROG_PT.y - TILE_HEIGHT * scale.y);
228 
229  const ossimDrect PROJ_RECT(UL_PROG_PT, LR_PROG_PT, OSSIM_RIGHT_HANDED);
230 
231 #if 0 /* Please leave for debug. (drb) */
232  cout << "m_ul: " << m_ul
233  << "\nm_gsd: " << m_gsd
234  << "\nscale: " << scale
235  << "\nresult->getScalarType(): " << result->getScalarType()
236  << "\nresult->getDataObjectStatus(): " << result->getDataObjectStatus()
237  << "\nPROJ_RECT: " << PROJ_RECT
238  << "\nTILE_RECT: " << TILE_RECT
239  << "\nUL_PROG_PT: " << UL_PROG_PT << endl;
240 #endif
241 
242  const ossim_float64 SCALE_X = m_hdr->getScaleFactorX();
243  const ossim_float64 SCALE_Y = m_hdr->getScaleFactorY();
244  const ossim_float64 SCALE_Z = m_hdr->getScaleFactorZ();
245  const ossim_float64 OFFSET_X = m_hdr->getOffsetX();
246  const ossim_float64 OFFSET_Y = m_hdr->getOffsetY();
247  const ossim_float64 OFFSET_Z = m_hdr->getOffsetZ();
248 
249  // Create array of buckets.
250  std::vector<ossimLasReader::Bucket> bucket( TILE_SIZE );
251 
252  // Loop through the point data.
254  ossimDpt lasPt;
255 
256  m_str.clear();
257  m_str.seekg(m_hdr->getOffsetToPointData());
258 
259  while ( m_str.good() )
260  {
261  // m_str.read((char*)lasPtRec, 28);
262  lasPtRec->readStream( m_str );
263 
264  //if ( lasPtRec->getReturnNumber() == ENTRY )
265  //{
266  lasPt.x = lasPtRec->getX() * SCALE_X + OFFSET_X;
267  lasPt.y = lasPtRec->getY() * SCALE_Y + OFFSET_Y;
268  if ( m_unitConverter )
269  {
270  convertToMeters(lasPt.x);
271  convertToMeters(lasPt.y);
272  }
273  if ( PROJ_RECT.pointWithin( lasPt ) )
274  {
275  // Compute the bucket index:
276  ossim_int32 line = static_cast<ossim_int32>((UL_PROG_PT.y - lasPt.y) / scale.y);
277  ossim_int32 samp = static_cast<ossim_int32>((lasPt.x - UL_PROG_PT.x) / scale.x );
278  ossim_int32 bucketIndex = line * TILE_WIDTH + samp;
279 
280  // Range check and add if in there.
281  if ( ( bucketIndex >= 0 ) && ( bucketIndex < TILE_SIZE ) )
282  {
283  ossim_float64 z = lasPtRec->getZ() * SCALE_Z + OFFSET_Z;
285  bucket[bucketIndex].add( z );
286  bucket[bucketIndex].setRed(lasPtRec->getRed());
287  bucket[bucketIndex].setGreen(lasPtRec->getGreen());
288  bucket[bucketIndex].setBlue(lasPtRec->getBlue());
289  bucket[bucketIndex].setIntensity(lasPtRec->getIntensity());
290 
291  }
292  }
293  //}
294  if ( m_str.eof() ) break;
295  }
296  delete lasPtRec;
297  lasPtRec = 0;
298 
299  //---
300  // We must always blank out the tile as we may not have a point for every
301  // point.
302  //---
303  result->makeBlank();
304 
305  //ossim_float32* buf = result->getFloatBuf(); // Tile buffer to fill.
306  if(m_entry == 1)
307  {
308  const ossim_uint32 BANDS = getNumberOfOutputBands();
309  std::vector<ossim_uint16> tempBuf(TILE_SIZE * BANDS);
310  ossim_uint16* buffer = &tempBuf.front();
311  for (ossim_uint32 band = 0; band < BANDS; ++band)
312  {
313  for (ossim_int32 i = 0; i < TILE_SIZE; ++i)
314  {
315  if(band == 0) buffer[i] = bucket[i].getRed();
316  if(band == 1) buffer[i] = bucket[i].getGreen();
317  if(band == 2) buffer[i] = bucket[i].getBlue();
318  }
319  }
320  result->loadTile(buffer, TILE_RECT, TILE_RECT, OSSIM_BIP);
321  }
322  else if (m_entry == 2)
323  {
324  ossim_uint16* buf = result->getUshortBuf();
325  for (ossim_int32 i = 0; i < TILE_SIZE; ++i)
326  {
327  buf[i] = bucket[i].getIntensity();
328  }
329  }
330  else
331  {
332  ossim_float32* buf = result->getFloatBuf();
333 
334  // Fill the tile. Currently no band loop:
335  for (ossim_int32 i = 0; i < TILE_SIZE; ++i)
336  {
337  buf[i] = bucket[i].getValue();
338  }
339  }
340 
341  // Revalidate.
342  result->validate();
343  }
344 
345  return status;
346 
347 } // End: bool ossimLibLasReader::getTile(ossimImageData* result, ossim_uint32 resLevel)
348 
350 {
351  return 1; // tmp
352 }
353 
355 {
356  if(m_entry == 1) return 3;
357  return 1;
358 }
359 
361 {
362  ossim_uint32 result = 0;
363  if ( isOpen() )
364  {
365  result = static_cast<ossim_uint32>(ceil((m_ul.y - m_lr.y) / m_gsd.y));
366  if (resLevel) result = (result>>resLevel);
367  }
368  return result;
369 }
370 
372 {
373  ossim_uint32 result = 0;
374  if ( isOpen() )
375  {
376  result = static_cast<ossim_uint32>(ceil((m_lr.x - m_ul.x) / m_gsd.x));
377  if (resLevel) result = (result>>resLevel);
378  }
379  return result;
380 }
381 
383 {
384  return 0;
385 }
386 
388 {
389  return 0;
390 }
391 
393 {
394  ossimIpt ipt;
396  return ipt.x;
397 }
398 
400 {
401  ossimIpt ipt;
403  return ipt.y;
404 }
405 
407 {
408  //return OSSIM_FLOAT32;
410  if(m_entry == 1 || m_entry == 2) stype = OSSIM_UINT16;
411  return stype;
412 }
413 
414 void ossimLasReader::getEntryList(std::vector<ossim_uint32>& entryList)const
415 {
416  if ( isOpen() )
417  {
418  entryList.push_back(0);
419  entryList.push_back(1);
420  entryList.push_back(2);
421  //for ( ossim_uint32 entry = 0; entry < 15; ++entry )
422  //{
423  // if ( m_hdr->getNumberOfPoints(entry) ) entryList.push_back(entry);
424  //}
425  }
426  else
427  {
428  entryList.clear();
429  }
430 }
431 
433 {
434  return static_cast<ossim_uint32>(m_entry);
435 }
436 
438 {
439  bool result = false;
440  if ( isOpen() )
441  {
442  std::vector<ossim_uint32> entryList;
443  getEntryList( entryList );
444  std::vector<ossim_uint32>::const_iterator i = entryList.begin();
445  while ( i != entryList.end() )
446  {
447  if ( (*i) == entryIdx )
448  {
449  m_entry = entryIdx;
450  result = true;
451  }
452  ++i;
453  }
454  }
455  if(result) initTile();
456  return result;
457 }
458 
460 {
461  return ossimString("las");
462 }
463 
465 {
466  return ossimString("ossim las reader");
467 }
468 
470 {
471  if ( !theGeometry )
472  {
473  // Check for external geom:
475  if ( theGeometry.valid() == true )
476  {
477  // Picked up an external geometry file(dot.geom).
479 
481  if ( proj.valid() == true )
482  {
483  // Set the units:
484  if ( proj->isGeographic() )
485  {
487  }
488  else
489  {
490  // Currently hard coding to meters. May need to add property to override this.
492  }
493 
494  // Call initValues to set the tie point / bounds:
495  initValues();
496 
497  // Set the tie and gsd:
498  if ( proj->isGeographic() )
499  {
501  ossimGpt gpt(m_ul.y, m_ul.x, 0.0, proj->getDatum() );
502  proj->setUlTiePoints( gpt );
504  }
505  else
506  {
507  // Currently hard coding to meters. May need to add property to override this.
509  proj->setUlTiePoints(m_ul);
511  }
512 
513  ossimIpt imgSize;
514  imgSize.x = (ossim_int32)getNumberOfSamples(0);
515  imgSize.y = (ossim_int32)getNumberOfLines(0);
516 
517  theGeometry->setImageSize( imgSize );
518  }
519  }
520 
521  if ( !theGeometry )
522  {
524  if ( m_proj.valid() )
525  {
527  }
528  else
529  {
530  //---
531  // WARNING:
532  // Must create/set theGeometry at this point or the next call to
533  // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
534  // as it does a recursive call back to ossimImageHandler::getImageGeometry().
535  //---
536 
537  // Try factories for projection.
539  }
540  }
541 
542  // Set image things the geometry object should know about.
544  }
545 
546  return theGeometry;
547 }
548 
550 {
551  return m_minZ;
552 }
553 
555 {
556  return m_maxZ;
557 }
558 
560 {
561  return -99999.0;
562 }
563 
565 {
566  // Can support any number of rlevels.
567  ossim_uint32 result = 1;
568  const ossim_uint32 STOP_DIMENSION = 16;
569  ossim_uint32 largestImageDimension = getNumberOfSamples(0) > getNumberOfLines(0) ?
571  while(largestImageDimension > STOP_DIMENSION)
572  {
573  largestImageDimension /= 2;
574  ++result;
575  }
576  return result;
577 }
578 
579 bool ossimLasReader::saveState(ossimKeywordlist& kwl, const char* prefix)const
580 {
581  kwl.add( prefix, GSD_KW, m_gsd.toString().c_str(), true );
582  kwl.add( prefix, SCAN_KW, ossimString::toString(m_scan).c_str(), true );
583  return ossimImageHandler::saveState(kwl, prefix);
584 }
585 
586 bool ossimLasReader::loadState(const ossimKeywordlist& kwl, const char* prefix)
587 {
588  bool result = false;
589  if ( ossimImageHandler::loadState(kwl, prefix) )
590  {
591  result = open();
592  if ( result )
593  {
594  // Get our keywords:
595  const char* lookup = kwl.find(prefix, GSD_KW);
596  if ( lookup )
597  {
598  m_gsd.toPoint( ossimString(lookup) );
599  }
600  lookup = kwl.find(prefix, SCAN_KW);
601  if ( lookup )
602  {
603  ossimString s = lookup;
604  m_scan = s.toBool();
605  }
606  }
607  }
608  return result;
609 }
610 
612 {
613  if ( property.valid() )
614  {
615  if ( property->getName() == GSD_KW )
616  {
617  ossimString s;
618  property->valueToString(s);
619  ossim_float64 d = s.toFloat64();
620  if ( ossim::isnan(d) == false )
621  {
622  setGsd( d );
623  }
624  }
625  else if ( property->getName() == SCAN_KW )
626  {
627  ossimString s;
628  property->valueToString(s);
629  m_scan = s.toBool();
630  }
631  else
632  {
634  }
635  }
636 }
637 
639 {
641  if ( name == GSD_KW )
642  {
644  prop = new ossimStringProperty(name, value);
645  }
646  else if ( name == SCAN_KW )
647  {
648  prop = new ossimBooleanProperty(name, m_scan);
649  }
650  else
651  {
652  prop = ossimImageHandler::getProperty(name);
653  }
654  return prop;
655 }
656 
657 void ossimLasReader::getPropertyNames(std::vector<ossimString>& propertyNames)const
658 {
659  propertyNames.push_back( ossimString(GSD_KW) );
660  propertyNames.push_back( ossimString(SCAN_KW) );
662 }
663 
665 {
666  bool result = false;
667 
668  if ( isOpen() )
669  {
670  // Check for external geometry file for projection stuff.
671  ossimFilename geomFile;
672  getFilenameWithThisExt( ossimString(".geom" ), geomFile );
673  if ( geomFile.exists() == true )
674  {
675  // Call get image geometry to initialize ourself.
677  if ( geom.valid() == true )
678  {
679  // Check for map projection.
681  if ( proj.valid() == true )
682  {
683  if ( dynamic_cast<ossimMapProjection*>( proj.get() ) )
684  {
685  result = true;
686  }
687  }
688  }
689  }
690 
691  if ( !result )
692  {
693  // Check for option var record.
694  result = parseVarRecords();
695 
696  if ( !result )
697  {
698  // Checks for external FGDC text file.
699  result = initFromExternalMetadata();
700  }
701  }
702  }
703 
704  return result;
705 }
706 
708 {
709  bool result = true;
710 
711  ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
712  if ( proj )
713  {
714  //---
715  // Set the tie and scale:
716  // Note the scale can be set in other places so only set here if it
717  // has nans.
718  //---
719  if ( proj->isGeographic() )
720  {
721  ossimGpt gpt(m_ul.y, m_ul.x, 0.0, proj->getDatum() );
722  proj->setUlTiePoints( gpt );
723 
724  if ( m_gsd.hasNans() )
725  {
727  if ( m_gsd.hasNans() || !m_gsd.x || !m_gsd.y )
728  {
729  // Set to some default:
730  m_gsd.x = 0.000008983; // About 1 meter at the Equator.
731  m_gsd.y = m_gsd.x;
733  }
734 
735  }
736  }
737  else
738  {
739  proj->setUlTiePoints(m_ul);
740 
741  if ( m_gsd.hasNans() )
742  {
743  m_gsd = proj->getMetersPerPixel();
744  if ( m_gsd.hasNans() || !m_gsd.x || !m_gsd.y )
745  {
746  // Set to some default:
747  m_gsd.x = 1.0;
748  m_gsd.y = 1.0;
749  proj->setMetersPerPixel( m_gsd );
750  }
751  }
752  }
753  }
754  else
755  {
756  result = false;
757  m_ul.makeNan();
758  m_lr.makeNan();
759  m_gsd.makeNan();
760 
762  << "ossimLasReader::initProjection WARN Could not cast to map projection!"
763  << std::endl;
764  }
765 
766  return result;
767 
768 } // bool ossimLasReader::initProjection()
769 
771 {
773 
774  m_tile = new ossimImageData(this,
776  BANDS,
777  getTileWidth(),
778  getTileHeight());
779 
780  for(ossim_uint32 band = 0; band < BANDS; ++band)
781  {
782  if (m_entry == 0 || m_entry == 1)
783  {
784  m_tile->setMinPix(getMinPixelValue(band), band);
785  m_tile->setMaxPix(getMaxPixelValue(band), band);
786  m_tile->setNullPix(getNullPixelValue(band), band);
787  }
788  }
789 
790  m_tile->initialize();
791 }
792 
794 {
795  ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
796  if ( proj )
797  {
798  if ( proj->isGeographic() )
799  {
801  }
802  else
803  {
804  const char* lookup = geomKwl.find("image0.linear_units");
805  if ( lookup )
806  {
807  std::string units = lookup;
808  if ( units == "meters" )
809  {
811  }
812  else if ( units == "feet" )
813  {
815  }
816  else if ( units == "us_survey_feet" )
817  {
819  }
820  else
821  {
823  << "ossimLibLasReader::initUnits WARN:\n"
824  << "Unhandled linear units code: " << units << std::endl;
825  }
826  }
827  }
828  }
829 
830  // Don't make a unit converter for decimal degrees...
832  {
834  }
835 }
836 
838 {
839  static const char M[] = "ossimLasReader::initValues";
840 
841  if ( m_scan )
842  {
843  // Set to bogus values to start.
850 
851  const ossim_float64 SCALE_X = m_hdr->getScaleFactorX();
852  const ossim_float64 SCALE_Y = m_hdr->getScaleFactorY();
853  const ossim_float64 SCALE_Z = m_hdr->getScaleFactorZ();
854  const ossim_float64 OFFSET_X = m_hdr->getOffsetX();
855  const ossim_float64 OFFSET_Y = m_hdr->getOffsetY();
856  const ossim_float64 OFFSET_Z = m_hdr->getOffsetZ();
857 
859 
860  m_str.clear();
861  m_str.seekg(m_hdr->getOffsetToPointData());
862 
865  ossim_float64 z;
866 
867  while ( m_str.good() )
868  {
869  lasPtRec->readStream( m_str );
870 
871 #if 0 /* Please leave for debug. (drb) */
873 #endif
874 
875  x = lasPtRec->getX() * SCALE_X + OFFSET_X;
876  y = lasPtRec->getY() * SCALE_Y + OFFSET_Y;
877  z = lasPtRec->getZ() * SCALE_Z + OFFSET_Z;
878 
879  //std::cout << "X: " << lasPtRec->getX() << " SCALE: " << SCALE_X << " OFFSET: " << OFFSET_X << " XNORM: " << x << std::endl;
880  //std::cout << "Y: " << lasPtRec->getY() << " SCALE: " << SCALE_Y << " OFFSET: " << OFFSET_Y << " YNORM: " << y << std::endl;
881  //std::cout << "Z: " << lasPtRec->getZ() << " SCALE: " << SCALE_Z << " OFFSET: " << OFFSET_Z << " ZNORM: " << z << std::endl;
882 
883  if ( x < m_ul.x ) m_ul.x = x;
884  if ( x > m_lr.x ) m_lr.x = x;
885  if ( y > m_ul.y ) m_ul.y = y;
886  if ( y < m_lr.y ) m_lr.y = y;
887  if ( z > m_maxZ ) m_maxZ = z;
888  if ( z < m_minZ ) m_minZ = z;
889 
890  if ( m_str.eof() ) break;
891  }
892  delete lasPtRec;
893  lasPtRec = 0;
894  }
895  else
896  {
897  // Set the upper left (tie).
898  m_ul.x = m_hdr->getMinX();
899  m_ul.y = m_hdr->getMaxY();
900 
901  // Set the lower right.
902  m_lr.x = m_hdr->getMaxX();
903  m_lr.y = m_hdr->getMinY();
904 
905  // Set the min/max:
906  m_minZ = m_hdr->getMinZ();
907  m_maxZ = m_hdr->getMaxZ();
908  }
909 
910  if ( m_unitConverter ) // Need to convert to meters.
911  {
914 
917 
920  }
921 
922  if ( traceDebug() )
923  {
924  ossimNotify(ossimNotifyLevel_DEBUG) << M << " DEBUG:\nBounds from header:";
925  ossimDpt pt;
926  pt.x = m_hdr->getMinX();
927  pt.y = m_hdr->getMaxY();
928  if ( m_unitConverter )
929  {
930  convertToMeters(pt.x);
931  convertToMeters(pt.y);
932  }
933  ossimNotify(ossimNotifyLevel_DEBUG) << "\nul: " << pt;
934  pt.x = m_hdr->getMaxX();
935  pt.y = m_hdr->getMinY();
936 
937  if ( m_unitConverter )
938  {
939  convertToMeters(pt.x);
940  convertToMeters(pt.y);
941  }
942  ossimNotify(ossimNotifyLevel_DEBUG) << "\nlr: " << pt;
943  pt.x = m_hdr->getMinZ();
944  pt.y = m_hdr->getMaxZ();
945  if ( m_unitConverter )
946  {
947  convertToMeters(pt.x);
948  convertToMeters(pt.y);
949  }
951  << "\nminZ: " << pt.x
952  << "\nmaxZ: " << pt.y << "\n";
953  if ( m_scan )
954  {
956  << "Bounds from scan:"
957  << "\nul: " << m_ul
958  << "\nlr: " << m_lr
959  << "\nminZ: " << m_minZ
960  << "\nmaxZ: " << m_maxZ << "\n";
961  }
962  }
963 }
964 
966 {
967  static const char M[] = "ossimLasReader::parseVarRecords";
968  if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
969 
970  bool result = false;
971 
972  if ( isOpen() )
973  {
974  std::streampos origPos = m_str.tellg();
975  std::streamoff pos = static_cast<std::streamoff>(m_hdr->getHeaderSize());
976 
977  m_str.clear();
978  m_str.seekg(pos, std::ios_base::beg);
979 
980  ossim_uint32 vlrCount = m_hdr->getNumberOfVlrs();
981  ossim_uint16 reserved;
982  char uid[17];
983  uid[16]='\n';
984  ossim_uint16 recordId;
985  ossim_uint16 length;
986  char des[33];
987  des[32] = '\n';
988 
989  //---
990  // Things we need to save for printGeoKeys:
991  //---
992  ossim_uint16* geoKeyBlock = 0;
993  ossim_uint64 geoKeyLength = 0;
994  ossim_float64* geoDoubleBlock = 0;
995  ossim_uint64 geoDoubleLength = 0;
996  ossim_int8* geoAsciiBlock = 0;
997  ossim_uint64 geoAsciiLength = 0;
998 
999  ossimEndian* endian = 0;
1000  // LAS LITTLE ENDIAN:
1002  {
1003  endian = new ossimEndian;
1004  }
1005 
1006  for ( ossim_uint32 i = 0; i < vlrCount; ++i )
1007  {
1008  m_str.read((char*)&reserved, 2);
1009  m_str.read(uid, 16);
1010  m_str.read((char*)&recordId, 2);
1011  m_str.read((char*)&length, 2);
1012  m_str.read(des, 32);
1013 
1014  // LAS LITTLE ENDIAN:
1015  if ( endian )
1016  {
1017  endian->swap(recordId);
1018  endian->swap(length);
1019  }
1020 
1021  if ( traceDebug() )
1022  {
1024  << "uid: " << uid
1025  << "\nrecordId: " << recordId
1026  << "\nlength: " << length
1027  << "\ndes: " << des
1028  << std::endl;
1029  }
1030 
1031  if (recordId == 34735) // GeoTiff projection keys.
1032  {
1033  geoKeyLength = length/2;
1034  if ( geoKeyBlock )
1035  {
1036  delete [] geoKeyBlock;
1037  }
1038  geoKeyBlock = new ossim_uint16[geoKeyLength];
1039  m_str.read((char*)geoKeyBlock, length);
1040  if ( endian )
1041  {
1042  endian->swap(geoKeyBlock, geoKeyLength);
1043  }
1044  }
1045  else if (recordId == 34736) // GeoTiff double parameters.
1046  {
1047  geoDoubleLength = length/8;
1048  if ( geoDoubleBlock )
1049  {
1050  delete [] geoDoubleBlock;
1051  }
1052  geoDoubleBlock = new ossim_float64[geoDoubleLength];
1053  m_str.read((char*)geoDoubleBlock, length);
1054  if ( endian )
1055  {
1056  endian->swap(geoDoubleBlock, geoDoubleLength);
1057  }
1058  }
1059  else if (recordId == 34737) // GeoTiff ascii block.
1060  {
1061  geoAsciiLength = length;
1062  if (geoAsciiBlock)
1063  {
1064  delete [] geoAsciiBlock;
1065  }
1066  geoAsciiBlock = new ossim_int8[length];
1067  m_str.read((char*)geoAsciiBlock, length);
1068  }
1069  else
1070  {
1071  m_str.seekg(length, ios_base::cur);
1072  }
1073  }
1074 
1075  //---
1076  // Must have at mimimum the geoKeyBlock for a projection.
1077  // Note the geoDoubleBlock is needed for some.
1078  // Note the geoAsciiBlock is not needed, i.e. only informational.
1079  //---
1080  if ( geoKeyBlock )
1081  {
1082  //---
1083  // Give the geokeys to ossimTiffInfo to get back a keyword list that can be fed to
1084  // ossimProjectionFactoryRegistry::createProjection
1085  //---
1086  ossimTiffInfo info;
1087  ossimKeywordlist geomKwl;
1088  info.getImageGeometry(geoKeyLength, geoKeyBlock,
1089  geoDoubleLength,geoDoubleBlock,
1090  geoAsciiLength,geoAsciiBlock,
1091  geomKwl);
1092 
1093  // Create the projection.
1095  if (m_proj.valid())
1096  {
1097  // Units must be set before initValues and initProjection.
1098  initUnits(geomKwl);
1099 
1100  // Must be called before initProjection.
1101  initValues();
1102 
1103  result = initProjection(); // Sets the ties and scale...
1104 
1105  if (traceDebug())
1106  {
1108  }
1109  }
1110  }
1111  else
1112  {
1113  /* Current data samples appear to be UTM but not sure where to find the zone
1114  const char* prefix = "image0.";
1115  // Build a default projection
1116  ossimKeywordlist geomKwl;
1117  geomKwl.add(prefix, "datum", "WGE", true);
1118  geomKwl.add(prefix, "pixel_type", "pixel_is_area", true);
1119  geomKwl.add(prefix, "type", "ossimEquDistCylProjection", true);
1120  m_proj = ossimProjectionFactoryRegistry::instance()->createProjection(geomKwl);
1121  if(m_proj.valid())
1122  {
1123  initUnits(geomKwl);
1124  initValues();
1125  result = initProjection(); // Sets the ties and scale...
1126  if (traceDebug())
1127  {
1128  m_proj->print(ossimNotify(ossimNotifyLevel_DEBUG));
1129  }
1130  }
1131  */
1132  }
1133 
1134  if ( geoKeyBlock )
1135  {
1136  delete [] geoKeyBlock;
1137  geoKeyBlock = 0;
1138  }
1139  if (geoDoubleBlock)
1140  {
1141  delete [] geoDoubleBlock;
1142  geoDoubleBlock = 0;
1143  }
1144  if (geoAsciiBlock)
1145  {
1146  delete [] geoAsciiBlock;
1147  geoAsciiBlock = 0;
1148  }
1149 
1150  m_str.seekg(origPos);
1151 
1152  if ( endian )
1153  {
1154  delete endian;
1155  endian = 0;
1156  }
1157  }
1158 
1159  if (traceDebug())
1160  {
1161  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
1162  }
1163  return result;
1164 }
1165 
1167 {
1168  static const char M[] = "ossimLasReader::initFromExternalMetadata";
1169  if (traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered...\n";
1170 
1171  bool result = false;
1172 
1173  ossimFilename fgdcFile = theImageFile;
1174  fgdcFile.setExtension("txt");
1175  if ( fgdcFile.exists() == false )
1176  {
1177  fgdcFile.setExtension("TXT");
1178  }
1179 
1180  if ( fgdcFile.exists() )
1181  {
1183  if ( fgdcDoc->open( fgdcFile ) )
1184  {
1185  fgdcDoc->getProjection( m_proj );
1186  if ( m_proj.valid() )
1187  {
1188  // Units must be set before initValues and initProjection.
1189  std::string units;
1190  fgdcDoc->getAltitudeDistanceUnits(units);
1191  if ( ( units == "feet" ) || ( units == "international feet" ) )
1192  {
1193  m_units = OSSIM_FEET;
1194  }
1195  else if ( units == "survey feet" )
1196  {
1198  }
1199  else
1200  {
1202  }
1203 
1204  // Must be called before initProjection.
1205  initValues();
1206 
1207  result = initProjection(); // Sets the ties and scale...
1208 
1209  if (traceDebug())
1210  {
1212  }
1213  }
1214  }
1215  }
1216 
1217  if (traceDebug())
1218  {
1219  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exit status = " << (result?"true\n":"false\n");
1220  }
1221  return result;
1222 }
1223 
1225 {
1226  ossimLasPointRecordInterface* result = 0;
1227 
1228  switch(m_hdr->getPointDataFormatId())
1229  {
1230  case 0:
1231  {
1232  result = new ossimLasPointRecord0();
1233  break;
1234  }
1235  case 1:
1236  {
1237  result = new ossimLasPointRecord1();
1238  break;
1239  }
1240  case 2:
1241  {
1242  result = new ossimLasPointRecord2();
1243  break;
1244  }
1245  case 3:
1246  {
1247  result = new ossimLasPointRecord3();
1248  break;
1249  }
1250  case 4:
1251  {
1252  result = new ossimLasPointRecord4();
1253  break;
1254  }
1255  default:
1256  {
1257  break;
1258  }
1259  }
1260 
1261  return result;
1262 }
1263 
1264 void ossimLasReader::getScale(ossimDpt& scale, ossim_uint32 resLevel) const
1265 {
1266  // std::pow(2.0, 0) returns 1.
1267  ossim_float64 d = std::pow(2.0, static_cast<double>(resLevel));
1268  scale.x = m_gsd.x * d;
1269  scale.y = m_gsd.y * d;
1270 }
1271 
1273 {
1274  m_gsd.x = gsd;
1275  m_gsd.y = m_gsd.x;
1276 
1277  if ( m_proj.valid() && ( m_gsd.hasNans() == false ) )
1278  {
1279  ossimMapProjection* proj = dynamic_cast<ossimMapProjection*>( m_proj.get() );
1280  if ( proj && ( m_gsd.hasNans() == false ) )
1281  {
1282  if ( proj->isGeographic() )
1283  {
1285  }
1286  else
1287  {
1288  proj->setMetersPerPixel( m_gsd );
1289  }
1290  }
1291  }
1292 }
ossim_float64 m_minZ
virtual std::ostream & print(std::ostream &out) const =0
ossim_uint32 x
virtual ossim_uint32 getNumberOfInputBands() const
Gets bands.
bool open(const ossimFilename &file)
open method.
virtual const ossimDpt & getDecimalDegreesPerPixel() const
Returns decimal degrees per pixel as an ossimDpt with "x" representing longitude and "y" representing...
virtual void close()
Close method.
ossim_uint32 getNumberOfVlrs() const
static ossimImageGeometryRegistry * instance()
ossimRefPtr< ossimImageGeometry > theGeometry
char ossim_int8
Previous DLL import export section.
bool pointWithin(const ossimDpt &pt, double epsilon=0.0) const
Definition: ossimDrect.h:781
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
ossimRefPtr< ossimImageData > m_tile
virtual ossim_uint16 getRed() const =0
ossimUnitConversionTool * m_unitConverter
ossimLasReader()
default constructor
std::ifstream m_str
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
virtual const ossim_uint16 * getUshortBuf() const
16 bit unsigned integer
Container class for LAS point record type 1.
virtual ossim_int32 getY() const =0
Represents serializable keyword/value map.
void convertToMeters(ossim_float64 &value) const
ossim_uint32 y
virtual double getMinPixelValue(ossim_uint32 band=0) const
bool valid() const
Definition: ossimRefPtr.h:75
void setGsd(const ossim_float64 &gsd)
Sets m_gsd data member and projection if projection is set.
const char * find(const char *key) const
bool checkSignature(std::istream &in) const
Checks for LASF in first four bytes.
float ossim_float32
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
virtual ossimString getShortName() const
virtual ossim_uint32 getCurrentEntry() const
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool getImageGeometry(ossimKeywordlist &geomKwl, ossim_uint32 entryIndex) const
Extracts geometry info to keyword list.
const ossim_float64 & getMaxX() const
static ossimString toString(bool aValue)
Numeric to string methods.
virtual bool isGeographic() const
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
virtual ossimString getLongName() const
const ossimIpt & ul() const
Definition: ossimIrect.h:274
const ossim_float64 & getScaleFactorY() const
void getScale(ossimDpt &scale, ossim_uint32 resLevel) const
Get the scale for resLevel.
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual bool open()
open method.
virtual bool isOpen() const
is open method.
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
virtual void setDecimalDegreesPerPixel(const ossimDpt &gsd)
bool initFromExternalMetadata()
Looks for external FGDC text file to initialize projection from.
const ossim_float64 & getScaleFactorZ() const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Set propterty method.
ossim_uint32 getOffsetToPointData() const
virtual ossim_uint32 getTileWidth() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Get propterty method.
const ossim_float64 & getMinX() const
32 bit floating point
ossimDpt getDegreesPerPixel() const
Returns the resolution of this image in degrees/pixel.
TIFF info class.
Definition: ossimTiffInfo.h:36
unsigned short ossim_uint16
virtual void setProperty(ossimRefPtr< ossimProperty > property)
void setImageSize(const ossimIpt &size)
Container class for LAS point record type 1.
virtual ossim_int32 getZ() const =0
virtual bool extendGeometry(ossimImageHandler *handler) const
virtual void initialize()
Initialize the data buffer.
virtual void setMetersPerPixel(const ossimDpt &gsd)
const ossim_float64 & getOffsetX() const
ossim_float64 m_maxZ
ossim_uint8 m_entry
ossimScalarType getOutputScalarType() const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Returns a pointer to a tile given an origin representing the upper left corner of the tile to grab fr...
virtual void setNullPix(ossim_float64 null_pix)
virtual ossim_uint32 getImageTileWidth() const
Gets tile width.
ossimProjection * createProjection(const ossimFilename &filename, ossim_uint32 entryIdx) const
const ossim_float64 & getOffsetZ() const
virtual ossim_uint16 getIntensity() const =0
Container class for LAS point record type 4.
virtual ossim_uint32 getTileHeight() const
virtual ossimDataObjectStatus validate() const
virtual const ossimDatum * getDatum() const
bool exists() const
ossimLasPointRecordInterface * getNewPointRecord() const
Returns a point of type.
const ossim_float64 & getScaleFactorX() const
virtual ossim_uint32 getImageTileHeight() const
Gets tile height.
bool toBool() const
String to numeric methods.
void initUnits(const ossimKeywordlist &geomKwl)
unsigned long long ossim_uint64
void readStream(std::istream &in)
Method to initialize from input stream.
unsigned int ossim_uint32
ossimDpt getMetersPerPixel() const
Returns the GSD associated with this image in the active projection.
void toPoint(const std::string &s)
Initializes this point from string.
Definition: ossimDpt.cpp:192
virtual ossim_int32 getX() const =0
const ossim_float64 & getMaxY() const
ossim_float64 toFloat64() const
const ossim_float64 & getOffsetY() const
virtual ossimIrect getImageRectangle() const
Support data container for FGDC in text format.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
const ossim_float64 & getMinZ() const
virtual bool setCurrentEntry(ossim_uint32 entryIdx)
virtual void close()
Deletes the overview and clears the valid image vertices.
ossimUnitType m_units
ossim_uint8 getPointDataFormatId() const
ossim_uint32 width() const
Definition: ossimIrect.h:500
void initImageParameters(ossimImageGeometry *geom) const
Convenience method to set things needed in the image geometry from the image handler.
bool hasNans() const
Definition: ossimDpt.h:67
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
virtual const ossim_float32 * getFloatBuf() const
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const
Gets lines.
static ossimProjectionFactoryRegistry * instance()
virtual void readStream(std::istream &in)=0
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Get propterty names.
virtual ossimRefPtr< ossimImageGeometry > getExternalImageGeometry() const
Returns the image geometry object associated with this tile source or NULL if non defined...
Container class for LAS point record type 3.
return status
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
void getProjection(ossimRefPtr< ossimProjection > &proj)
Gets projection from Spatial_Reference_Information block.
virtual ossim_uint16 getBlue() const =0
ossimString toString(ossim_uint32 precision=15) const
Definition: ossimDpt.cpp:160
void getFilenameWithThisExt(const ossimString &ext, ossimFilename &f) const
Returns the image file with extension set using supplentary directory for dirname if set...
virtual void setMaxPix(ossim_float64 max_pix)
virtual ossim_uint32 getNumberOfDecimationLevels() const
This class defines an abstract Handler which all image handlers(loaders) should derive from...
const ossim_float64 & getMaxZ() const
#define max(a, b)
Definition: auxiliary.h:76
ossim_int32 y
Definition: ossimIpt.h:142
virtual void completeOpen()
Will complete the opening process.
virtual double getNullPixelValue(ossim_uint32 band=0) const
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const
Gets samples.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
ossim_uint32 area() const
Definition: ossimIrect.h:396
double x
Definition: ossimDpt.h:164
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
OSSIM Interface for LAS point record types.
virtual void setUlTiePoints(const ossimGpt &gpt)
ossim_int32 x
Definition: ossimIpt.h:141
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossim_uint16 getHeaderSize() const
ossimLasHdr * m_hdr
virtual ossimDpt getMetersPerPixel() const
Container class for LAS point record type 2.
ossimFilename & setExtension(const ossimString &e)
Sets the extension of a file name.
virtual void setMinPix(ossim_float64 min_pix)
virtual ~ossimLasReader()
virtual destructor
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
virtual void getEntryList(std::vector< ossim_uint32 > &entryList) const
Gets entry list.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual ossim_uint16 getGreen() const =0
const ossim_float64 & getMinY() const
const ossimString & getName() const
#define min(a, b)
Definition: auxiliary.h:75
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
int ossim_int32
void getAltitudeDistanceUnits(std::string &units) const
Gets units from Altitude_Distance_Units.
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
ossimRefPtr< ossimProjection > m_proj
OSSIM LAS LIDAR reader.