OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimSrtmHandler.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Burken
6 //
7 // Description:
8 //
9 // Shuttle Radar Topography Mission (SRTM) elevation source.
10 //
11 //----------------------------------------------------------------------------
12 // $Id: ossimSrtmHandler.cpp 23117 2015-01-29 22:33:13Z okramer $
13 
15 #include <ossim/base/ossimCommon.h>
18 #include <ossim/base/ossimGpt.h>
19 #include <ossim/base/ossimEndian.h>
21 
22 RTTI_DEF1(ossimSrtmHandler, "ossimSrtmHandler" , ossimElevCellHandler)
23 
24 //***
25 // Define Trace flags for use within this file:
26 //***
27 #include <ossim/base/ossimTrace.h>
28 static ossimTrace traceDebug ("ossimSrtmElevSource:debug");
29 
31  :
33  m_streamOpen(false),
34  m_numberOfLines(0),
35  m_numberOfSamples(0),
36  m_srtmRecordSizeInBytes(0),
37  m_latSpacing(0.0),
38  m_lonSpacing(0.0),
39  m_nwCornerPost(),
40  m_swapper(0)
41 {
42 }
43 
45 {
46  if (m_swapper)
47  {
48  delete m_swapper;
49  m_swapper = 0;
50  }
51  close();
52 }
53 
55 {
56  if(!isOpen()) return ossim::nan();
57  if(!m_memoryMap.empty())
58  {
59  switch(m_scalarType)
60  {
61  case OSSIM_SINT16:
62  {
64  }
65  case OSSIM_FLOAT32:
66  {
68  }
69  default:
70  {
71  break;
72  }
73  }
74  }
75  else
76  {
77  switch(m_scalarType)
78  {
79  case OSSIM_SINT16:
80  {
82  }
83  case OSSIM_FLOAT32:
84  {
86  }
87  default:
88  {
89  break;
90  }
91  }
92  }
93 
94  return ossim::nan();
95 }
96 
97 template <class T>
99 {
100  // Establish the grid indexes:
101  double xi = (gpt.lon - m_nwCornerPost.lon) / m_lonSpacing;
102  double yi = (m_nwCornerPost.lat - gpt.lat) / m_latSpacing;
103 
104  int x0 = static_cast<int>(xi);
105  int y0 = static_cast<int>(yi);
106 
107  if(x0 == (m_numberOfSamples-1))
108  {
109  --x0; // Move over one post.
110  }
111 
112  // Check for top edge.
113  // if (gpt.lat == theGroundRect.ul().lat)
114  if(y0 == (m_numberOfLines-1))
115  {
116  --y0; // Move down one post.
117  }
118 
119 
120  // Do some error checking.
121  if ( xi < 0.0 || yi < 0.0 ||
122  x0 > (m_numberOfSamples - 2.0) ||
123  y0 > (m_numberOfLines - 2.0) )
124  {
125  return ossim::nan();
126  }
127 
128  T p[4];
129 
130  double p00;
131  double p01;
132  double p10;
133  double p11;
134 
135  //---
136  // Grab the four points from the srtm cell needed.
137  //---
138  std::streampos offset = y0 * m_srtmRecordSizeInBytes + x0 * sizeof(T);
139 
140  {
141  std::lock_guard<std::mutex> lock(m_fileStrMutex);
142 
143  // lets a seek cur
144  //
145  // Put the file pointer at the start of the first elevation post.
146  m_fileStr.seekg(offset, std::ios::beg);
147  // Get the first post.
148  m_fileStr.read((char*)p, sizeof(T));
149 
150  // Get the second post.
151  m_fileStr.read((char*)(p+1), sizeof(T));
152 
153  // Move over to the next column.
154  offset += m_srtmRecordSizeInBytes;
155 
156  m_fileStr.seekg(offset, std::ios::beg);
157 
158  // Get the third post.
159  m_fileStr.read((char*)(p+2), sizeof(T));
160 
161  // Get the fourth post.
162  m_fileStr.read((char*)(p+3), sizeof(T));
163 
164  if(m_fileStr.fail())
165  {
166  return ossim::nan();
167  }
168  }
169  if (m_swapper)
170  {
171  m_swapper->swap((T*)p, 4);
172  }
173 
174  p00 = p[0];
175  p01 = p[1];
176  p10 = p[2];
177  p11 = p[3];
178 
179  // Perform bilinear interpolation:
180 
181  double xt0 = xi - x0;
182  double yt0 = yi - y0;
183  double xt1 = 1-xt0;
184  double yt1 = 1-yt0;
185 
186  double w00 = xt1*yt1;
187  double w01 = xt0*yt1;
188  double w10 = xt1*yt0;
189  double w11 = xt0*yt0;
190 
191  //***
192  // Test for null posts and set the corresponding weights to 0:
193  //***
194  if (p00 == theNullHeightValue)
195  w00 = 0.0;
196  if (p01 == theNullHeightValue)
197  w01 = 0.0;
198  if (p10 == theNullHeightValue)
199  w10 = 0.0;
200  if (p11 == theNullHeightValue)
201  w11 = 0.0;
202 
203 #if 0 /* Serious debug only... */
204  cout << "\np00: " << p00
205  << "\np01: " << p01
206  << "\np10: " << p10
207  << "\np11: " << p11
208  << "\nw00: " << w00
209  << "\nw01: " << w01
210  << "\nw10: " << w10
211  << "\nw11: " << w11
212  << endl;
213 #endif
214 
215  double sum_weights = w00 + w01 + w10 + w11;
216 
217  if (sum_weights)
218  {
219  return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights;
220  }
221 
222  return ossim::nan();
223 }
224 
225 
226 template <class T>
228  const ossimGpt& gpt)
229 {
230  // Establish the grid indexes:
231  double xi = (gpt.lon - m_nwCornerPost.lon) / m_lonSpacing;
232  double yi = (m_nwCornerPost.lat - gpt.lat) / m_latSpacing;
233 
234  int x0 = static_cast<int>(xi);
235  int y0 = static_cast<int>(yi);
236 
237  if(x0 == (m_numberOfSamples-1))
238  {
239  --x0; // Move over one post.
240  }
241 
242  // Check for top edge.
243  // if (gpt.lat == theGroundRect.ul().lat)
244  if(y0 == (m_numberOfLines-1))
245  {
246  --y0; // Move down one post.
247  }
248 #if 0
249  // Check for right edge.
251  {
252  --x0; // Move over one post to the left.
253  }
254 
255  // Check for bottom edge.
257  {
258  --y0; // Move up one post.
259  }
260 #endif
261  // Do some error checking.
262  if ( xi < 0.0 || yi < 0.0 ||
263  x0 > (m_numberOfSamples - 2.0) ||
264  y0 > (m_numberOfLines - 2.0) )
265  {
266  // std::cout << "ossimSrtmHandler::getHeightAboveMSLTemplate: leaving 1" << std::endl;
267  return ossim::nan();
268  }
269 
270  // Grab the four points from the srtm cell needed.
271  ossim_uint64 offset = y0 * m_srtmRecordSizeInBytes + x0 * sizeof(T);
272  ossim_uint64 offset2 =offset+m_srtmRecordSizeInBytes;
273  T v00 = *(reinterpret_cast<T*> (&m_memoryMap[offset]));
274  T v01 = *(reinterpret_cast<T*> (&m_memoryMap[offset + sizeof(T)]));
275  T v10 = *(reinterpret_cast<T*> (&m_memoryMap[offset2]));
276  T v11 = *(reinterpret_cast<T*> (&m_memoryMap[offset2 + sizeof(T)]));
277  if (m_swapper)
278  {
279  m_swapper->swap(v00);
280  m_swapper->swap(v01);
281  m_swapper->swap(v10);
282  m_swapper->swap(v11);
283  }
284  double p00 = v00;
285  double p01 = v01;
286  double p10 = v10;
287  double p11 = v11;
288 
289  double xt0 = xi - x0;
290  double yt0 = yi - y0;
291  double xt1 = 1-xt0;
292  double yt1 = 1-yt0;
293 
294  double w00 = xt1*yt1;
295  double w01 = xt0*yt1;
296  double w10 = xt1*yt0;
297  double w11 = xt0*yt0;
298 
299  //***
300  // Test for null posts and set the corresponding weights to 0:
301  //***
302  if (p00 == theNullHeightValue)
303  w00 = 0.0;
304  if (p01 == theNullHeightValue)
305  w01 = 0.0;
306  if (p10 == theNullHeightValue)
307  w10 = 0.0;
308  if (p11 == theNullHeightValue)
309  w11 = 0.0;
310 
311 #if 0 /* Serious debug only... */
312  cout << "\np00: " << p00
313  << "\np01: " << p01
314  << "\np10: " << p10
315  << "\np11: " << p11
316  << "\nw00: " << w00
317  << "\nw01: " << w01
318  << "\nw10: " << w10
319  << "\nw11: " << w11
320  << endl;
321 #endif
322 
323  double sum_weights = w00 + w01 + w10 + w11;
324 
325  if (sum_weights)
326  {
327  return (p00*w00 + p01*w01 + p10*w10 + p11*w11) / sum_weights;
328  }
329 
330  return ossim::nan();
331 }
332 
333 double ossimSrtmHandler::getPostValue(const ossimIpt& /* gridPt */) const
334 {
336  << "ossimSrtmHandler::getPostValue(const ossimIpt& gridPt): NEED TO IMPLEMENT TO NEW INTERFACE\n";
337 
338  return theNullHeightValue;
339 #if 0
340  static const char MODULE[] = "ossimSrtmHandler::getPostValue";
341 
342  if(!theFileStr.valid()) return ossim::nan();
343 
344  // Do some error checking.
345  if ( gridPt.x < 0.0 || gridPt.y < 0.0 ||
346  gridPt.x > (theNumberOfSamples - 1) ||
347  gridPt.y > (theNumberOfLines - 1) )
348  {
349  if(traceDebug())
350  {
352  << "WARNING " << MODULE << ": No intersection..." << std::endl;
353  }
354  return ossim::nan();
355  }
356 
357  if (!isOpen())
358  {
359  return ossim::nan();
360  }
361 
362  std::streampos offset = gridPt.y * theSrtmRecordSizeInBytes + gridPt.x * 2;
363 
364  // Put the file pointer at the start of the first elevation post.
365  m_fileStr.seekg(offset, std::ios::beg);
366 
367  ossim_sint16 p;
368 
369  // Get the post.
370  m_fileStr.read((char*)&p, 2);
371  if (theSwapper)
372  {
373  theSwapper->swap(p);
374  }
375  return p;
376 #endif
377 }
378 
380 {
382 }
383 
386 m_supportData(src.m_supportData),
387 m_streamOpen(src.m_streamOpen),
388 m_numberOfLines(src.m_numberOfLines),
389 m_numberOfSamples(src.m_numberOfSamples),
390 m_srtmRecordSizeInBytes(src.m_srtmRecordSizeInBytes),
391 m_latSpacing(src.m_latSpacing),
392 m_lonSpacing(src.m_lonSpacing),
393 m_nwCornerPost(src.m_nwCornerPost),
394 m_swapper(src.m_swapper?new ossimEndian:0),
395 m_scalarType(src.m_scalarType),
396 m_memoryMap(src.m_memoryMap)
397 {
398  if(m_memoryMap.empty()&&src.isOpen())
399  {
400  m_fileStr.open(src.getFilename().c_str(),
401  std::ios::binary|std::ios::in);
402  }
403 }
404 
406 {
407  if(!m_memoryMap.empty()) return true;
408 
409  std::lock_guard<std::mutex> lock(m_fileStrMutex);
410  return m_streamOpen;
411  // return (m_fileStr.is_open());
412 }
413 
414 
415 bool ossimSrtmHandler::open(const ossimFilename& file, bool memoryMapFlag)
416 {
417  theFilename = file;
419  if (!m_supportData.setFilename(file, false) )
420  {
422  return false;
423  }
424  if(m_swapper) {delete m_swapper;m_swapper=0;}
426  // SRTM is stored in big endian.
428  {
429  m_swapper = new ossimEndian();
430  }
431  m_streamOpen = false;
442  0.0),
444  m_nwCornerPost.lon+1.0,
445  0.0));
447 
448  // Set the base class null height value.
449  theNullHeightValue = -32768.0;
450 
451  m_fileStr.clear();
452  m_fileStr.open(theFilename.c_str(), std::ios::in | std::ios::binary);
453  if(!m_fileStr)
454  {
455  return false;
456  }
457 
458  if(memoryMapFlag)
459  {
460  m_memoryMap.resize(theFilename.fileSize());
461  m_fileStr.read((char*)&m_memoryMap.front(), (streamsize)m_memoryMap.size());
462  m_fileStr.close();
463  }
464  m_streamOpen = true;
465  // Capture the stream state for non-const is_open on old compiler.
466 
467  return m_streamOpen;
468 #if 0
469  // theMinHeightAboveMSL;
470  // theMaxHeightAboveMSL;
471  if(theFileStr.valid())
472  {
473  if(!m_fileStr.fail())
474  {
475  return true;
476  }
477  }
478  theFileStr = 0;
479 
480 
481  theFileStr = ossimStreamFactoryRegistry::instance()->createNewIFStream(theFilename,
482  std::ios::in | std::ios::binary);
483 
484  if(theFileStr.valid())
485  {
486  return (!m_fileStr.fail());
487  }
488  return false;
489 #endif
490 }
491 
493 {
494  m_fileStr.close();
495  m_memoryMap.clear();
496  m_streamOpen = false;
497 }
ossimSrtmSupportData m_supportData
double getHeightAboveMSLFileTemplate(T dummy, const ossimGpt &gpt)
ossim_int32 m_numberOfLines
std::vector< ossim_int8 > m_memoryMap
double getHeightAboveMSLMemoryTemplate(T dummy, const ossimGpt &gpt)
virtual const ossimFilename & getFilename() const
ossim_float64 getSouthwestLatitude() const
ossim_float64 getSouthwestLongitude() const
ossim_int64 fileSize() const
float ossim_float32
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
double y
Definition: ossimDpt.h:165
ossimScalarType m_scalarType
16 bit signed integer
ossim_uint32 getNumberOfSamples() const
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
static const ossimErrorCode OSSIM_ERROR
32 bit floating point
bool m_streamOpen
true if stream is open.
virtual bool open(const ossimFilename &file, bool memoryMapFlag=false)
Opens a stream to the srtm cell.
ossimSrtmHandler()
Constructor that takes a file name.
virtual ~ossimSrtmHandler()
destructor
virtual ossimIpt getSizeOfElevCell() const
METHOD: getSizeOfElevCell Returns the number of post in the cell.
virtual void close()
Closes the stream to the file.
ossimGrect theGroundRect
double lat
Definition: ossimDpt.h:165
ossim_float64 lon
Definition: ossimGpt.h:266
signed short ossim_sint16
ossim_int32 m_srtmRecordSizeInBytes
unsigned long long ossim_uint64
ossimFilename theFilename
Virtual method for reading.
OSSIM_DLL ossim_uint32 scalarSizeInBytes(ossimScalarType scalarType)
std::mutex m_fileStrMutex
double lon
Definition: ossimDpt.h:164
ossim_int32 m_numberOfSamples
ossim_uint32 getNumberOfLines() const
virtual double getPostValue(const ossimIpt &gridPt) const
METHOD: getPostValue Returns the value at a given grid point as a double.
for an srtm file.
ossim_float64 getLatitudeSpacing() const
std::ifstream m_fileStr
ossimEndian * m_swapper
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
ossimScalarType getScalarType() const
ossimDpt metersPerDegree() const
Definition: ossimGpt.cpp:498
ossim_float64 lat
Definition: ossimGpt.h:265
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
const ossimGpt & lr() const
Definition: ossimGrect.h:269
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
virtual bool isOpen() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_float64 getLongitudeSpacing() const
virtual double getHeightAboveMSL(const ossimGpt &)
METHOD: getHeightAboveMSL Height access methods.
bool setFilename(const ossimFilename &srtmFile, bool scanForMinMax=false)
Initializes object from file.