OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimGpt.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Garrett Potts
6 //
7 // Description:
8 //
9 // LATITUDE AND LONGITUDE VALUES ARE IN DEGREES.
10 //
11 //*******************************************************************
12 // $Id: ossimGpt.cpp 20615 2012-02-27 12:43:12Z gpotts $
13 
14 #include <ossim/base/ossimGpt.h>
17 #include <ossim/base/ossimDms.h>
18 #include <ossim/base/ossimDatum.h>
24 #include <iostream>
25 #include <sstream>
26 
28 {
29  // Capture the original flags.
30  std::ios_base::fmtflags f = os.flags();
31 
32  // Set the new precision capturing old.
33  std::streamsize oldPrecision = os.precision(precision);
34 
35  os << setiosflags(ios::fixed)
36  << "( ";
37 
38  if(isLatNan())
39  {
40  os << "nan" << ", ";
41  }
42  else
43  {
44  os << latd() << ", ";
45  }
46  if(isLonNan())
47  {
48  os << "nan" << ", ";
49  }
50  else
51  {
52  os << lond() << ", ";
53  }
54  if(isHgtNan())
55  {
56  os << "nan" << ", ";
57  }
58  else
59  {
60  // millimeter precision for height
61  os << setprecision(3) << height() << ", ";
62  }
63 
64  os << (theDatum?theDatum->code().c_str():"") << " )";
65 
66  // Reset flags and precision.
67  os.setf(f);
68  os.precision(oldPrecision);
69 
70  return os;
71 }
72 
74 {
75  return pt.print(os);
76 }
77 
79 {
81 
82  os << setprecision(precision);
83  os << "(";
84 
85  if(isLatNan())
86  {
87  os << "nan" << ",";
88  }
89  else
90  {
91  os << latd() << ",";
92  }
93  if(isLonNan())
94  {
95  os << "nan" << ",";
96  }
97  else
98  {
99  os << lond() << ",";
100  }
101  if(isHgtNan())
102  {
103  os << "nan" << ",";
104  }
105  else
106  {
107  // millimeter precision for height
108  os << height() << ",";
109  }
110 
111  os << (theDatum?theDatum->code().c_str():"") << ")";
112  return ossimString(os.str());
113 }
114 
115 
116 void ossimGpt::toPoint(const std::string& s)
117 {
118  std::istringstream is(s);
119  is >> *this;
120 }
121 
123 {
124  //---
125  // Expected input format:
126  // ( 30.00000000000000, -90.00000000000000, 0.00000000000000, WGE )
127  // -----latitude---- -----longitude---- ------height---- datum
128  //---
129 
130  // Start with a nan point.
131  pt.makeNan();
132 
133  // Check the stream.
134  if (!is) return is;
135 
136  const int SZ = 64; // Handle real big number...
137  ossimString os;
138  char buf[SZ];
139  char c = 0;
140 
141  //---
142  // LATITUDE SECTION:
143  //---
144 
145  // Grab data up to the first comma.
146  is.get(buf, SZ, ',');
147 
148  if (!is) return is;
149 
150  // Copy to ossim string.
151  os = buf;
152 
153  // Get rid of the '(' if there is any.
154  std::string::size_type pos = os.find('(');
155  if (pos != std::string::npos)
156  {
157  os.erase(pos, 1);
158  }
159 
160  if (os.contains("nan") == false)
161  {
162  pt.latd(os.toFloat64());
163  }
164  else
165  {
166  pt.latd(ossim::nan());
167  }
168 
169  // Eat the comma that we stopped at.
170  while (c != ',')
171  {
172  is.get(c);
173  if (!is) break;
174  }
175 
176  //---
177  // LONGITUDE SECTION:
178  //---
179 
180  // Grab the data up to the next ','
181  is.get(buf, SZ, ',');
182 
183  if (!is) return is;
184 
185  // Copy to ossim string.
186  os = buf;
187 
188  if (os.contains("nan") == false)
189  {
190  pt.lond(os.toFloat64());
191  }
192  else
193  {
194  pt.lond(ossim::nan());
195  }
196 
197  // Eat the comma that we stopped at.
198  c = 0;
199  while (c != ',')
200  {
201  is.get(c);
202  if (!is) break;
203  }
204 
205  //---
206  // HEIGHT SECTION:
207  //---
208 
209  // Grab the data up to the ','
210  is.get(buf, SZ, ',');
211 
212  if (!is) return is;
213 
214  // Copy to ossim string.
215  os = buf;
216 
217  if (os.contains("nan") == false)
218  {
219  pt.height(os.toFloat64());
220  }
221  else
222  {
223  pt.height(ossim::nan());
224  }
225 
226  // Eat the comma that we stopped at.
227  c = 0;
228  while (c != ',')
229  {
230  is.get(c);
231  if (!is) break;
232  }
233 
234  //---
235  // DATUM SECTION:
236  //---
237 
238  // Grab the data up to the ')'
239  is.get(buf, SZ, ')');
240 
241  if (!is) return is;
242 
243  // Copy to ossim string.
244  os = buf;
245  os.trim(); // Just in case datum factory doesn't handle spaces.
246 
248  if (datum)
249  {
250  pt.datum(datum);
251  }
252  else
253  {
254  pt.datum(ossimDatumFactory::instance()->wgs84());
255  }
256 
257  // Gobble the trailing ")".
258  c = 0;
259  while (c != ')')
260  {
261  is.get(c);
262  if (!is) break;
263  }
264 
265  // Finished
266  return is;
267 }
268 
269 //*****************************************************************************
270 // COPY CONSTRUCTOR: ossimGpt(ossimGpt)
271 //*****************************************************************************
273  : lat(src.lat),
274  lon(src.lon),
275  hgt(src.hgt)
276 {
277  theDatum = src.datum();
278  if(!theDatum)
279  {
281  }
282 // limitLonTo180();
283 }
284 
285 //*****************************************************************************
286 // CONSTRUCTOR: ossimGpt(ossimEcefPoint, datum)
287 //*****************************************************************************
289  const ossimDatum* datum)
290  :
291  theDatum (datum)
292 {
293  if(!theDatum)
294  {
296  }
297  if(ecef_point.isNan())
298  {
299  makeNan();
300  }
301  else
302  {
303  theDatum->ellipsoid()->XYZToLatLonHeight(ecef_point.x(),
304  ecef_point.y(),
305  ecef_point.z(),
306  lat,
307  lon,
308  hgt);
309 
310  }
311 }
312 
313 //*****************************************************************************
314 // METHOD: ossimGpt::changeDatum
315 //*****************************************************************************
317 {
318  if (*datum == *theDatum)
319  return;
320 
321  // only shift if all values lat and lon is good
322  if(!isLatNan() && !isLonNan())
323  {
324  if(datum)
325  {
326  double h = hgt;
327  *this = datum->shift(*this);
328  if(ossim::isnan(h))
329  {
330  hgt = h;
331  }
332  theDatum = datum;
333  }
334  }
335 }
336 
337 //*****************************************************************************
338 // METHOD: ossimGpt::toDmsString()
339 //*****************************************************************************
341 {
342  ossimString result;
343 
344  result += "lat: ";
345  if(isLatNan())
346  {
347  result += "nan";
348  }
349  else
350  {
351  result += ossimDms(latd()).toString("dd@mm'ss.ssss\"C");
352  }
353  result += " lon: ";
354  if(isLonNan())
355  {
356  result += "nan";
357  }
358  else
359  {
360  result += ossimDms(lond(),false).toString("dd@mm'ss.ssss\"C");
361  }
362 
363  return result;
364 }
365 
366 bool ossimGpt::isEqualTo(const ossimGpt& rhs, ossimCompareType compareType)const
367 {
368  bool result = false;
369  if(!ossim::isnan(lat)&&!ossim::isnan(rhs.lat))
370  {
371  result = ossim::almostEqual(lat, rhs.lat);
372  }
373  else
374  {
375  result = ossim::isnan(lat)&&ossim::isnan(rhs.lat);
376  }
377 
378  if(result)
379  {
380  if(!ossim::isnan(lon)&&!ossim::isnan(rhs.lon))
381  {
382  result = ossim::almostEqual(lon, rhs.lon);
383  }
384  else
385  {
386  result = ossim::isnan(lon)&&ossim::isnan(rhs.lon);
387  }
388  }
389  if(result)
390  {
391  if(!ossim::isnan(hgt)&&!ossim::isnan(rhs.hgt))
392  {
393  result = ossim::almostEqual(hgt, rhs.hgt);
394  }
395  else
396  {
397  result = ossim::isnan(hgt)&&ossim::isnan(rhs.hgt);
398  }
399  }
400 
401  if(result)
402  {
403  if(theDatum&&rhs.theDatum)
404  {
405  if(compareType == OSSIM_COMPARE_FULL)
406  {
407  result = theDatum->isEqualTo(*rhs.theDatum);
408  }
409  else
410  {
411  result = theDatum == rhs.theDatum;
412  }
413 
414  }
415  else if(reinterpret_cast<ossim_uint64>(theDatum)|reinterpret_cast<ossim_uint64>(rhs.theDatum))
416  {
417  result = false;
418  }
419  }
420 
421  return result;
422 }
423 
424 
425 //*****************************************************************************
426 // METHOD: ossimGpt::distanceTo(ossimGpt)
427 //
428 // Computes straight-line distance to arg point, in meters.
429 //
430 //*****************************************************************************
431 double ossimGpt::distanceTo(const ossimGpt& arg_pt) const
432 {
433  ossimEcefPoint p1 (*this);
434  ossimEcefPoint p2 (arg_pt);
435 
436  return (p1 - p2).magnitude();
437 }
438 
439 //*****************************************************************************
440 // METHOD: azimuthTo(ossimGpt)
441 // Computes the great-circle starting azimuth (i.e., at this gpt) to the argument gpt in degrees.
442 // In other words, what direction we would need to start walking in to travel the shortest
443 // distance to arg_gpt (assumes spherical earth).
444 // Taken from American Practical Navigator, a.k.a. Bowditch (NIMA 2002)
445 //*****************************************************************************
446 double ossimGpt::azimuthTo(const ossimGpt& gpt) const
447 {
448  using namespace ossim; // for trig functions in degrees
449 
450  //### NOT WORKING ###
451  //double dlo = fabs(lon - gpt.lon);
452  //if (lat * gpt.lat < 0)
453  // dlo *= -1.0;
454 
455  //double c = atand(sind(dlo)/((cosd(lat)*tand(gpt.lat)) - (sind(lat)*cosd(dlo))));
456  //return c;
457 
458  // Use alternate local method (not great circle):
459  double mean_lat = 0.5*(lat + gpt.lat);
460  double dlon = ossim::cosd(mean_lat)*(gpt.lon - lon);
461  double dlat = gpt.lat - lat;
462  double theta = ossim::atan2d(dlon,dlat);
463  if (theta < 0)
464  theta += 360.0;
465  return theta;
466 }
467 
468 //*****************************************************************************
469 // METHOD: ossimGpt::heightMSL() const
470 //
471 // Returns the height data member adjusted for geoid.
472 //
473 //*****************************************************************************
474 double ossimGpt::heightMSL() const
475 {
476  double offset = ossimGeoidManager::instance()->offsetFromEllipsoid(*this);
477  return (hgt - offset);
478 }
479 
480 //*****************************************************************************
481 // METHOD: ossimGpt::heightMSL(double)
482 //
483 // Sets the height data member adjusted for geoid.
484 //
485 //*****************************************************************************
487 {
488  double offset = ossimGeoidManager::instance()->offsetFromEllipsoid(*this);
489  hgt = heightMSL + offset;
490 }
491 
492 //*****************************************************************************
493 // METHOD: ossimGpt::metersPerDegree(double)
494 //
495 // Computes geodetic arc lengths at this ground point.
496 //
497 //*****************************************************************************
499 {
500 //#define USE_ELLIPTICAL_RADII
501 #ifdef USE_ELLIPTICAL_RADII
502  ossimDpt radii;
503  theDatum->ellipsoid()->geodeticRadii(lat, radii);
504  return ossimDpt (RAD_PER_DEG * radii.x * ossim::cosd(lat),
505  RAD_PER_DEG * radii.y);
506 #else
507  ossimDpt result;
508 
509  double radius = theDatum->ellipsoid()->geodeticRadius(lat);
510  result.y = RAD_PER_DEG * radius;
511  result.x = result.y * ossim::cosd(lat);
512 
513  return result;
514 #endif
515 }
516 
517 bool ossimGpt::operator==(const ossimGpt& gpt) const
518 {
519  return ( ossim::almostEqual(lat, gpt.lat) &&
520  ossim::almostEqual(lon, gpt.lon) &&
521  ossim::almostEqual(hgt, gpt.hgt) &&
522  (*theDatum == *(gpt.theDatum)));
523 }
524 
virtual ossimGpt shift(const ossimGpt &aPt) const =0
double azimuthTo(const ossimGpt &arg_gpt) const
METHOD: azimuthTo(ossimGpt) Computes the great-circle starting azimuth (i.e., at this gpt) to the arg...
Definition: ossimGpt.cpp:446
double heightMSL() const
Definition: ossimGpt.cpp:474
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
bool isLonNan() const
Definition: ossimGpt.h:140
static ossimDatumFactoryRegistry * instance()
instance method
const ossimDatum * theDatum
Know reference location plus an implied ellipsoid.
Definition: ossimGpt.h:281
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
virtual bool isEqualTo(const ossimObject &obj, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
Definition: ossimDatum.cpp:179
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
double y
Definition: ossimDpt.h:165
bool contains(char aChar) const
Definition: ossimString.h:58
virtual const ossimString & code() const
Definition: ossimDatum.h:57
void makeNan()
Definition: ossimGpt.h:130
double x() const
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
ossimCompareType
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
bool isLatNan() const
Definition: ossimGpt.h:139
double distanceTo(const ossimGpt &arg_gpt) const
METHOD: distanceTo(ossimGpt) Computes straight-line distance in meters between this and arg gpt: ...
Definition: ossimGpt.cpp:431
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
bool isHgtNan() const
Definition: ossimGpt.h:143
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
bool isEqualTo(const ossimGpt &rhs, ossimCompareType compareType=OSSIM_COMPARE_FULL) const
Definition: ossimGpt.cpp:366
ossim_float64 lon
Definition: ossimGpt.h:266
void toPoint(const std::string &s)
Initializes this point from string.
Definition: ossimGpt.cpp:116
unsigned int ossim_uint32
std::string::iterator erase(std::string::iterator p)
Erases the character at position p.
Definition: ossimString.h:736
virtual const ossimDatum * create(const ossimString &code) const
create method
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual const ossimEllipsoid * ellipsoid() const
Definition: ossimDatum.h:60
static ossimGeoidManager * instance()
Implements singelton pattern:
double height() const
Definition: ossimGpt.h:107
ossim_float64 toFloat64() const
static ossimDatumFactory * instance()
double atan2d(double y, double x)
Definition: ossimCommon.h:267
std::istream & operator>>(std::istream &is, ossimGpt &pt)
Definition: ossimGpt.cpp:122
bool operator==(const ossimGpt &gpt) const
Definition: ossimGpt.cpp:517
double cosd(double x)
Definition: ossimCommon.h:259
ossimString toDmsString() const
Definition: ossimGpt.cpp:340
std::ostream & print(std::ostream &os, ossim_uint32 precision=15) const
Definition: ossimGpt.cpp:27
std::ostream & operator<<(std::ostream &os, const ossimGpt &pt)
Definition: ossimGpt.cpp:73
void geodeticRadii(const double &latitude, ossimDpt &radii) const
std::basic_istream< char > istream
Base class for char input streams.
Definition: ossimIosFwd.h:20
double y() const
double geodeticRadius(const double &latitude) const
bool isNan() const
double x
Definition: ossimDpt.h:164
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
ossimGpt(const double alat=0, const double alon=0, const double ahgt=0, const ossimDatum *aDatum=ossimDatumFactory::instance() ->wgs84())
Constructor.
Definition: ossimGpt.h:37
ossimDpt metersPerDegree() const
Definition: ossimGpt.cpp:498
ossim_float64 lat
Definition: ossimGpt.h:265
ossimString toString(ossim_uint32 precision=15) const
Definition: ossimGpt.cpp:78
const ossimDatum * wgs84() const
std::basic_istringstream< char > istringstream
Class for char input memory streams.
Definition: ossimIosFwd.h:32
virtual double offsetFromEllipsoid(const ossimGpt &gpt)
void XYZToLatLonHeight(double x, double y, double z, double &lat, double &lon, double &height) const
double z() const
#define RAD_PER_DEG
std::string::size_type find(const std::string &s, std::string::size_type pos=0) const
Searches for s as a substring of *this, beginning at character pos of *this.
Definition: ossimString.h:753
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
ossimString toString(const ossimString &formatString=ossimString("")) const
You can specify a number of different formats.
Definition: ossimDms.cpp:294
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91