OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimElevSource.cpp
Go to the documentation of this file.
1 //*****************************************************************************
2 // FILE: ossimElevSource.cc
3 //
4 // License: See top level LICENSE.txt file.
5 //
6 // DESCRIPTION:
7 // Contains implementation of class ossimElevSource. This is the base class
8 // for all sources of elevation data. it maintains a single common static
9 // instance of the geoid for use by all instances of objects derived from
10 // this one.
11 //
12 // SOFTWARE HISTORY:
13 //>
14 // 18Apr2001 Oscar Kramer
15 // Initial coding.
16 //<
17 //*****************************************************************************
18 // $Id: ossimElevSource.cpp 23117 2015-01-29 22:33:13Z okramer $
19 
22 #include <ossim/base/ossimGpt.h>
24 #include <ossim/base/ossimDatum.h>
27 
28 RTTI_DEF1(ossimElevSource, "ossimElevSource" , ossimSource)
29 
30 //***
31 // Define Trace flags for use within this file:
32 //***
33 #include <ossim/base/ossimTrace.h>
34 static ossimTrace traceExec ("ossimElevSource:exec");
35 static ossimTrace traceDebug ("ossimElevSource:debug");
36 
37 
38 static const char ENABLE_STATS_KW[] = "elevation.compute_statistics.enabled";
39 
41  :
42  theMinHeightAboveMSL (0.0),
43  theMaxHeightAboveMSL (0.0),
44  theNullHeightValue (ossim::nan()),
45  theSeaLevelValue (OSSIM_DEFAULT_MEAN_SEA_LEVEL),
46  theGroundRect(),
47  theComputeStatsFlag(false)
48 
49 {
50  if (traceExec())
51  {
53  << "DEBUG ossimElevSource::ossimElevSource: entering..."
54  << std::endl;
55  }
56 
57  // User can turn on off with a keyword.
58  const char* lookup =
59  ossimPreferences::instance()->findPreference(ENABLE_STATS_KW);
60  if (lookup)
61  {
63  }
64 
65  if (traceDebug())
66  {
68  << "DEBUG:"
69  << "\ntheComputeStatsFlag: "
70  << (theComputeStatsFlag?"true":"false")
71  << endl;
72  }
73 
74 
75  if (traceExec())
76  {
78  << "DEBUG ossimElevSource::ossimElevSource: returning..."
79  << std::endl;
80  }
81 }
82 
84  :ossimSource(src),
85  theMinHeightAboveMSL(src.theMinHeightAboveMSL),
86  theMaxHeightAboveMSL(src.theMaxHeightAboveMSL),
87  theNullHeightValue(src.theNullHeightValue),
88  theSeaLevelValue(src.theSeaLevelValue),
89  theGroundRect(src.theGroundRect),
90  theComputeStatsFlag(src.theComputeStatsFlag)
91 {
92 }
93 
95 {}
96 
98 {
100  << "FATAL ossimElevSource::getHeightAboveEllipsoid Not implemented..."
101  << std::endl;
102  return theNullHeightValue;
103 }
104 
105 //*****************************************************************************
106 // METHOD: intersectRay()
107 //
108 // Service method for intersecting a ray with the elevation surface to
109 // arrive at a ground point. The ray is expected to originate ABOVE the
110 // surface and pointing down.
111 //
112 // NOTE: the gpt argument is expected to be initialized with the desired
113 // datum, including ellipsoid, for the proper intersection point to be
114 // computed.
115 //
116 // LIMITATION: This release supports only single valued solutions, i.e., it
117 // is possible a ray passing through one side of a mountain and out the other
118 // will return an intersection with the far side. Eventually, a more robust
119 // algorithm will be employed.
120 //
121 //*****************************************************************************
122 bool ossimElevSource::intersectRay(const ossimEcefRay& ray, ossimGpt& gpt, double defaultElevValue)
123 {
124  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: entering..." << std::endl;
125 
126  static const double CONVERGENCE_THRESHOLD = 0.001; // meters
127  static const int MAX_NUM_ITERATIONS = 50;
128 
129  double h_ellips; // height above ellipsoid
130  bool intersected;
131  ossimEcefPoint prev_intersect_pt (ray.origin());
132  ossimEcefPoint new_intersect_pt;
133  double distance;
134  bool done = false;
135  int iteration_count = 0;
136 
137  if(ray.hasNans())
138  {
139  gpt.makeNan();
140  return false;
141  }
142  //***
143  // Set the initial guess for horizontal intersect position as the ray's
144  // origin, and establish the datum and ellipsoid:
145  //***
146  const ossimDatum* datum = gpt.datum();
147  const ossimEllipsoid* ellipsoid = datum->ellipsoid();
148 // double lat, lon, h;
149 
150 // ellipsoid->XYZToLatLonHeight(ray.origin().x(),
151 // ray.origin().y(),
152 // ray.origin().z(),
153 // lat, lon, h);
154 // ossimGpt nadirGpt(lat, lon, h);
155 
156 // std::cout << "nadir pt = " << nadirGpt << std::endl;
157 
158  gpt = ossimGpt(prev_intersect_pt, datum);
159 
160  //
161  // Loop to iterate on ray intersection with variable elevation surface:
162  //
163  do
164  {
165  //
166  // Intersect ray with ellipsoid inflated by h_ellips:
167  //
168  h_ellips = getHeightAboveEllipsoid(gpt);
169  if ( ossim::isnan(h_ellips) ) h_ellips = defaultElevValue;
170 
171  intersected = ellipsoid->nearestIntersection(ray,
172  h_ellips,
173  new_intersect_pt);
174  if (!intersected)
175  {
176  //
177  // No intersection (looking over the horizon), so set ground point
178  // to NaNs:
179  //
180  gpt.makeNan();
181  done = true;
182  }
183  else
184  {
185  //
186  // Assign the ground point to the latest iteration's intersection
187  // point:
188  //
189  gpt = ossimGpt(new_intersect_pt, datum);
190 
191  //
192  // Determine if convergence achieved:
193  //
194  distance = (new_intersect_pt - prev_intersect_pt).magnitude();
195  if (distance < CONVERGENCE_THRESHOLD)
196  done = true;
197  else
198  {
199  prev_intersect_pt = new_intersect_pt;
200  }
201  }
202 
203  iteration_count++;
204 
205  } while ((!done) && (iteration_count < MAX_NUM_ITERATIONS));
206 
207  if (iteration_count == MAX_NUM_ITERATIONS)
208  {
209  if(traceDebug())
210  {
211  ossimNotify(ossimNotifyLevel_WARN) << "WARNING ossimElevSource::intersectRay: Max number of iterations reached solving for ground "
212  << "point. Result is probably inaccurate." << std::endl;
213  }
214  }
215 
216  if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimElevSource::intersectRay: returning..." << std::endl;
217  return intersected;
218 }
219 
221 {
222  return theMinHeightAboveMSL;
223 }
224 
226 {
227  return theMaxHeightAboveMSL;
228 }
229 
231 {
232  return theNullHeightValue;
233 }
234 
236 {
237  return theSeaLevelValue;
238 }
239 
241 {
242  return theGroundRect;
243 }
244 
246  const ossimConnectableObject* /* object */)const
247 {
248  return false;
249 }
250 
252 {}
253 
254 
256 {
257  return theComputeStatsFlag;
258 }
259 
261 {
262  theComputeStatsFlag = flag;
263 }
264 
266 {
267  out << "\nossimElevSource @ "<< (ossim_uint64) this
268  << "\ntheMinHeightAboveMSL = "<<theMinHeightAboveMSL
269  << "\ntheMaxHeightAboveMSL = "<<theMaxHeightAboveMSL
270  << "\ntheNullHeightValue = "<<theNullHeightValue
271  << "\ntheSeaLevelValue = "<<theSeaLevelValue
272  << "\ntheGroundRect = "<<theGroundRect;
273  // GP: need this by itself. MS errors out
274  ossimSource::print(out);
275  return out;
276 }
277 
double getSeaLevelValue() const
virtual ~ossimElevSource()
bool intersectRay(const ossimEcefRay &ray, ossimGpt &gpt, double defaultElevValue=0.0)
METHOD: intersectRay()
double theMinHeightAboveMSL
Data members:
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
const ossimEcefPoint & origin() const
Definition: ossimEcefRay.h:79
void makeNan()
Definition: ossimGpt.h:130
#define OSSIM_DEFAULT_MEAN_SEA_LEVEL
virtual bool getComputeStatisticsFlag() const
Opens a stream to an elevation cell.
virtual void setComputeStatisticsFlag(bool flag)
Sets the flag which controls whether or not statistics will be computed upon opening a cell and not f...
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
bool hasNans() const
Definition: ossimEcefRay.h:60
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
virtual const ossimGrect & getBoundingGndRect() const
METHODS: accuracyLE90(), accuracyCE90() Returns the vertical and horizontal accuracy (90% confidence)...
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
ossimGrect theGroundRect
ossimElevSource()
Constructors/Destructors:
const char * findPreference(const char *key) const
bool toBool() const
String to numeric methods.
unsigned long long ossim_uint64
virtual const ossimEllipsoid * ellipsoid() const
Definition: ossimDatum.h:60
static ossimPreferences * instance()
virtual double getMinHeightAboveMSL() const
Access methods for the bounding elevations:
virtual bool canConnectMyInputTo(ossim_int32 inputIndex, const ossimConnectableObject *object) const
required to be overriden by derived classes
virtual double getMaxHeightAboveMSL() const
double getNullHeightValue() const
Special numeric quantities as defined by this source:
double theMaxHeightAboveMSL
virtual void initialize()
Implement ossimSource base-class pure virtuals:
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual double getHeightAboveEllipsoid(const ossimGpt &)
float distance(double lat1, double lon1, double lat2, double lon2, int units)
bool nearestIntersection(const ossimEcefRay &ray, ossimEcefPoint &rtnPt) const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91