USGS

Isis 3.0 Object Programmers' Reference

Home

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 "SpecialPixel.h"
30 #include "TProjection.h"
31 
32 namespace Isis {
37  m_equatorialRadius = NULL;
38  m_polarRadius = NULL;
39 
41  }
42 
43 
54  Latitude::Latitude(double latitude, Angle::Units latitudeUnits,
55  ErrorChecking errors) : Angle() {
56  m_equatorialRadius = NULL;
57  m_polarRadius = NULL;
58 
59  m_errors = errors;
60 
61  setPlanetocentric(latitude, latitudeUnits);
62  }
63 
64 
72  Latitude::Latitude(Angle latitude, ErrorChecking errors) : Angle() {
73  m_equatorialRadius = NULL;
74  m_polarRadius = NULL;
75 
76  m_errors = errors;
77 
78  setPlanetocentric(latitude.radians(), Radians);
79  }
80 
81 
94  Latitude::Latitude(Angle latitude, PvlGroup mapping,
95  ErrorChecking errors) : Angle(latitude) {
96  m_equatorialRadius = NULL;
97  m_polarRadius = NULL;
98 
99  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
100  m_equatorialRadius = new Distance(toDouble(mapping["EquatorialRadius"][0]),
102  m_polarRadius = new Distance(toDouble(mapping["PolarRadius"][0]),
104  }
105  else {
106  PvlGroup radiiGrp = TProjection::TargetRadii(mapping["TargetName"]);
107 
108  m_equatorialRadius = new Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
110  m_polarRadius = new Distance(toDouble(radiiGrp["PolarRadius"][0]),
112  }
113 
114  m_errors = errors;
115 
116  if(mapping["LatitudeType"][0] == "Planetographic") {
117  setPlanetographic(latitude.radians(), Radians);
118  }
119  else if(mapping["LatitudeType"][0] == "Planetocentric") {
120  setPlanetocentric(latitude.radians(), Radians);
121  }
122  else {
123  QString msg = "Latitude type [" + mapping["LatitudeType"][0] +
124  "] is not recognized";
126  }
127  }
128 
129 
142  Latitude::Latitude(double latitude,
143  PvlGroup mapping,
144  Angle::Units latitudeUnits,
145  ErrorChecking errors) : Angle(latitude, latitudeUnits) {
146  m_equatorialRadius = NULL;
147  m_polarRadius = NULL;
148 
149  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
150  m_equatorialRadius = new Distance(toDouble(mapping["EquatorialRadius"][0]),
152  m_polarRadius = new Distance(toDouble(mapping["PolarRadius"][0]),
154  }
155  else {
156  PvlGroup radiiGrp = TProjection::TargetRadii(mapping["TargetName"]);
157 
158  m_equatorialRadius = new Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
160  m_polarRadius = new Distance(toDouble(radiiGrp["PolarRadius"][0]),
162  }
163 
164  m_errors = errors;
165 
166  if(mapping["LatitudeType"][0] == "Planetographic") {
167  setPlanetographic(latitude, latitudeUnits);
168  }
169  else if(mapping["LatitudeType"][0] == "Planetocentric") {
170  setPlanetocentric(latitude, latitudeUnits);
171  }
172  else {
173  IString msg = "Latitude type [" + IString(mapping["LatitudeType"][0]) +
174  "] is not recognized";
176  }
177  }
178 
179 
193  Latitude::Latitude(double latitude,
194  Distance equatorialRadius, Distance polarRadius,
195  CoordinateType latType,
196  Angle::Units latitudeUnits,
197  ErrorChecking errors) : Angle(latitude, latitudeUnits) {
198  m_equatorialRadius = NULL;
199  m_polarRadius = NULL;
200 
201  m_equatorialRadius = new Distance(equatorialRadius);
202  m_polarRadius = new Distance(polarRadius);
203 
204  m_errors = errors;
205 
206  if (latType == Planetocentric) {
207  setPlanetocentric(latitude, latitudeUnits);
208  }
209  else if (latType == Planetographic) {
210  setPlanetographic(latitude, latitudeUnits);
211  }
212  else {
213  IString msg = "Enumeration value [" + IString(latType) + "] is not a "
214  "valid CoordinateType";
216  }
217  }
218 
219 
225  Latitude::Latitude(const Latitude &latitudeToCopy) : Angle(latitudeToCopy) {
226  m_equatorialRadius = NULL;
227  m_polarRadius = NULL;
228 
229  m_errors = latitudeToCopy.m_errors;
230 
231  if(latitudeToCopy.m_equatorialRadius) {
232  m_equatorialRadius = new Distance(*latitudeToCopy.m_equatorialRadius);
233  }
234 
235  if(latitudeToCopy.m_polarRadius) {
236  m_polarRadius = new Distance(*latitudeToCopy.m_polarRadius);
237  }
238  }
239 
240 
245  if (m_equatorialRadius) {
246  delete m_equatorialRadius;
247  m_equatorialRadius = NULL;
248  }
249 
250  if (m_polarRadius) {
251  delete m_polarRadius;
252  m_polarRadius = NULL;
253  }
254  }
255 
256 
265  return angle(units);
266  }
267 
268 
275  void Latitude::setPlanetocentric(double latitude, Angle::Units units) {
276  setAngle(latitude, units);
277  }
278 
279 
290  if (m_equatorialRadius == NULL || m_polarRadius == NULL) {
291  IString msg = "Latitude [" + IString(degrees()) + " degrees] cannot "
292  "be converted to Planetographic without the planetary radii, please "
293  "use the other Latitude constructor";
295  }
296 
297  if (*this > Angle(90.0, Angle::Degrees) ||
298  *this < Angle(-90.0, Angle::Degrees)) {
299  IString msg = "Latitudes outside of the -90/90 range cannot be converted "
300  "between Planetographic and Planetocentric";
302  }
303 
304  if(!isValid()) {
305  IString msg = "Invalid planetographic latitudes are not currently "
306  "supported";
308  }
309 
310  double ographicLatitude = atan(tan(radians()) *
313 
314  // This theoretically should just be an angle, but make it a Latitude so
315  // we can access angle
316  return Latitude(ographicLatitude, Angle::Radians).angle(units);
317  }
318 
319 
326  void Latitude::setPlanetographic(double latitude, Angle::Units units) {
327  if (m_equatorialRadius == NULL || m_polarRadius == NULL) {
328  IString msg = "Latitude [" + IString(latitude) + "] cannot be "
329  "converted to Planetocentic without the planetary radii, please use "
330  "the other Latitude constructor";
332  }
333 
334  Angle inputAngle(latitude, units);
335 
336  if (inputAngle > Angle(90.0, Angle::Degrees) ||
337  inputAngle < Angle(-90.0, Angle::Degrees)) {
338  IString msg = "Latitudes outside of the -90/90 range cannot be converted "
339  "between Planetographic and Planetocentric";
341  }
342 
343  if(IsSpecial(latitude)) {
344  IString msg = "Invalid planetographic latitudes are not currently "
345  "supported";
347  }
348 
349  double ocentricLatitude = atan(tan(inputAngle.radians()) *
352 
353  // Sometimes the trig functions return the negative of the expected value at the pole.
354  if ((ocentricLatitude > 0) != (inputAngle.radians() > 0)) {
355  ocentricLatitude *= -1;
356  }
357 
358  setAngle(ocentricLatitude, Angle::Radians);
359  }
360 
361 
373  bool Latitude::inRange(Latitude min, Latitude max) const {
374  // Validity check on the range
375  if (min > max) {
376  IString msg = "Minimum latitude [" + IString(min.degrees()) +
377  "] degrees is greater than maximum latitude [" +
378  IString(max.degrees()) + "] degrees";
380  }
381 
382  // Provide a little wriggle room for precision problems
383  Angle epsilon(DBL_EPSILON, Angle::Degrees);
384  Latitude adjustedMin = min - epsilon;
385  Latitude adjustedMax = max + epsilon;
386 
387  // Is this latitude between the min and the max
388  return *this >= adjustedMin && *this <= adjustedMax;
389  }
390 
391 
399  Latitude& Latitude::operator=(const Latitude & latitudeToCopy) {
400  if(this == &latitudeToCopy) return *this;
401 
402  m_equatorialRadius = NULL;
403  m_polarRadius = NULL;
404 
405  m_errors = latitudeToCopy.m_errors;
406 
407  if(latitudeToCopy.m_equatorialRadius) {
408  m_equatorialRadius = new Distance(*latitudeToCopy.m_equatorialRadius);
409  }
410 
411  if(latitudeToCopy.m_polarRadius) {
412  m_polarRadius = new Distance(*latitudeToCopy.m_polarRadius);
413  }
414 
415  setPlanetocentric(latitudeToCopy.planetocentric());
416 
417  return *this;
418  }
419 
420 
429  Latitude Latitude::add(Angle angleToAdd, PvlGroup mapping) {
430 
431  CoordinateType latType;
432 
433  Distance equatorialRadius;
434  Distance polarRadius;
435  if (mapping.hasKeyword("EquatorialRadius") && mapping.hasKeyword("PolarRadius")) {
436  equatorialRadius = Distance(toDouble(mapping["EquatorialRadius"][0]),
438  polarRadius = Distance(toDouble(mapping["PolarRadius"][0]),
440  }
441  else {
442  PvlGroup radiiGrp = TProjection::TargetRadii(mapping["TargetName"]);
443 
444  equatorialRadius = Distance(toDouble(radiiGrp["EquatorialRadius"][0]),
446  polarRadius = Distance(toDouble(radiiGrp["PolarRadius"][0]),
448  }
449 
450  if(mapping["LatitudeType"][0] == "Planetocentric")
451  latType = Planetocentric;
452  else if (mapping["LatitudeType"][0] == "Planetographic")
453  latType = Planetographic;
454  else {
455  IString msg = "Latitude type [" + IString(mapping["LatitudeType"][0]) +
456  "] is not recognized";
458  }
459 
460  return add(angleToAdd, equatorialRadius, polarRadius, latType);
461  }
462 
463 
473  Latitude Latitude::add(Angle angleToAdd, Distance equatorialRadius, Distance polarRadius,
474  CoordinateType latType) {
475  Latitude result;
476 
477  switch (latType) {
478  case Planetocentric:
479  result = Latitude(planetocentric() + angleToAdd.radians(), equatorialRadius, polarRadius,
480  latType, Radians, m_errors);
481  break;
482 
483  case Planetographic:
484  result = Latitude(planetographic() + angleToAdd.radians(), equatorialRadius, polarRadius,
485  latType, Radians, m_errors);
486  break;
487  }
488 
489  return result;
490  }
491 
492 
499  void Latitude::setAngle(double angle, const Angle::Units &units) {
500  // Check for passing 90 degrees if that error checking is on
501  if (!IsSpecial(angle) && (m_errors & AllowPastPole) != AllowPastPole) {
502  Angle tmpAngle(angle, units);
503  if(tmpAngle > Angle(90, Angle::Degrees) ||
504  tmpAngle < Angle(-90, Angle::Degrees)) {
505  IString msg = "Latitudes past 90 degrees are not valid. The latitude "
506  "[" + IString(tmpAngle.degrees()) + " degrees] is not allowed";
508  }
509  }
510 
511  Angle::setAngle(angle, units);
512  }
513 }