Isis 3 Programmer Reference
Latitude.cpp
Go to the documentation of this file.
1 
20 #include "Latitude.h"
21 
22 #include <cmath>
23 
24 #include "Constants.h"
25 #include "Distance.h"
26 #include "IException.h"
27 #include "IString.h"
28 #include "PvlGroup.h"
29 #include "QString"
30 #include "SpecialPixel.h"
31 #include "Target.h"
32 
33 namespace Isis {
34 
39 
40  m_equatorialRadius = NULL;
41  m_polarRadius = NULL;
42 
44  }
45 
46 
58  Latitude::Latitude(double latitude, Angle::Units latitudeUnits,
59  ErrorChecking errors) : Angle() {
60 
61  m_equatorialRadius = NULL;
62  m_polarRadius = NULL;
63 
64  m_errors = errors;
65 
66  setPlanetocentric(latitude, latitudeUnits);
67  }
68 
69 
77  Latitude::Latitude(Angle latitude, ErrorChecking errors) : Angle() {
78 
79  m_equatorialRadius = NULL;
80  m_polarRadius = NULL;
81 
82  m_errors = errors;
83 
84  setPlanetocentric(latitude.radians(), Radians);
85  }
86 
87 
103  Latitude::Latitude(Angle latitude, PvlGroup mapping,
104  ErrorChecking errors) : Angle(latitude) {
105 
106  m_equatorialRadius = NULL;
107  m_polarRadius = NULL;
108 
109  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
110  m_equatorialRadius = new Distance(toDouble(mapping["EquatorialRadius"][0]),
112  m_polarRadius = new Distance(toDouble(mapping["PolarRadius"][0]),
114  }
115  else {
116  try {
117  PvlGroup radiiGrp = Target::radiiGroup(mapping["TargetName"][0]);
118  m_equatorialRadius = new Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
120  m_polarRadius = new Distance(toDouble(radiiGrp["PolarRadius"][0]),
122  }
123  catch (IException &e) {
124  QString msg = "Unable to create Latitude object from given mapping group.";
125  throw IException(e, IException::Unknown, msg, _FILEINFO_);
126  }
127  }
128 
129  m_errors = errors;
130 
131  if (mapping["LatitudeType"][0] == "Planetographic") {
132  setPlanetographic(latitude.radians(), Radians);
133  }
134  else if (mapping["LatitudeType"][0] == "Planetocentric") {
135  setPlanetocentric(latitude.radians(), Radians);
136  }
137  else {
138  QString msg = "Latitude type [" + mapping["LatitudeType"][0] +
139  "] is not recognized";
141  }
142  }
143 
144 
161  Latitude::Latitude(double latitude,
162  PvlGroup mapping,
163  Angle::Units latitudeUnits,
164  ErrorChecking errors) : Angle(latitude, latitudeUnits) {
165 
166  m_equatorialRadius = NULL;
167  m_polarRadius = NULL;
168 
169  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
170  m_equatorialRadius = new Distance(toDouble(mapping["EquatorialRadius"][0]),
172  m_polarRadius = new Distance(toDouble(mapping["PolarRadius"][0]),
174  }
175  else {
176  try {
177  PvlGroup radiiGrp = Target::radiiGroup(mapping["TargetName"][0]);
178  m_equatorialRadius = new Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
180  m_polarRadius = new Distance(toDouble(radiiGrp["PolarRadius"][0]),
182  }
183  catch (IException &e) {
184  QString msg = "Unable to create Latitude object from given mapping group.";
185  throw IException(e, IException::Unknown, msg, _FILEINFO_);
186  }
187  }
188 
189  m_errors = errors;
190 
191  if (mapping["LatitudeType"][0] == "Planetographic") {
192  setPlanetographic(latitude, latitudeUnits);
193  }
194  else if (mapping["LatitudeType"][0] == "Planetocentric") {
195  setPlanetocentric(latitude, latitudeUnits);
196  }
197  else {
198  QString msg = "Latitude type [" + mapping["LatitudeType"][0] +
199  "] is not recognized";
201  }
202  }
203 
204 
221  Latitude::Latitude(double latitude,
222  Distance equatorialRadius, Distance polarRadius,
223  CoordinateType latType,
224  Angle::Units latitudeUnits,
225  ErrorChecking errors) : Angle(latitude, latitudeUnits) {
226 
227  m_equatorialRadius = NULL;
228  m_polarRadius = NULL;
229 
230  m_equatorialRadius = new Distance(equatorialRadius);
231  m_polarRadius = new Distance(polarRadius);
232 
233  m_errors = errors;
234 
235  if (latType == Planetocentric) {
236  setPlanetocentric(latitude, latitudeUnits);
237  }
238  else if (latType == Planetographic) {
239  setPlanetographic(latitude, latitudeUnits);
240  }
241  else {
242  QString msg = "Enumeration value [" + toString(latType) + "] is not a valid CoordinateType";
244  }
245  }
246 
247 
253  Latitude::Latitude(const Latitude &latitudeToCopy) : Angle(latitudeToCopy) {
254 
255  m_equatorialRadius = NULL;
256  m_polarRadius = NULL;
257 
258  m_errors = latitudeToCopy.m_errors;
259 
260  if (latitudeToCopy.m_equatorialRadius) {
261  m_equatorialRadius = new Distance(*latitudeToCopy.m_equatorialRadius);
262  }
263 
264  if (latitudeToCopy.m_polarRadius) {
265  m_polarRadius = new Distance(*latitudeToCopy.m_polarRadius);
266  }
267  }
268 
269 
274  if (m_equatorialRadius) {
275  delete m_equatorialRadius;
276  m_equatorialRadius = NULL;
277  }
278 
279  if (m_polarRadius) {
280  delete m_polarRadius;
281  m_polarRadius = NULL;
282  }
283  }
284 
285 
296  return angle(units);
297  }
298 
299 
306  void Latitude::setPlanetocentric(double latitude, Angle::Units units) {
307  setAngle(latitude, units);
308  }
309 
310 
329 
330  if (m_equatorialRadius == NULL || m_polarRadius == NULL) {
331  QString msg = "Latitude [" + toString(true) + "] cannot "
332  "be converted to Planetographic without the planetary radii, please "
333  "use the other Latitude constructor.";
335  }
336 
337  if (*this > Angle(90.0, Angle::Degrees) ||
338  *this < Angle(-90.0, Angle::Degrees)) {
339  QString msg = "Latitudes outside of the -90/90 range cannot be converted "
340  "between Planetographic and Planetocentric";
342  }
343 
344  if (!isValid()) {
345  QString msg = "Invalid planetographic latitudes are not currently "
346  "supported";
348  }
349 
350  double ographicLatitude = atan(tan(radians()) *
353 
354  // This theoretically should just be an angle, but make it a Latitude so
355  // we can access angle
356  return Latitude(ographicLatitude, Angle::Radians).angle(units);
357  }
358 
359 
373  void Latitude::setPlanetographic(double latitude, Angle::Units units) {
374 
375  if (m_equatorialRadius == NULL || m_polarRadius == NULL) {
376  QString msg = "Latitude [" + Isis::toString(latitude) + " degrees] cannot be "
377  "converted to Planetocentic without the planetary radii, please use "
378  "the other Latitude constructor.";
380  }
381 
382  Angle inputAngle(latitude, units);
383 
384  if (inputAngle > Angle(90.0, Angle::Degrees) ||
385  inputAngle < Angle(-90.0, Angle::Degrees)) {
386  QString msg = "Latitudes outside of the -90/90 range cannot be converted "
387  "between Planetographic and Planetocentric";
389  }
390 
391  // Since the Angle constructor handles special pixels, we will never get to this line of code
392  // when passing in a special pixel.
393  // Left this here just in case the functionality in Angle changes.
394  if (IsSpecial(latitude)) {
395  QString msg = "Invalid planetographic latitudes are not currently "
396  "supported";
398  }
399 
400  double ocentricLatitude = atan(tan(inputAngle.radians()) *
403 
404  // Sometimes the trig functions return the negative of the expected value at the pole.
405  if ((ocentricLatitude > 0) != (inputAngle.radians() > 0)) {
406  ocentricLatitude *= -1;
407  }
408 
409  setAngle(ocentricLatitude, Angle::Radians);
410  }
411 
412 
421  return m_errors;
422  }
423 
424 
434  m_errors = errors;
435  }
436 
437 
452  bool Latitude::inRange(Latitude min, Latitude max) const {
453 
454  // Validity check on the range
455  if (min > max) {
456  QString msg = "Minimum latitude [" + min.toString(true) +
457  "] is greater than maximum latitude [" +
458  max.toString(true) + "]";
460  }
461 
462  // Provide a little wriggle room for precision problems
463  Angle epsilon(DBL_EPSILON, Angle::Degrees);
464  Latitude adjustedMin = min - epsilon;
465  Latitude adjustedMax = max + epsilon;
466 
467  // Is this latitude between the min and the max
468  return *this >= adjustedMin && *this <= adjustedMax;
469  }
470 
471 
480  Latitude& Latitude::operator=(const Latitude & latitudeToCopy) {
481 
482  if (this == &latitudeToCopy) return *this;
483 
484  m_equatorialRadius = NULL;
485  m_polarRadius = NULL;
486 
487  m_errors = latitudeToCopy.m_errors;
488 
489  if (latitudeToCopy.m_equatorialRadius) {
490  m_equatorialRadius = new Distance(*latitudeToCopy.m_equatorialRadius);
491  }
492 
493  if (latitudeToCopy.m_polarRadius) {
494  m_polarRadius = new Distance(*latitudeToCopy.m_polarRadius);
495  }
496 
497  setPlanetocentric(latitudeToCopy.planetocentric());
498 
499  return *this;
500  }
501 
502 
516  Latitude Latitude::add(Angle angleToAdd, PvlGroup mapping) {
517 
518  CoordinateType latType;
519 
520  Distance equatorialRadius;
521  Distance polarRadius;
522  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
523  equatorialRadius = Distance(toDouble(mapping["EquatorialRadius"][0]),
525  polarRadius = Distance(toDouble(mapping["PolarRadius"][0]),
527  }
528  else {
529  try {
530  PvlGroup radiiGrp = Target::radiiGroup(mapping["TargetName"][0]);
531  equatorialRadius = Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
533  polarRadius = Distance(toDouble(radiiGrp["PolarRadius"][0]),
535  }
536  catch (IException &e) {
537  QString msg = "Unable to add angle to Latitude object from given mapping group.";
538  throw IException(e, IException::Unknown, msg, _FILEINFO_);
539  }
540  }
541 
542  if (mapping["LatitudeType"][0] == "Planetocentric")
543  latType = Planetocentric;
544  else if (mapping["LatitudeType"][0] == "Planetographic")
545  latType = Planetographic;
546  else {
547  QString msg = "Latitude type [" + mapping["LatitudeType"][0] + "] is not recognized";
549  }
550 
551  return add(angleToAdd, equatorialRadius, polarRadius, latType);
552  }
553 
554 
566  Distance equatorialRadius,
567  Distance polarRadius,
568  CoordinateType latType) {
569  Latitude result;
570 
571  switch (latType) {
572  case Planetocentric:
573  result = Latitude(planetocentric() + angleToAdd.radians(), equatorialRadius, polarRadius,
574  latType, Radians, m_errors);
575  break;
576 
577  case Planetographic:
578  result = Latitude(planetographic() + angleToAdd.radians(), equatorialRadius, polarRadius,
579  latType, Radians, m_errors);
580  break;
581  }
582 
583  return result;
584  }
585 
586 
596  void Latitude::setAngle(const double &angle,
597  const Angle::Units &units) {
598 
599  // Check for passing 90 degrees if that error checking is on
601  Angle tmpAngle(angle, units);
602  if (tmpAngle > Angle(90, Angle::Degrees) ||
603  tmpAngle < Angle(-90, Angle::Degrees)) {
604  QString msg = "Latitudes past 90 degrees are not valid. The latitude ["
605  + Isis::toString(tmpAngle.degrees(), 8) + "] is not allowed";
607  }
608  }
609  Angle::setAngle(angle, units);
610  }
611 }
void setErrorChecking(ErrorChecking errors)
Set the error checking status.
Definition: Latitude.cpp:433
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Units
The set of usable angle measurement units.
Definition: Angle.h:66
Distance * m_polarRadius
Used for converting to Planetographic, this is the radius of the target perpendicular to the equatori...
Definition: Latitude.h:183
Don&#39;t throw an exception if a latitude beyond -90/90 is found.
Definition: Latitude.h:87
double planetographic(Angle::Units units=Angle::Radians) const
Get the latitude in the planetographic coordinate system.
Definition: Latitude.cpp:328
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
virtual void setAngle(const double &angle, const Units &unit)
Set angle value in desired units.
Definition: Angle.cpp:338
Latitude()
Create a blank Latitude object without Planetographic support.
Definition: Latitude.cpp:38
double planetocentric(Angle::Units units=Angle::Radians) const
Get the latitude in the planetocentric (universal) coordinate system.
Definition: Latitude.cpp:295
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
Distance measurement, usually in meters.
Definition: Distance.h:47
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
This is the universal (and default) latitude coordinate system.
Definition: Latitude.h:103
ErrorChecking m_errors
This contains which exceptions should not be thrown.
Definition: Latitude.h:186
bool inRange(Latitude min, Latitude max) const
Checks if this latitude value is within the given range.
Definition: Latitude.cpp:452
This is a secondary coordinate system for latitudes.
Definition: Latitude.h:115
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
Angle()
Constructs a blank angle object which needs a value to be set in order to do any calculations.
Definition: Angle.cpp:38
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
virtual QString toString(bool includeUnits=true) const
Get the angle in human-readable form.
Definition: Angle.cpp:258
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
Definition: Target.cpp:393
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
void setPlanetographic(double latitude, Angle::Units units=Angle::Radians)
Set the latitude given a value in the Planetographic coordinate system.
Definition: Latitude.cpp:373
void setPlanetocentric(double latitude, Angle::Units units=Angle::Radians)
Set the latitude given a value in the Planetocentric coordinate system.
Definition: Latitude.cpp:306
ErrorChecking errorChecking() const
Get the error checking status.
Definition: Latitude.cpp:420
Distance * m_equatorialRadius
Used for converting to Planetographic, this is the radius of the target on the equatorial plane...
Definition: Latitude.h:178
virtual void setAngle(const double &angle, const Angle::Units &units)
Same as planetocentric.
Definition: Latitude.cpp:596
Defines an angle and provides unit conversions.
Definition: Angle.h:62
virtual double angle(const Units &unit) const
Return angle value in desired units.
Definition: Angle.cpp:304
~Latitude()
This cleans up the Latitude class.
Definition: Latitude.cpp:273
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
ErrorChecking
Some user-configurable error checking parameters.
Definition: Latitude.h:83
CoordinateType
These are the latitude coordinate systems.
Definition: Latitude.h:97
The distance is being specified in meters.
Definition: Distance.h:56
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition: Angle.h:80
Latitude add(Angle angleToAdd, PvlGroup mapping)
Adds an angle to this latitude.
Definition: Latitude.cpp:516
Latitude & operator=(const Latitude &latitudeToCopy)
This assigns another latitude to this one - making this latitude an exact duplicate of the other...
Definition: Latitude.cpp:480
Unless noted otherwise, the portions of Isis written by the USGS are public domain.