OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageElevationDatabase.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // File: ossimImageElevationDatabase.cpp
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 // Author: David Burken
10 //
11 // Description: See class desciption in header file.
12 //
13 //----------------------------------------------------------------------------
14 // $Id$
15 
17 #include <ossim/base/ossimDpt.h>
18 #include <ossim/base/ossimString.h>
19 #include <ossim/base/ossimTrace.h>
22 #include <cmath>
23 
24 static ossimTrace traceDebug(ossimString("ossimImageElevationDatabase:debug"));
25 
27 
29  :
32  m_entryMap(),
33  m_lastMapKey(0),
34  m_lastAccessedId(0)
35 {
36 }
37 
38 // Protected destructor as this is derived from ossimRefenced.
40 {
41 }
42 
43 bool ossimImageElevationDatabase::open(const ossimString& connectionString)
44 {
45  // return false; // tmp drb...
46 
47  static const char M[] = "ossimImageElevationDatabase::open";
48  if(traceDebug())
49  {
51  << M << " entered...\n"
52  << "\nConnection string: " << connectionString << "\n";
53  }
54 
55  bool result = false;
56 
57  close();
58 
59  if ( connectionString.size() )
60  {
61  m_connectionString = connectionString.c_str();
62 
63  loadFileMap();
64 
65  if ( m_entryMap.size() )
66  {
67  result = true;
68  }
69  else
70  {
72  }
73  }
74 
75  if(traceDebug())
76  {
77  ossimNotify(ossimNotifyLevel_DEBUG) << M << " result=" << (result?"true\n":"false\n");
78  }
79 
80  return result;
81 }
82 
84 {
85  m_meanSpacing = 0.0;
86  m_geoid = 0;
88 }
89 
91 {
92  double h = ossim::nan();
93  if(isSourceEnabled())
94  {
96  if(handler.valid())
97  {
98  h = handler->getHeightAboveMSL(gpt); // still need to shift
99 
100  // Save the elev source's post spacing as the database's mean spacing:
101  m_meanSpacing = handler->getMeanSpacingMeters();
102  }
103  }
104 
105  return h;
106 }
107 
109 {
110  double h = getHeightAboveMSL(gpt);
111  if(!ossim::isnan(h))
112  {
113  h += getOffsetFromEllipsoid(gpt);
114  }
115  return h;
116 }
117 
119  const ossimGpt& gpt)
120 {
122 
123  // Need to disable elevation while loading the DEM image to prevent recursion:
124  disableSource();
125 
126  std::map<ossim_uint64, ossimImageElevationFileEntry>::iterator i = m_entryMap.begin();
127  while ( i != m_entryMap.end() )
128  {
129  if ( (*i).second.m_loadedFlag == false )
130  {
131  // not loaded
133 
134  if ( (*i).second.m_rect.isLonLatNan() )
135  {
136  if ( h->open( (*i).second.m_file ) )
137  {
138  // First time opened. Capture the rectangle. for next time.
139  (*i).second.m_rect = h->getBoundingGndRect();
140  }
141  else
142  {
144  << "ossimImageElevationDatabase::createCell WARN:\nCould not open: "
145  << (*i).second.m_file << "\nRemoving file from map!" << std::endl;
146 
147  // Get a copy of the iterator to delet.
148  std::map<ossim_uint64, ossimImageElevationFileEntry>::iterator badIter = i;
149 
150  ++i; // Go to next image.
151 
152  // Must put lock around erase.
153  m_cacheMapMutex.lock();
154  m_entryMap.erase(badIter);
155  m_cacheMapMutex.unlock();
156 
157  continue; // Skip the rest of this loop.
158  }
159  }
160 
161  // Check the North up bounding rectangle for intersect.
162  if ( (*i).second.m_rect.pointWithin(gpt) )
163  {
164  if ( h->isOpen() == false )
165  {
166  h->open( (*i).second.m_file );
167  }
168 
169  if ( h->isOpen() )
170  {
171  //---
172  // Check point coverage again as image may not be geographic and pointHasCoverage
173  // has a check on worldToLocal point.
174  //---
175  if ( h->pointHasCoverage(gpt) )
176  {
177  m_lastAccessedId = (*i).first;
178  (*i).second.m_loadedFlag = true;
179  result = h.get();
180  break;
181  }
182  else
183  {
184  h = 0;
185  }
186  }
187  }
188  else
189  {
190  h = 0;
191  }
192  }
193 
194  ++i;
195  }
196 
197  enableSource();
198  return result;
199 }
200 
202  const ossimGpt& gpt)
203 {
205 
206  // Note: Must do mutex lock / unlock around any cach map access.
207  m_cacheMapMutex.lock();
208 
209  if ( m_cacheMap.size() )
210  {
211  //---
212  // Look in existing map for handler.
213  //
214  // Note: Cannot key off of id from gpt as cells can be any arbituary dimensions.
215  //---
216 
217  CellMap::iterator lastAccessedCellIter = m_cacheMap.find(m_lastAccessedId);
218  CellMap::iterator iter = lastAccessedCellIter;
219 
220  // Check from last accessed to end.
221  while ( iter != m_cacheMap.end() )
222  {
223  if ( iter->second->m_handler->pointHasCoverage(gpt) )
224  {
225  result = iter->second->m_handler.get();
226  break;
227  }
228  ++iter;
229  }
230 
231  if ( result.valid() == false )
232  {
233  iter = m_cacheMap.begin();
234 
235  // Beginning to last accessed.
236  while ( iter != lastAccessedCellIter)
237  {
238  if ( iter->second->m_handler->pointHasCoverage(gpt) )
239  {
240  result = iter->second->m_handler.get();
241  break;
242  }
243  ++iter;
244  }
245  }
246 
247  if ( result.valid() )
248  {
249  m_lastAccessedId = iter->second->m_id;
250  iter->second->updateTimestamp();
251  }
252  }
253  m_cacheMapMutex.unlock();
254 
255  if ( result.valid() == false )
256  {
257  // Not in m_cacheMap. Create a new cell for point if we have coverage.
258  result = createCell(gpt);
259 
260  if(result.valid())
261  {
262  std::lock_guard<std::mutex> lock(m_cacheMapMutex);
263 
264  //---
265  // Add the cell to map.
266  // NOTE: ossimImageElevationDatabase::createCell sets m_lastAccessedId to that of
267  // the entries map key.
268  //---
269  m_cacheMap.insert(std::make_pair(m_lastAccessedId,
270  new CellInfo(m_lastAccessedId, result.get())));
271 
272  ++m_lastMapKey;
273 
274  // Check the map size and purge cells if needed.
275  if(m_cacheMap.size() > m_maxOpenCells)
276  {
278  }
279  }
280  }
281 
282  return result;
283 }
284 
286 {
287  //---
288  // NOTE:
289  //
290  // The bounding rect is the North up rectangle. So if the underlying image projection is not
291  // a geographic projection and there is a rotation this could return false positives. Inside
292  // the ossimImageElevationDatabase::createCell there is a call to
293  // ossimImageElevationHandler::pointHasCoverage which does a real check from the
294  // ossimImageGeometry of the image.
295  //---
296  bool result = false;
297  std::map<ossim_uint64, ossimImageElevationFileEntry>::const_iterator i = m_entryMap.begin();
298  while ( i != m_entryMap.end() )
299  {
300  if ( (*i).second.m_rect.pointWithin(gpt) )
301  {
302  result = true;
303  break;
304  }
305  ++i;
306  }
307  return result;
308 }
309 
310 
312 {
313  // The bounding rect is the North up rectangle. So if the underlying image projection is not
314  // a geographic projection and there is a rotation this will include null coverage area.
315  rect.makeNan();
316  std::map<ossim_uint64, ossimImageElevationFileEntry>::const_iterator i = m_entryMap.begin();
317  ossimGrect subRect;
318  while ( i != m_entryMap.end() )
319  {
320  subRect = i->second.m_rect;
321  if (subRect.isLonLatNan())
322  {
323  // The DEM source was not yet initialized:
325  if ( h->open( i->second.m_file ) )
326  subRect = h->getBoundingGndRect();
327  else
328  {
329  ++i;
330  continue;
331  }
332  }
333  if (rect.isLonLatNan())
334  rect = subRect;
335  else
336  rect = rect.combine(subRect);
337  ++i;
338  }
339 }
340 
341 
343 {
344  if(pointHasCoverage(gpt))
345  {
346  info.m_surfaceName = "Image Elevation";
347  }
348 
349  return false;
350 }
351 
352 bool ossimImageElevationDatabase::loadState(const ossimKeywordlist& kwl, const char* prefix)
353 {
354  static const char M[] = "ossimImageElevationDatabase::loadState";
355  if(traceDebug())
356  {
358  << M << " entered..." << "\nkwl:\n" << kwl << "\n";
359  }
360  bool result = false;
361  const char* lookup = kwl.find(prefix, "type");
362  if ( lookup )
363  {
364  std::string type = lookup;
365  if ( ( type == "image_directory" ) || ( type == "ossimImageElevationDatabase" ) )
366  {
367  result = ossimElevationCellDatabase::loadState(kwl, prefix);
368 
369  if ( result )
370  {
371  loadFileMap();
372  }
373  }
374  }
375 
376  if(traceDebug())
377  {
378  ossimNotify(ossimNotifyLevel_DEBUG) << M << " result=" << (result?"true\n":"false\n");
379  }
380 
381  return result;
382 }
383 
384 bool ossimImageElevationDatabase::saveState(ossimKeywordlist& kwl, const char* prefix) const
385 {
386  return ossimElevationCellDatabase::saveState(kwl, prefix);
387 }
388 
390 {
391  static const char M[] = "ossimImageElevationDatabase::processFile";
392  if(traceDebug())
393  {
395  << M << " entered...\n" << "file: " << file << "\n";
396  }
397 
398  // Add the file.
399  m_entryMap.insert( std::make_pair(m_lastMapKey++, ossimImageElevationFileEntry(file)) );
400 
401  if(traceDebug())
402  {
403  // Since ossimFileWalker is threaded output the file so we know which job exited.
404  ossimNotify(ossimNotifyLevel_DEBUG) << M << "\nfile: " << file << "\nexited...\n";
405  }
406 }
407 
409 {
410  if ( m_connectionString.size() )
411  {
412  // Create a file walker which will find files we can load from the connection string.
413  ossimFileWalker* fw = new ossimFileWalker();
414 
416 
417  // This links the file walker back to our "processFile" method.
418  fw->setFileProcessor( this );
419 
421 
422  // ossimFileWalker::walk will in turn call back to processFile method for each file it finds.
423  fw->walk(f);
424 
425  delete fw;
426  fw = 0;
427  }
428 }
429 
430 // Hidden from use:
433 {
434  m_entryMap = copy.m_entryMap;
435  m_lastMapKey = copy.m_lastMapKey;
437 }
438 
439 // Private container class:
441  : m_file(),
442  m_rect(),
443  m_loadedFlag(false)
444 {
445  m_rect.makeNan();
446 }
447 
448 // Private container class:
450  const ossimFilename& file)
451  : m_file(file),
452  m_rect(),
453  m_loadedFlag(false)
454 {
455  m_rect.makeNan();
456 }
457 
460  : m_file(copy_this.m_file),
461  m_rect(copy_this.m_rect),
462  m_loadedFlag(copy_this.m_loadedFlag)
463 {
464 }
465 
467 {
468  ossimKeywordlist kwl;
469  saveState(kwl);
470  out << "\nossimImageElevationDatabase @ "<< (ossim_uint64) this << "\n"
471  << kwl <<ends;
472  return out;
473 }
474 
void clear()
Erases the entire container.
Definition: ossimString.h:432
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual ~ossimImageElevationDatabase()
Protected destructor.
virtual double getHeightAboveMSL(const ossimGpt &)=0
Height access methods:
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Statisfies pure virtual ossimElevSource::getAccuracyLE90.
virtual double getMeanSpacingMeters() const
METHOD: meanSpacingMeters() Implements pure virtual for.
virtual ossimRefPtr< ossimElevCellHandler > getOrCreateCellHandler(const ossimGpt &gpt)
Gets cell for point.
void setFileProcessor(ossimFileProcessorInterface *fpi)
Sets ossimFileProcessorInterfacecallback method to process files.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Save the state to a keyword list.
Represents serializable keyword/value map.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
void makeNan()
Definition: ossimGrect.h:284
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual void disableSource()
Definition: ossimSource.cpp:89
bool m_loadedFlag
True if in ossimElevationCellDatabase::m_cacheMap.
Utility class to walk through directories and get a list of files to process.
virtual void close()
close method.
virtual const ossimGrect & getBoundingGndRect() const
METHODS: accuracyLE90(), accuracyCE90() Returns the vertical and horizontal accuracy (90% confidence)...
virtual bool pointHasCoverage(const ossimGpt &) const
pointHasCoverage(gpt)
void getBoundingRect(ossimGrect &rect) const
Gets the bounding rectangle/coverage of elevation.
Elevation source for a generic image opened via ossimImageHandler.
std::map< ossim_uint64, ossimImageElevationFileEntry > m_entryMap
ossimRefPtr< ossimGeoid > m_geoid
std::string::size_type size() const
Definition: ossimString.h:405
RTTI_DEF1(ossimImageElevationDatabase, "ossimImageElevationDatabase", ossimElevationCellDatabase)
unsigned long long ossim_uint64
virtual ossimRefPtr< ossimElevCellHandler > createCell(const ossimGpt &gpt)
virtual double getHeightAboveEllipsoid(const ossimGpt &)
Get height above ellipsoid for point.
virtual void enableSource()
Definition: ossimSource.cpp:84
virtual void processFile(const ossimFilename &file)
ProcessFile method.
void initializeDefaultFilterList()
Initializes the filter list with a default set of filtered out file names.
ossimGrect m_rect
Bounding rectangle in decimal degrees.
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
void loadFileMap()
Initializes m_entryMap with all loadable files from m_connectionString.
ossimGrect combine(const ossimGrect &rect) const
Definition: ossimGrect.h:213
virtual double getOffsetFromEllipsoid(const ossimGpt &gpt)
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
virtual bool open(const ossimString &connectionString)
Open a connection to a database.
ossimImageElevationDatabase()
default constructor
bool isLonLatNan() const
Definition: ossimGrect.h:290
virtual bool open(const ossimFilename &file)
Opens a stream to the srtm cell.
virtual bool pointHasCoverage(const ossimGpt &gpt) const
Satisfies pure virtual ossimElevSource::pointHasCoverage.
virtual double getHeightAboveMSL(const ossimGpt &gpt)
Get height above MSL for point.
void walk(const std::vector< ossimFilename > &files)
Takes an array of files.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
virtual bool getAccuracyInfo(ossimElevationAccuracyInfo &info, const ossimGpt &gpt) const