OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHgtRef.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Hicks
6 //
7 // Description: Height reference class.
8 //
9 //----------------------------------------------------------------------------
10 
14 #include <ossim/base/ossimTrace.h>
15 #include <ossim/base/ossimString.h>
16 #include <ossim/base/ossimTrace.h>
17 #include <ossim/base/ossimNotify.h>
21 
22 
23 static ossimTrace traceDebug(ossimString("ossimHgtRef:debug"));
24 
25 #ifdef OSSIM_ID_ENABLED
26 static const char OSSIM_ID[] = "$Id: ossimHgtRef.cpp 21399 2012-07-27 18:19:22Z gpotts $";
27 #endif
28 
29 
30 
31 //*****************************************************************************
32 // METHOD: ossimHgtRef::ossimHgtRef()
33 //
34 // Constructor for DEM reference.
35 //
36 //*****************************************************************************
38 :
39 theCurrentHeightRefType(cRefType)
40 {
41  if (traceDebug())
42  {
44  << "ossimHgtRef::ossimHgtRef DEBUG:" << std::endl;
45 #ifdef OSSIM_ID_ENABLED
47  << "OSSIM_ID: " << OSSIM_ID << std::endl;
48 #endif
49  }
50 
51 }
52 
53 
54 //*****************************************************************************
55 // METHOD: ossimHgtRef::ossimHgtRef()
56 //
57 // Constructor for ellipsoid reference.
58 //
59 //*****************************************************************************
61 :
62 theCurrentHeightRefType(cRefType),
63 theCurrentRefHeight(atHgt)
64 {
65  if (traceDebug())
66  {
68  << "ossimHgtRef::ossimHgtRef DEBUG:" << std::endl;
69 #ifdef OSSIM_ID_ENABLED
71  << "OSSIM_ID: " << OSSIM_ID << std::endl;
72 #endif
73  }
74 
75 }
76 
77 
78 
80 {
81 }
82 
83 
84 //*****************************************************************************
85 // METHOD: ossimHgtRef::getRefHeight()
86 //
87 // Get current reference height based on state of theCurrentHeightRefType.
88 //
89 //*****************************************************************************
91 {
92  ossim_float64 refHgt;
93 
95  {
96  case AT_HGT:
97  refHgt = theCurrentRefHeight;
98  break;
99  case AT_DEM:
101  break;
102  default:
103  refHgt = 0.0;
104  break;
105  }
106 
107  return refHgt;
108 }
109 
110 //*****************************************************************************
111 // METHOD: ossimHgtRef::getSurfaceInfo()
112 //
113 // Get reference surface information.
114 //
115 //*****************************************************************************
116 
117 #if 0
118 bool ossimHgtRef::getSurfaceInfo(const ossimGpt& pg,
119  ossimElevationAccuracyInfo& info) const
120 {
121  bool infoOK = false;
122 
123  // ossimElevManager::ElevationDatabaseListType dbList;
124  // std::vector<ossimFilename> cellList;
125 
126 
127  //double hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(pg);
128 
129 
130 /*
131 
132  dbList = ossimElevManager::instance()->getElevationDatabaseList();
133  ossim_uint32 idx;
134 
135  for(idx=0; idx < dbList.size(); ++idx)
136  {
137  double h = dbList[idx]->getHeightAboveEllipsoid(pg);
138  if (!ossim::isnan(h))
139  {
140  hgt = h;
141  break;
142  }
143  }
144  */
145  /*
146  if (!ossim::isnan(hgt))
147  {
148  ossimElevManager::instance()->getOpenCellList(cellList);
149 
150  ossimRefPtr<ossimImageHandler> ih =
151  ossimImageHandlerRegistry::instance()->open(cellList[idx]);
152  ossimString hanType(ih->getClassName().c_str());
153 
154  ossimImageGeometry* geom = ih->getImageGeometry().get();
155  gsd = geom->getMetersPerPixel();
156 
157  info = hanType;
158  }
159  else
160  {
161  info = "No Surface";
162  }
163  */
164  infoOK = true;
165 
166  return infoOK;
167 }
168 #endif
169 
170 //*****************************************************************************
171 // METHOD: ossimHgtRef::getSurfaceCovMatrix()
172 //
173 // Get reference surface covariance matrix.
174 //
175 //*****************************************************************************
176 bool ossimHgtRef::getSurfaceCovMatrix(const ossimGpt& pg, NEWMAT::Matrix& cov) const
177 {
178 
179  ossim_float64 refCE;
180  ossim_float64 refLE;
181  ossimString info;
182  ossimDpt gsd;
183 
184  switch (theCurrentHeightRefType)
185  {
186  case AT_HGT:
187  // Set the reference CE/LE
188  // Note: currently set to reflect no contribution
189  refCE = 0.0;
190  refLE = .01;
191 
192  break;
193 
194  case AT_DEM:
195  {
196 
197  // Set the reference CE/LE
198  // Note: currently set to SRTM spec in METERS
199  // refCE = 20.0;
200  // refLE = 16.0;
201  // (ref: www2.jpl.nas.gov/srtm/statistics.html)
202  // "refCE = ossimElevManager::instance()->getAccuracyCE90(pg)" is
203  // the desirable operation here (if it is implemented)
204  // ================================================
205  // This is one step closer to automatic
206  // access to elevation surface accuracy
207  // TODO...
208  // [1] load from OSSIM_PREFERENCES?
209  // [2] does DTED header/metadata have info?
210  // ================================================
213 
214  if(info.hasValidAbsoluteError())
215  {
216  refCE = info.m_absoluteCE;
217  refLE = info.m_absoluteLE;
218  }
219  else
220  {
221  refCE = 20.0;
222  refLE = 16.0;
223  }
224 #if 0
225  if (getSurfaceInfo(pg, info, gsd))
226  {
227  if (info.contains("Srtm"))
228  {
229  if (gsd.x < 50.0)
230  {
231  // SRTM 1 arc
232  refCE = 20.0;
233  refLE = 10.0;
234  }
235  else
236  {
237  // SRTM 3 arc
238  refCE = 20.0;
239  refLE = 16.0;
240  }
241  }
242  else if (info.contains("Dted"))
243  {
244  if (gsd.x < 50.0)
245  {
246  // DTED level 2
247  refCE = 40.0;
248  refLE = 20.0;
249  }
250  else
251  {
252  // DTED level 1
253  refCE = 50.0;
254  refLE = 30.0;
255  }
256  }
257  else
258  {
259  // Other
260  refCE = 20.0;
261  refLE = 16.0;
262  }
263  }
264  if (traceDebug())
265  {
267  //<< "DEBUG: info: " << info
268  << " ref: " << refCE << "/" << refLE << endl;
269  }
270 #endif
271 
272  break;
273  }
274  default:
275  return false;
276  break;
277  }
278 
279  // Form the covariance matrix
280  // A circular error ellipse with no correlation must be assumed.
281  cov = 0.0;
282  cov(1,1) = refCE/2.146;
283  cov(2,2) = refCE/2.146;
284  cov(3,3) = refLE/1.6449;
285  cov(1,1) *= cov(1,1);
286  cov(2,2) *= cov(2,2);
287  cov(3,3) *= cov(3,3);
288 
289  return true;
290 }
291 
292 
293 //*****************************************************************************
295 //
296 // Get reference surface covariance matrix.
297 //
298 //*****************************************************************************
300  const ossim_float64 refLE,
301  NEWMAT::Matrix& cov) const
302 {
303  ossim_float64 useCE;
304  ossim_float64 useLE;
305 
306  if (refCE<0.0 || refLE<0.0)
307  {
308  return false;
309  }
310 
311  switch (theCurrentHeightRefType)
312  {
313  case AT_HGT:
314  // Set the reference CE/LE
315  // Note: currently set to reflect no contribution
316  useCE = 0.0;
317  useLE = .01;
318 
319  break;
320 
321  case AT_DEM:
322  // Set the reference CE/LE
323  useCE = refCE;
324  useLE = refLE;
325 
326  break;
327 
328  default:
329  return false;
330  break;
331  }
332 
333  // Form the covariance matrix
334  // A circular error ellipse with no correlation must be assumed.
335  cov = 0.0;
336  cov(1,1) = useCE/2.146;
337  cov(2,2) = useCE/2.146;
338  cov(3,3) = useLE/1.6449;
339  cov(1,1) *= cov(1,1);
340  cov(2,2) *= cov(2,2);
341  cov(3,3) *= cov(3,3);
342 
343  return true;
344 }
345 
346 
347 //*****************************************************************************
348 // METHOD: ossimHgtRef::getSurfaceNormalCovMatrix()
349 //
350 // Form surface normal ECF covariance matrix from ENU surface covariance.
351 //
352 //*****************************************************************************
353 bool ossimHgtRef::
355  (const ossimGpt& pg,
356  const NEWMAT::Matrix& surfCov,
357  NEWMAT::Matrix& normCov) const
358 {
359  // Set the local frame
360  ossimLsrSpace enu(pg);
361 
362  // Propagate the reference covariance matrix to ECF
363  NEWMAT::Matrix covEcf;
364  covEcf = enu.lsrToEcefRotMatrix() * surfCov * enu.lsrToEcefRotMatrix().t();
365 
366  // Get surface normal vector in ENU
367  ossimColumnVector3d sn = getLocalTerrainNormal(pg);
368  NEWMAT::Matrix tnU(3,1);
369  tnU << sn[0] << sn[1] << sn[2];
370 
371  // Rotate surface normal to ECF
372  NEWMAT::Matrix tnUecf(3,1);
373  tnUecf = enu.lsrToEcefRotMatrix() * tnU;
374 
375  // Propagate to terrain normal
376  NEWMAT::Matrix ptn;
377  NEWMAT::SymmetricMatrix ptns;
378  ptn = tnUecf.t() * covEcf * tnUecf;
379  ptns << ptn;
380 
381  // And back to ECF
382  normCov = tnUecf * ptns * tnUecf.t();
383 
384 
385  return true;
386 }
387 
388 
389 //*****************************************************************************
390 // METHOD: ossimHgtRef::getLocalTerrainNormal()
391 //
392 // Get get local terrain normal unit vector.
393 //
394 //*****************************************************************************
396 {
397  ossimColumnVector3d tNorm;
398  const ossim_float64 delta = 100.0;
399 
400  switch (theCurrentHeightRefType)
401  {
402  case AT_HGT:
403  // Use ellipsoid tangent plane mormal
404  tNorm = tNorm.zAligned();
405  break;
406 
407  case AT_DEM:
408  {
409  // Use local 3X3 grid around point to get mean slope
410  NEWMAT::Matrix h(3,3);
411  ossimDpt mpd;
412  mpd = pg.metersPerDegree();
413  ossim_float64 dLon = delta/mpd.x;
414  ossim_float64 dLat = delta/mpd.y;
415 
416 
417  for (ossim_int32 lon=-1; lon<=1; ++lon)
418  {
419  ossim_float64 clon = pg.lond()+lon*dLon;
420  for (ossim_int32 lat=-1; lat<=1; ++lat)
421  {
422  ossim_float64 clat = pg.latd()+lat*dLat;
423  ossimGpt p(clat, clon, pg.height());
424  h(2-lat,lon+2) =
426  }
427  }
428 
429  if (traceDebug())
430  {
432  <<"DEBUG: getLocalTerrainNormal... 3X3 grid"<<endl;
433  for (ossim_int32 lat=-1; lat<=1; ++lat)
434  {
435  for (ossim_int32 lon=-1; lon<=1; ++lon)
436  ossimNotify(ossimNotifyLevel_DEBUG)<<" "<<h(lat+2,lon+2);
438  }
439  }
440 
441  ossim_float64 dz_dlon =
442  ((h(1,3)+2*h(2,3)+h(3,3))-(h(1,1)+2*h(2,1)+h(3,1)))/(8*delta);
443  ossim_float64 dz_dlat =
444  ((h(1,1)+2*h(1,2)+h(1,3))-(h(3,1)+2*h(3,2)+h(3,3)))/(8*delta);
445  tNorm[0] = -dz_dlon;
446  tNorm[1] = -dz_dlat;
447  tNorm[2] = 1.0 - sqrt(dz_dlon*dz_dlon+dz_dlat*dz_dlat);
448  }
449 
450  // If error condition, return z-aligned vector to allow continuation
451  if (ossim::isnan(tNorm[0]) ||
452  ossim::isnan(tNorm[1]) ||
453  ossim::isnan(tNorm[2]))
454  {
455  tNorm = tNorm.zAligned();
456  if(traceDebug())
457  {
459  << "WARNING: ossimHgtRef::getLocalTerrainNormal(): "
460  << "\n error... terrain normal set to vertical..."
461  << std::endl;
462 
463  }
464  }
465  break;
466 
467  default:
468  tNorm = tNorm.zAligned();
469  break;
470  }
471 
472  return tNorm;
473 }
virtual bool getAccuracyInfo(ossimElevationAccuracyInfo &info, const ossimGpt &gpt) const
virtual ossim_float64 getRefHeight(const ossimGpt &pg) const
Method to get height reference.
Definition: ossimHgtRef.cpp:90
virtual ~ossimHgtRef()
virtual destructor.
Definition: ossimHgtRef.cpp:79
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
double y
Definition: ossimDpt.h:165
static ossimElevManager * instance()
METHOD: instance() Implements singelton pattern.
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
virtual bool getSurfaceCovMatrix(const ossimGpt &pg, NEWMAT::Matrix &cov) const
Method to get surface information string.
ossimHgtRef(HeightRefType_t cRefType)
constructor.
Definition: ossimHgtRef.cpp:37
ossim_float64 theCurrentRefHeight
Definition: ossimHgtRef.h:117
double ossim_float64
const NEWMAT::Matrix & lsrToEcefRotMatrix() const
virtual double getHeightAboveEllipsoid(const ossimGpt &gpt)
double height() const
Definition: ossimGpt.h:107
HeightRefType_t theCurrentHeightRefType
Definition: ossimHgtRef.h:116
virtual ossimColumnVector3d getLocalTerrainNormal(const ossimGpt &pg) const
Method to get local terrain normal unit vector (slope).
double x
Definition: ossimDpt.h:164
ossimDpt metersPerDegree() const
Definition: ossimGpt.cpp:498
bool getSurfaceNormalCovMatrix(const ossimGpt &pg, const NEWMAT::Matrix &surfCov, NEWMAT::Matrix &normCov) const
Method to get surface normal covariance matrix.
const ossimColumnVector3d & zAligned()
HeightRefType_t
Definition: ossimHgtRef.h:17
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
int ossim_int32
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91