OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimElevManager.cpp
Go to the documentation of this file.
1 //**************************************************************************
2 // FILE: ossimElevManager.cpp
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // DESCRIPTION:
9 // Contains implementation of class ossimElevManager. This object
10 // provides a single interface for accessing multiple elevation
11 // sources. This object owns one or more elevation sources in an ordered
12 // list. When queried for an elevation at a particular point, it searches
13 // the available sources for the best result, instantiating new sources if
14 // necessary.
15 //
16 // SOFTWARE HISTORY:
17 //>
18 // 23Apr2001 Oscar Kramer
19 // Initial coding.
20 //<
21 //**************************************************************************
22 // $Id: ossimElevManager.cpp 23641 2015-12-02 20:32:06Z dburken $
23 
28 #include <ossim/base/ossimTrace.h>
32 #include <algorithm>
33 
34 //ossimElevManager* ossimElevManager::m_instance = 0;
35 static ossimTrace traceDebug("ossimElevManager:debug");
36 
37 //---
38 // For std::sort of ElevationDatabaseListType
39 // e.g.: std::sort( dbList.begin(), dbList.end(), dbSort );
40 //---
42 {
43  bool result = false;
44  if ( a.valid() && b.valid() )
45  {
46  result = ( a->getMeanSpacingMeters() < b->getMeanSpacingMeters() );
47  }
48  return result;
49 }
50 
52  :
53  m_connectionString(value),
54  m_database(0)
55 {}
56 
58 {
59  if(!hasVisited(obj))
60  {
61  ossimElevationDatabase* databsase = dynamic_cast<ossimElevationDatabase*>(obj);
62  if(databsase)
63  {
64  if(m_connectionString == databsase->getConnectionString())
65  {
66  m_database = databsase;
67  m_stopTraversalFlag = true;
68  }
69  }
70  }
71 }
72 
74 {
75  static ossimElevManager inst;
76  return &inst;
77 }
78 
80  :ossimElevSource(),
84  m_useGeoidIfNullFlag(false),
85  m_useStandardPaths(false),
87  m_mutex()
88 {
89  //---
90  // Auto load removed to avoid un-wanted directory scanning.
91  // Use ossim preferences. drb - 28 March 2016.
92  //---
93  // loadStandardElevationPaths();
94 }
95 
97 {
98  clear();
99 }
100 
102 {
103  double result = ossim::nan();
104 
105  if (!isSourceEnabled())
106  return result;
107 
109  for (ossim_uint32 idx = 0; (idx < elevDbList.size()) && ossim::isnan(result); ++idx)
110  {
111  result = elevDbList[idx]->getHeightAboveEllipsoid(gpt);
112  }
113 
114  if (ossim::isnan(result))
115  {
116  // No elevation value was returned from the database, so try next best alternatives depending
117  // on ossim_preferences settings. Priority goes to default ellipsoid height if available:
119  {
121  }
122  else if (m_useGeoidIfNullFlag)
123  {
125  }
126  }
127 
128  // Next, ossim_preferences may have indicated an elevation offset to use (top of trees, error
129  // bias, etc):
130  if (!ossim::isnan(m_elevationOffset) && !ossim::isnan(result))
131  result += m_elevationOffset;
132 
133  return result;
134 }
135 
137 {
138  double result = ossim::nan();
139 
140  if (!isSourceEnabled())
141  return result;
142 
144  for (ossim_uint32 idx = 0; (idx < elevDbList.size()) && ossim::isnan(result); ++idx)
145  {
146  result = elevDbList[idx]->getHeightAboveMSL(gpt);
147  }
148 
149  if (ossim::isnan(result) && m_useGeoidIfNullFlag)
150  {
151  // No elevation value was returned from the database, so try next best alternatives depending
152  // on ossim_preferences settings. First default to height at MSL itself:
153  result = 0.0; // MSL
155  {
156  // Use the default height above ellipsoid corrected for best guess of MSL above ellipsoid
157  // (i.e., the geoid):
159  if (!ossim::isnan(dh))
160  result = m_defaultHeightAboveEllipsoid - dh;
161  }
162  }
163 
164  // ossim_preferences may have indicated an elevation offset to use (top of trees, error bias, etc)
165  if (!ossim::isnan(result) && (!ossim::isnan(m_elevationOffset)))
166  result += m_elevationOffset;
167 
168  return result;
169 }
170 
172 {
173  if (!m_useStandardPaths)
174  return;
175 
178 
179  userDir = userDir.dirCat("elevation");
180  installDir = installDir.dirCat("elevation");
181 
182  loadElevationPath(userDir);
183  loadElevationPath(installDir);
184 
185  ossimString paths = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_ELEVATION_PATH");
186  std::vector<ossimString> pathArray;
187  ossimString pathSeparator = ":";
188 #if defined(WIN32) && !defined(CYGWIN)
189  pathSeparator = ";";
190 #endif
191 
192  if(!paths.empty())
193  {
194  paths.split(pathArray, pathSeparator);
195  if(!pathArray.empty())
196  {
197  ossim_uint32 idx = 0;
198  for(idx = 0; idx < pathArray.size(); ++idx)
199  {
200  ossimFilename file(pathArray[idx]);
201 
202  if(file.exists())
203  {
204  loadElevationPath(file);
205  }
206  }
207  }
208  }
209 }
210 
211 bool ossimElevManager::loadElevationPath(const ossimFilename& path, bool set_as_first)
212 {
213  bool result = false;
215 
216  if(!database && path.isDir())
217  {
218  ossimDirectory dir;
219 
220  if(dir.open(path))
221  {
222  ossimFilename file;
224  do
225  {
227  if(database)
228  {
229  result = true;
230  addDatabase(database, set_as_first);
231  }
232  }while(dir.getNext(file));
233  }
234  }
235  else if(database)
236  {
237  result = true;
238  addDatabase(database, set_as_first);
239  }
240 
241  return result;
242 }
243 
244 void ossimElevManager::getOpenCellList(std::vector<ossimFilename>& list) const
245 {
246  if ( m_dbRoundRobin.size() )
247  {
248  ElevationDatabaseListType& elevDbList = m_dbRoundRobin[0];
249  for(ossim_uint32 idx = 0; idx < elevDbList.size(); ++idx)
250  {
251  // If this is a cell based database get the files:
253  dynamic_cast<const ossimElevationCellDatabase*>( elevDbList[idx].get() );
254  if ( db.valid() )
255  {
256  db->getOpenCellList(list);
257  }
258  }
259  }
260 }
261 
262 void ossimElevManager::getCellsForBounds( const std::string& connectionString,
263  const ossim_float64& minLat,
264  const ossim_float64& minLon,
265  const ossim_float64& maxLat,
266  const ossim_float64& maxLon,
267  std::vector<ossimFilename>& cells,
268  ossim_uint32 maxNumberOfCells)
269 {
271 
272  // See if the connectionString is already opened:
273  ossimString os = connectionString;
275  accept( visitor );
276  cellDatabase = dynamic_cast<ossimElevationCellDatabase*>( visitor.getElevationDatabase() );
277 
278  if ( cellDatabase.valid() == false )
279  {
280  // Try to open it:
283 
284  if ( db.valid() )
285  {
286  cellDatabase = dynamic_cast<ossimElevationCellDatabase*>( db.get() );
287  }
288  }
289 
290  // Lastly get the files:
291  if ( cellDatabase.valid() )
292  {
293  cellDatabase->getCellsForBounds( minLat, minLon, maxLat, maxLon, cells, maxNumberOfCells );
294  }
295  else
296  {
297  // Bummer:
298  cells.clear();
299  }
300 }
301 
303  const ossim_float64& minLon,
304  const ossim_float64& maxLat,
305  const ossim_float64& maxLon,
306  std::vector<ossimFilename>& cells,
307  ossim_uint32 maxNumberOfCells )
308 {
309  //TODO: Presently incrementing by 0.1 deg. If an elev cell
310  // is smaller than this, it may be missed. Need to generalize to support arbitrary cell sizes.
311 
312  //TODO: This method relies on the caching of open cells. If the bounds are too large too permit
313  // all cells to remain open, this method will incorrectly return a subset of all cells providing
314  // coverage.
315 
316  // Ping the collection of databases for elevation values at regular intervals inside the bounds.
317  // This will autoload the best cells:
318  cells.clear();
319  const ossim_float64 DELTA_DEG = 0.1; // degree
320  ossimGpt gpt;
321  for (gpt.lat=minLat; gpt.lat<=maxLat; gpt.lat+=DELTA_DEG)
322  {
323  for (gpt.lon=minLon; gpt.lon<=maxLon; gpt.lon+=DELTA_DEG)
324  {
325  getHeightAboveMSL(gpt);
326  }
327  }
328 
329  // Convert filename list to string list (why are they different)?
330  ossim_uint32 limitCells = maxNumberOfCells>0?maxNumberOfCells:static_cast<ossim_uint32>(9999999999);
331  std::vector<ossimFilename> open_cells;
332  getOpenCellList(open_cells);
333  std::vector<ossimFilename>::iterator iter = open_cells.begin();
334  while ((iter != open_cells.end()) && (cells.size() < limitCells))
335  {
336  cells.push_back(*iter);
337  ++iter;
338  }
339 }
340 
341 
343  std::vector<ossimFilename>& cells,
344  ossim_uint32 maxCells)
345 {
346  getCellsForBounds(bbox.lr().lat, bbox.ul().lon, bbox.ul().lat, bbox.lr().lon, cells, maxCells);
347 }
348 
350 {
351  std::vector<ElevationDatabaseListType>::iterator i = m_dbRoundRobin.begin();
352  while ( i != m_dbRoundRobin.end() )
353  {
354  i->clear();
355  ++i;
356  }
357 }
358 
360 {
361  std::vector<ElevationDatabaseListType>::iterator rri = m_dbRoundRobin.begin();
362  while ( rri != m_dbRoundRobin.end() )
363  {
364  ElevationDatabaseListType& elevDbList = *rri;
365 
366  ossimElevManager::ElevationDatabaseListType::iterator i = elevDbList.begin();
367  while ( i != elevDbList.end() )
368  {
369  if ( (*i).valid() )
370  {
371  (*i)->accept( visitor );
372 
373  if ( visitor.stopTraversal() )
374  {
375  break;
376  }
377  }
378  ++i;
379  }
380  ++rri;
381  }
382 }
383 
385 {
387  for(ossim_uint32 idx = 0;(idx < elevDbList.size()); ++idx)
388  {
389  if(elevDbList[idx]->getAccuracyInfo(info, gpt))
390  {
391  return true;
392  }
393  }
394 
395  return false;
396 }
397 
399 {
400  if ( m_dbRoundRobin.size() )
401  {
402  ElevationDatabaseListType& elevDbList = m_dbRoundRobin[0];
403  for(ossim_uint32 idx = 0;(idx < elevDbList.size()); ++idx)
404  {
405  if(elevDbList[idx]->pointHasCoverage(gpt))
406  {
407  return true;
408  }
409  }
410  }
411  return false;
412 }
413 
414 bool ossimElevManager::saveState(ossimKeywordlist& kwl, const char* prefix) const
415 {
416  kwl.add(prefix, "elevation_offset", m_elevationOffset, true);
417  kwl.add(prefix, "default_height_above_ellipsoid", m_defaultHeightAboveEllipsoid, true);
418  kwl.add(prefix, "use_geoid_if_null", m_useGeoidIfNullFlag, true);
419  kwl.add(prefix, "use_standard_elev_paths", m_useStandardPaths, true);
420  kwl.add(prefix, "threads", ossimString::toString(m_maxRoundRobinSize), true);
421 
422  return ossimElevSource::saveState(kwl, prefix);
423 }
424 
429 bool ossimElevManager::loadState(const ossimKeywordlist& kwl, const char* prefix)
430 {
431  if (traceDebug())
432  {
434  << "DEBUG ossimElevManager::loadState: Entered..."
435  << std::endl;
436  }
437  if(!ossimElevSource::loadState(kwl, prefix))
438  {
439  return false;
440  }
441  ossimString copyPrefix(prefix);
442  ossimString elevationOffset = kwl.find(copyPrefix, "elevation_offset");
443  ossimString defaultHeightAboveEllipsoid = kwl.find(copyPrefix, "default_height_above_ellipsoid");
444  ossimString elevRndRbnSize = kwl.find(copyPrefix, "threads");
445 
446  kwl.getBoolKeywordValue(m_useGeoidIfNullFlag, "use_geoid_if_null", copyPrefix.chars());
447  kwl.getBoolKeywordValue(m_useStandardPaths, "use_standard_elev_paths", copyPrefix.chars());
448 
449  if(!elevationOffset.empty())
450  m_elevationOffset = elevationOffset.toDouble();
451 
452  if(!defaultHeightAboveEllipsoid.empty())
453  m_defaultHeightAboveEllipsoid = defaultHeightAboveEllipsoid.toDouble();
454 
455  ossim_uint32 numThreads = 1;
456  if(!elevRndRbnSize.empty())
457  {
458  if (elevRndRbnSize.contains("yes") || elevRndRbnSize.contains("true"))
459  numThreads = ossim::getNumberOfThreads();
460  else if (elevRndRbnSize.contains("no") || elevRndRbnSize.contains("false"))
461  numThreads = 1;
462  else
463  {
464  numThreads = elevRndRbnSize.toUInt32();
465  numThreads = numThreads > 0 ? numThreads : 1;
466  }
467  }
468  setRoundRobinMaxSize(numThreads);
469 
470  ossimString regExpression = ossimString("^(") + copyPrefix + "elevation_source[0-9]+.)";
471  vector<ossimString> keys = kwl.getSubstringKeyList( regExpression );
472  long numberOfSources = (long)keys.size();
473  ossim_uint32 offset = (ossim_uint32)(copyPrefix+"elevation_source").size();
474  ossim_uint32 idx = 0;
475  std::vector<int> theNumberList(numberOfSources);
476  for(idx = 0; idx < theNumberList.size();++idx)
477  {
478  ossimString numberStr(keys[idx].begin() + offset,
479  keys[idx].end());
480  theNumberList[idx] = numberStr.toInt();
481  }
482  std::sort(theNumberList.begin(), theNumberList.end());
483 
484  for(idx=0;idx < theNumberList.size();++idx)
485  {
486  ossimString newPrefix = copyPrefix;
487  newPrefix += ossimString("elevation_source");
488  newPrefix += ossimString::toString(theNumberList[idx]);
489  if (traceDebug())
490  {
492  << "DEBUG ossimElevManager::loadState:"
493  << "\nLooking for key: " << newPrefix
494  << std::endl;
495  }
496 
497  //---
498  // Check for enabled key first. Default, if not found is true for
499  // legacy compatibility.
500  //---
501  bool enabled = true;
502  std::string key = newPrefix.string();
503  key += ".";
505  std::string value = kwl.findKey( key );
506  if ( value.size() )
507  {
508  enabled = ossimString(value).toBool();
509  }
510 
511  if ( enabled )
512  {
513  // first check if new way is supported
516  if(database.valid())
517  {
518  if (traceDebug())
519  {
521  << "DEBUG ossimElevManager::loadState:"
522  << "\nadding elevation database: "
523  << database->getClassName()
524  << ": " << database->getConnectionString()
525  << std::endl;
526  }
527  addDatabase(database.get());
528  }
529  else
530  {
531  // if not new elevation load verify the old way by
532  // looking at the filename
533  //
534  ossimString fileKey = newPrefix;
535  fileKey += ".";
537  ossimString lookup = kwl.find(prefix, fileKey.c_str());
538  if (!lookup.empty())
539  {
541  } // end if lookup
542  }
543  }
544 
545  } // end for loop
546 
547  return true;
548 }
549 
551 {
552  m_maxRoundRobinSize = new_size;
553 
554 #ifdef DYNAMICALLY_ALLOCATE_ROUND_ROBIN
555  // Resize the round robin, preserves at least the first entry if any:
556  if (new_size < m_dbRoundRobin.size())
557  m_dbRoundRobin.resize(new_size);
558 #else
559  // OLK 02/2015 -- Was hoping to dynamically allocate the round robin as needed but was running
560  // into issues, so just allocating full set here (containing empty lists at this point). The
561  // heavy lifting is in addDatabase() where copies are made for each entry in the round robin. It
562  // would have been best to keep the size of the round robin to an as-needed basis to avoid
563  // unnecessary duplicate lists. However, this is only relevant for small apps (like ossim-info)
564  // where minimal number of elevation look-ups are done. TODO: Figure out why MT run core dumps
565  // when dynamically sizing m_dbRoundRobin.
566  m_dbRoundRobin.resize(new_size);
567 #endif
568 
569 }
570 
572 {
573  std::lock_guard<std::mutex> lock (m_mutex);
574 
575  // Quickly grab the DB to be used by this thread and increment DB index to be used by next thread
576  // May need to grow the list round robin as it is dynamically set as needed):
577  if (m_currentDatabaseIdx >= m_dbRoundRobin.size())
578  {
579  ossim_uint32 index = m_dbRoundRobin.size();
580  m_dbRoundRobin.resize(index+1);
581 
582  // An entry existed prior, duplicate its contents for all Db lists in the round robin. Only
583  // duplicate as needed beyond what already existed:
584  ElevationDatabaseListType::iterator iter = m_dbRoundRobin[0].begin();
585  while (iter != m_dbRoundRobin[0].end())
586  {
588  m_dbRoundRobin[index].push_back(dupDb);
589  ++iter;
590  }
591  }
592 
596 
597  return m_dbRoundRobin[index];
598 }
599 
600 void ossimElevManager::addDatabase(ossimElevationDatabase* database, bool set_as_first)
601 {
602  if(!database)
603  return;
604 
605  if (m_dbRoundRobin.empty())
606  m_dbRoundRobin.resize(1);
607 
608  std::vector<ElevationDatabaseListType>::iterator rri = m_dbRoundRobin.begin();
609  if (std::find(rri->begin(), rri->end(), database) == rri->end())
610  {
611  if (set_as_first)
612  rri->insert(rri->begin(), database);
613  else
614  rri->push_back(database);
615 
616  // Populate the parallel lists in the round-robin with duplicates:
617  ++rri;
618  while ( rri != m_dbRoundRobin.end() )
619  {
621  if (set_as_first)
622  rri->insert(rri->begin(), dupDb);
623  else
624  rri->push_back(dupDb);
625  ++rri;
626  }
627  }
628 }
629 
631 {
632  double spacing = ossim::nan();
633  if ( m_dbRoundRobin.size() )
634  {
635  ElevationDatabaseListType& elevDbList = m_dbRoundRobin[0];
636  for(ossim_uint32 idx = 0;(idx < elevDbList.size()); ++idx)
637  {
638  double d_idx = elevDbList[idx]->getMeanSpacingMeters();
639  if (ossim::isnan(spacing) || (d_idx < spacing))
640  {
641  spacing = d_idx;
642  }
643  }
644  }
645  return spacing;
646 }
647 
649 {
650  out << "\nossimElevManager @ "<< (ossim_uint64) this
651  << "\nm_defaultHeightAboveEllipsoid = "<<m_defaultHeightAboveEllipsoid
652  << "\nm_elevationOffset = "<<m_elevationOffset
653  << "\nm_useGeoidIfNullFlag = "<<m_useGeoidIfNullFlag
654  << "\nm_currentDatabaseIdx = "<<m_currentDatabaseIdx
655  << "\nm_dbRoundRobin.size = "<<m_dbRoundRobin.size();
656  for (ossim_uint32 i=0; i<m_dbRoundRobin.size(); ++i)
657  {
658  out<<"\nm_dbRoundRobin["<<i<<"].size = "<<m_dbRoundRobin[i].size()<<endl;
659  for (ossim_uint32 j=0; j<m_dbRoundRobin[i].size(); ++j)
660  {
661  out<<"m_dbRoundRobin["<<i<<"]["<<j<<"] = ";
662  // GP: We have to separate this line. On MS it will not compile
663  // otherwise
664  m_dbRoundRobin[i][j]->print(out);
665 
666  }
667  out<<endl;
668  }
669  out<<"\n";
671  return out;
672 }
673 
ossimElevationDatabase * getElevationDatabase()
virtual double getMeanSpacingMeters() const
Returns the mean post spacing (in meters) for the highest resolution DEM in the list or NaN if no DEM...
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
static ossimElevationDatabaseRegistry * instance()
virtual void accept(ossimVisitor &visitor)
We will add a visitor interface for all connectable objects.
ossim_float64 m_elevationOffset
virtual bool getAccuracyInfo(ossimElevationAccuracyInfo &info, const ossimGpt &gpt) const
virtual bool pointHasCoverage(const ossimGpt &) const
METHOD: pointHasCoverage(gpt) Returns TRUE if coverage exists over gpt:
void getOpenCellList(std::vector< ossimFilename > &list) const
virtual void visit(ossimObject *obj)
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Definition: ossimSource.cpp:55
bool valid() const
Definition: ossimRefPtr.h:75
bool getFirst(ossimFilename &filename, int flags=OSSIM_DIR_DEFAULT)
ossimFilename getInstalledOssimSupportDir() const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Definition: ossimSource.cpp:66
const char * find(const char *key) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
This code was derived from https://gist.github.com/mshockwave.
Definition: Barrier.h:8
bool contains(char aChar) const
Definition: ossimString.h:58
static ossimString toString(bool aValue)
Numeric to string methods.
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimString getClassName() const
Definition: ossimObject.cpp:64
ossim_uint32 toUInt32() const
static ossimElevManager * instance()
METHOD: instance() Implements singelton pattern.
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
bool isDir() const
bool dbSort(ossimRefPtr< ossimElevationDatabase > a, ossimRefPtr< ossimElevationDatabase > b)
bool getNext(ossimFilename &filename) const
ossim_uint32 m_maxRoundRobinSize
void getCellsForBounds(const std::string &connectionString, const ossim_float64 &minLat, const ossim_float64 &minLon, const ossim_float64 &maxLat, const ossim_float64 &maxLon, std::vector< ossimFilename > &cells, ossim_uint32 maxNumberOfCells=0)
Gets a list of elevation cells needed to cover bounding box.
OSSIM_DLL ossim_uint32 getNumberOfThreads()
Get the number threads to use from ossimPreferences or ossim::Thread.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual double getMeanSpacingMeters() const
METHOD: meanSpacingMeters() This method returns the post spacing in the region of gpt: ...
ConnectionStringVisitor(const ossimString &value)
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
bool exists() const
ossim_float64 lon
Definition: ossimGpt.h:266
virtual double getHeightAboveEllipsoid(const ossimGpt &gpt)
bool toBool() const
String to numeric methods.
std::vector< ossimRefPtr< ossimElevationDatabase > > ElevationDatabaseListType
unsigned long long ossim_uint64
unsigned int ossim_uint32
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
static ossimGeoidManager * instance()
Implements singelton pattern:
double toDouble() const
const ossimGpt & ul() const
Definition: ossimGrect.h:252
void setRoundRobinMaxSize(ossim_uint32 size)
virtual ~ossimElevManager()
bool loadElevationPath(const ossimFilename &path, bool set_as_first=false)
Adds a new elevation file (or multiple files if path is a directory) to the collection.
bool getBoolKeywordValue(bool &rtn_val, const char *keyword, const char *prefix=0) const
[OLK, Aug/2008] Sets the boolean <rtn_val> depending on value associated with keyword for values = (y...
static const char * ENABLED_KW
std::mutex m_mutex
I have tried the readwrite lock interfaces but have found it unstable.
bool open(const ossimFilename &dir)
virtual void getOpenCellList(std::vector< ossimFilename > &list) const
std::vector< ossimString > getSubstringKeyList(const ossimString &regularExpression) const
static ossimEnvironmentUtility * instance()
virtual double getHeightAboveMSL(const ossimGpt &gpt)
Height access methods:
ossimFilename dirCat(const ossimFilename &file) const
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
bool empty() const
Definition: ossimString.h:411
void getCellsForBounds(const ossim_float64 &minLat, const ossim_float64 &minLon, const ossim_float64 &maxLat, const ossim_float64 &maxLon, std::vector< ossimFilename > &cells, ossim_uint32 maxNumberOfCells=0)
Gets a list of elevation cells needed to cover bounding box.
bool stopTraversal() const
ossimString getEnvironmentVariable(const ossimString &variable) const
ossim_float64 lat
Definition: ossimGpt.h:265
virtual ossimObject * dup() const =0
void addDatabase(ossimElevationDatabase *database, bool set_as_first=false)
Adds a new elevation database to the collection.
ossimFilename getUserOssimSupportDir() const
ossimElevationDatabase * open(const ossimString &connectionString)
ossim_float64 m_defaultHeightAboveEllipsoid
std::vector< ElevationDatabaseListType > m_dbRoundRobin
virtual double offsetFromEllipsoid(const ossimGpt &gpt)
static const char * FILENAME_KW
const ossimGpt & lr() const
Definition: ossimGrect.h:269
ElevationDatabaseListType & getNextElevDbList() const
const ossimString & getConnectionString() const
ossimElevationDatabase * createDatabase(const ossimString &typeName) const
int toInt() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_uint32 m_currentDatabaseIdx
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
const std::string & string() const
Definition: ossimString.h:414
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91