Isis 3 Programmer Reference
UpturnedEllipsoidTransverseAzimuthal.cpp
Go to the documentation of this file.
1 
24 
25 #include <cmath>
26 #include <cfloat>
27 #include <iostream>
28 #include <iomanip>
29 
30 #include <QDebug>
31 
32 #include "Constants.h"
33 #include "IException.h"
34 #include "IString.h"
35 #include "TProjection.h"
36 #include "Pvl.h"
37 #include "PvlGroup.h"
38 #include "PvlKeyword.h"
39 #include "SpecialPixel.h"
40 
41 using namespace std;
42 namespace Isis {
63  UpturnedEllipsoidTransverseAzimuthal::UpturnedEllipsoidTransverseAzimuthal(Pvl &label,
64  bool allowDefaults) :
65  TProjection::TProjection(label) {
66  try {
67  // This algorithm can be found in the professional paper
68  // Cartographic Projections for Small Bodies of the Solar System
69  // by Maria E Fleis, Kira B Shingareva,
70  // Michael M Borisov, Michael V Alexandrovich, and Philip Stooke
71 
72  // Try to read the mapping group
73  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
74 
75  // Compute and write the default center longitude if allowed and
76  // necessary
77  double centerLongitude = 0.0;
78  if (!mapGroup.hasKeyword("CenterLongitude")) {
79  if (allowDefaults) {
80  // centerLongitude still 0.0 here
81  mapGroup += PvlKeyword("CenterLongitude", toString(centerLongitude), "Degrees");
82  }
83  else {
84  QString message = "Cannot project using upturned ellipsoid Transverse Azimuthal";
85  message += " without [CenterLongitude] value. Keyword does not exist";
86  message += " in labels and defaults are not allowed.";
87  throw IException(IException::Unknown, message, _FILEINFO_);
88  }
89  }
90  else {
91  centerLongitude = mapGroup["CenterLongitude"];
92  }
93 
94  if (MinimumLongitude() < centerLongitude - 90.0) {
95  QString message = "MinimumLongitude ["
96  + toString(MinimumLongitude())
97  + "] is invalid. Must be within -90 degrees of the CenterLongitude ["
98  + toString(centerLongitude) + "].";
99  throw IException(IException::Unknown, message, _FILEINFO_);
100  }
101  if (MaximumLongitude() > centerLongitude + 90.0) {
102  QString message = "MaximumLongitude ["
103  + toString(MaximumLongitude())
104  + "] is invalid. Must be within +90 degrees of the CenterLongitude ["
105  + toString(centerLongitude) + "].";
106  throw IException(IException::Unknown, message, _FILEINFO_);
107  }
108 
109  // Get the center longitude & latitude
110  // initialize member variables
111  init(centerLongitude);
112  }
113  catch(IException &e) {
114  QString message = "Invalid label group [Mapping]";
115  throw IException(e, IException::Unknown, message, _FILEINFO_);
116  }
117  }
118 
119 
125  UpturnedEllipsoidTransverseAzimuthal::~UpturnedEllipsoidTransverseAzimuthal() {
126  }
127 
128 
139  bool UpturnedEllipsoidTransverseAzimuthal::operator== (const Projection &proj) {
140  // don't do the below it is a recursive plunge
141  // if (Projection::operator!=(proj)) return false;
142 
143  // all other data members calculated using m_lambda0, m_a and m_b.
144  UpturnedEllipsoidTransverseAzimuthal *tcyl = (UpturnedEllipsoidTransverseAzimuthal *) &proj;
145  if ((tcyl->m_lambda0 != m_lambda0) ||
146  (tcyl->m_a != m_a) ||
147  (tcyl->m_b != m_b)) return false;
148 
149  return true;
150  }
151 
152 
161  return "UpturnedEllipsoidUpturnedEllipsoidTransverseAzimuthal";
162  }
163 
164 
171  return "1.0";
172  }
173 
174 
186  void UpturnedEllipsoidTransverseAzimuthal::init(double centerLongitude) {
187 
188  // adjust for positive east longitude direction and convert to radians
189  if (IsPositiveEast()) {
190  m_lambda0 = centerLongitude * DEG2RAD;
191  }
192  else {
193  m_lambda0 = ToPositiveEast(centerLongitude, 360) * DEG2RAD;
194  }
195  if (Has180Domain()) {
197  }
198  else {
200  }
201 
202  // Initialize miscellaneous protected data elements
203  m_good = false;
204 
205  m_minimumX = DBL_MAX;
206  m_maximumX = -DBL_MAX;
207  m_minimumY = DBL_MAX;
208  m_maximumY = -DBL_MAX;
209 
210  // Descriptions of the variables a, e
211  double axis1 = EquatorialRadius();
212  double axis2 = PolarRadius();
213  m_a = qMax(axis1, axis2); // major axis. generally, this is the larger of the equatorial axes
214  m_b = qMin(axis1, axis2); // minor axis. generally, this is the polar axis
215  m_e = Eccentricity(); // e = sqrt(1 - (b/a)^2)
216  // must be 0 <= e < 1
217  if (qFuzzyCompare(0.0, m_e)) {
218  m_e = 0.0;
219  }
220 
221  // to reduce calculations, calculate some scalar constants:
222  double t0 = m_b / m_a; // equals sqrt( 1 - m_e * m_e );
223  m_t = t0 * t0; // equals 1 - m_e * m_e ;
224  m_t1 = m_e * t0; // equals e/sqrt( 1 - m_e * m_e );
225  double k1 = 2 * m_a * exp(m_t1 * atan(m_t1));
226  // k = radius of the Equator of transverse graticule on Azimuthal projection
227  // under condition of no distortion in the center of projection
228  m_k = k1 * m_t;
229  }
230 
231 
250  const double lon) {
251  // when lat/lon is Null we can't set ground
252  if (lat == Null || lon == Null) {
253  m_good = false;
254  return m_good;
255  }
256 
257  // convert given lat to radians, planetocentric
258  // phiNorm = The planetocentric latitude, in normal aspect.
259  double phiNorm;
260  // when lat just barely beyond pole, set equal to pole
261  if (qFuzzyCompare(90.0, qAbs(lat)) && qAbs(lat) > 90.0) {
262  phiNorm = copysign(HALFPI, lat); // returns sign(lat) * PI/2
263  }
264  // if well beyond pole, it's bad
265  else if (qAbs(lat) > 90.0) {
266  m_good = false;
267  return m_good;
268  }
269  else if (IsPlanetocentric()) {
270  phiNorm = lat * DEG2RAD;
271  }
272  else {
273  // equations expect ocentric latitudes.
274  phiNorm = ToPlanetocentric(lat) * DEG2RAD;
275  }
276 
277  // convert given lon to positive east, then subtract center lon to get
278  // lambdaNorm = longitude east of the center of projection
279  double lambdaNorm;
280  if (IsPositiveEast()) {
281  lambdaNorm = lon * DEG2RAD - m_lambda0;
282  }
283  else {
284  lambdaNorm = ToPositiveEast(lon, 360) * DEG2RAD - m_lambda0;
285  }
286 
287  // Compute the rectangular x,y coordinate using the appropriate set of equations below
288  double x,y;
289 
290  // NOTE: z = the angular distance from the center of projection.
291  double cosz = cos(phiNorm) * cos(lambdaNorm);
292 
293  // First, we take care of the edge cases where
294  // 1. a rounding error causes cosz to be outside of the range of cosine
295  // 2. z == 0 (this could be handled by the next set of equations,
296  // but taking care of it here reduces calculations.)
297  if (cosz >= 1) {
298  // This is the origin,
299  // at lat = equator, lon = centerlon
300  x = 0.0;
301  y = 0.0;
302  }
303 
304  // This condition is used for the set of equations that are
305  // written to exclude the singularities where z == 0 or z == PI
306  // (i.e. the given longitude is equal to the center longitude
307  // or 180 degrees from it).
308  // Use these equations for 0.5 < cosz < 1.0, i.e. 0 < z < PI/3
309  else if (cosz > 0.5) { // && cosz < 1 is implied by bounds on cosine
310  // use pythagorean identity to get sine
311  double sinz = sqrt( 1 - cosz*cosz ); // due to restrictions above sinz != 0
312  // phi = the latitude at "upturned" ellipsoid of revolution
313  // NOTE: Since cos(z) > 0.5 or cos(z) < -0.5,
314  // there is no risk of zero denominator when dividing by cosz
315  double phi = HALFPI - atan2( sinz, m_t * cosz );
316  double sinPhi = sin(phi);
317  // rhoOverTanZ = rho/tanz
318  // where rho = the radius of latitude circle (transverse graticule)
319  // NOTE: We know sin(phi) = -1 only if
320  // phi = PI/2 - arctan(angle) = -PI/2 or 3PI/2
321  // but the range of arctangent is (-PI/2, PI/2),
322  // so there is no risk of zero denominator dividing by (1+sin(phi))
323  double rhoOverTanZ = m_k * sinPhi / ( ( 1 + sinPhi )
324  * m_t
325  * exp( m_t1 * atan( m_t1 * sinPhi ) ) );
326  x = rhoOverTanZ * tan(lambdaNorm);
327  y = rhoOverTanZ * (sin(phiNorm) / cosz ); // Note: cos(z) > 0.5, so no dividing by zero
328  }
329 
330  // This condition is used for the set of equations that are
331  // written to exclude the singularity where z == PI/2.
332  // Use these equations for -1 <= cosz <= 0.5, i.e. PI/3 <= z < PI.
333  else {
334  // For this case, we will restrict z near multiples of PI using a
335  // tolerance value in order to avoid singularities at 0 and PI. We
336  // define zmin and zmax by:
337  //
338  // zmin = minimal value of angular distance from the center of projection
339  // = 0 + angular tolerance
340  // zmax = maximal value of angular distance from the center of projection
341  // in the neighborhood of point opposite to the center of projection
342  // = PI - angular tolerance
343  double tolerance = 0.0016;//???
344  double coszmax = cos(PI - tolerance);
345  double lambdaModulus = fmod(lambdaNorm, TWOPI);
346  if (cosz < coszmax) {
347  cosz = coszmax; // prevents cosz from equalling -1
348  // The following prevent lambdaNorm from being too close to +/-PI
349 
350  // if the given longitude is within tolerance of -PI and less than -PI,
351  // set it to -PI - tolerance)
352  //if (qFuzzyCompare(lambdaNorm, -PI) && lambdaNorm <= -PI) {
353  if (-PI - tolerance < lambdaModulus && lambdaModulus <= -PI) {
354  lambdaNorm = -PI - tolerance;
355  }
356  // if the given longitude is within tolerance of -PI and greater than -PI,
357  // set it to -zmax (i.e. -PI + tolerance)
358  //
359  //if (qFuzzyCompare(lambdaNorm, -PI) && lambdaNorm > -PI) {
360  else if (-PI < lambdaModulus && lambdaModulus <= -PI + tolerance) {
361  lambdaNorm = -PI + tolerance;
362  }
363  // if the given longitude is within tolerance of PI and less than PI,
364  // set it to zmax (i.e. PI - tolerance)
365  //
366  //if (qFuzzyCompare(lambdaNorm, PI) && lambdaNorm <= PI) {
367  else if (PI - tolerance < lambdaModulus && lambdaModulus <= PI) {
368  lambdaNorm = PI - tolerance;
369  }
370  // if the given longitude is within tolerance of PI and greater than PI,
371  // set it to PI + tolerance
372  //
373  //if (qFuzzyCompare(lambdaNorm, PI) && lambdaNorm > PI) {
374  else if (PI < lambdaModulus && lambdaModulus < PI + tolerance) {
375  lambdaNorm = PI + tolerance;
376  }
377  }
378  // use pythagorean identity to get sine
379  double sinz = sqrt( 1 - cosz*cosz ); // due to restrictions above, we know sinz != 0
380 
381  // phi = latitude at "upturned" ellipsoid of revolution
382  // NOTE: On the interval, PI/3 <= z < PI,
383  // we know 0 < sin(z) <= 1,
384  // so there is no risk of zero denom when dividing by sinz
385  double phi = atan2( m_t * cosz, sinz );
386  double sinPhi = sin(phi);
387  // Note: We know sin(phi) = -1 only if
388  // phi = arctan(angle) = -PI/2
389  // but the range of arctangent is the open interval (-PI/2, PI/2),
390  // so there is no risk of zero denominator dividing by (1+sin(phi))
391  double rhoOverSinZ = m_k * cos(phi) / ( ( 1 + sinPhi )
392  * sinz
393  * exp( m_t1 * atan(m_t1 * sinPhi ) ) );
394  x = rhoOverSinZ * cos(phiNorm) * sin(lambdaNorm);
395  y = rhoOverSinZ * sin(phiNorm);
396  }
397 
398  // set member data and return status
399  m_good = true;
400  m_latitude = lat;
401  m_longitude = lon;
402  SetComputedXY(x, y); // sets m_x = x and m_y = y and handles rotation
403  // Note: if x or y are Null, sets m_good back to false
404  return m_good;
405  }
406 
407 
426  const double y) {
427  if (x == Null || y == Null) {
428  m_good = false;
429  return m_good;
430  }
431  // Save the coordinate
432  SetXY(x, y);
433 
434  if (qFuzzyCompare(x + 1.0, 1.0) && qFuzzyCompare(y + 1.0, 1.0)) {
435  // origin
436  m_latitude = 0.0;
438  }
439  else {
440 
441  // We are given the following forward equations:
442  //
443  // x = (rho/sin(z)) * cos(phiNorm) * sin(lambdaNorm)
444  // y = (rho/sin(z)) * sin(phiNorm)
445  // rho/sin(z) = ( k*cos(phi) / [(1+sin(phi))*sin(z)*e^{t1*arctan(t1*sin(phi)}] )
446  // phi = arctan( (1-e^2)*cos(z) / sin(z) )
447  //
448  // So, after simplifying, we can verify x^2 + y^2 = rho^2
449  // Thus, we have two solutions for rho:
450  //
451  // rho = +/- sqrt(x^2 + y^2)
452  // rho = ( k*cos(phi) / [(1+sin(phi))*e^{t1*arctan(t1*sin(phi)}] )
453  //
454  // Now, we can use Newton's root finding method for the function
455  // f(phi) = g(phi) - h(phi) on [-pi/2, pi/2]
456  // where
457  // g(phi) = k*cos(phi) / [(1+sin(phi))*e^{t1*arctan(t1*sin(phi)}]
458  // and
459  // h(phi) = sqrt(x^2 + y^2).
460  //
461  // After simplifying, the derivative with respect to phi is
462  // f'(phi) = -k * (1 + t1^2) /
463  // [(1 + sin(phi)) * e^{t1 * arctan(t1 * sin(phi)} * (1 + t1^2 * sin^2(phi))]
464 
465  double phi0, fphi0, fprimephi0, phi1;
466  bool converged = false;
467  int iterations = 0;
468  double tolerance = 10e-10;
469  phi0 = 0.0; // start at the equator???
470  while (!converged && iterations < 1000) {
471  fphi0 = m_k * cos(phi0) / ((1 + sin(phi0)) * exp(m_t1 * atan( m_t1 * sin(phi0) )))
472  - sqrt(x*x + y*y);
473 
474  fprimephi0 = -m_k * (1 + m_t1 * m_t1)
475  / ((1 + sin(phi0))
476  * exp(m_t1 * atan( m_t1 * sin(phi0) ))
477  * (1 + m_t1 * m_t1 * sin(phi0) * sin(phi0)));
478  phi1 = phi0 - fphi0 / fprimephi0;
479  // if phi wrapped at the poles, make sure phi is on [-pi/2, pi/2]
480  if (qAbs(phi1) > HALFPI) {
481  double phiDegrees = To180Domain(phi1*RAD2DEG);
482  if (phiDegrees > 90.0) {
483  phiDegrees -= 90.0;
484  }
485  if (phiDegrees < -180.0) {
486  phiDegrees += 90.0;
487  }
488  phi1 = phiDegrees * DEG2RAD;
489  }
490  if (qAbs(phi0 - phi1) < tolerance) {
491  converged = true;
492  }
493  else {
494  phi0 = phi1;
495  iterations++;
496  }
497  }
498 
499  if (!converged) {
500  m_good = false;
501  return m_good;
502  }
503 
504  // Now we have phi, the latitude at "upturned" ellipsoid of revolution.
505  double phi = phi1;
506 
507  // Now use the forward equation for phi to solve for z, the angular distance from the center
508  // of projection:
509  //
510  // phi = arctan( (1-e^2) * cos(z) / sin(z))
511  //
512  double z = atan2((1 - m_e * m_e), tan(phi)); // see handling of cylind???
513 
514  // Get phiNorm,the planetocentric latitude, in normal aspect. The range of arcsine is
515  // [-pi/2, pi/2] so we are guaranteed to get an angle between the poles. Use the forward
516  // equation:
517  //
518  // y = (rho / sinz ) * sin(phiNorm)
519  //double rho = ( m_k * cos(phi) / ((1+sin(phi))*exp(m_e, m_t1*arctan(m_t1*sin(phi))) );
520  double rho = sqrt(x*x + y*y);
521  double phiNorm = asin( y * sin(z) / rho );
522 
523  // Get lambdaNorm, the longitude east of lambda0, using the forward equation
524  // cos(z) = cos(phiNorm) * cos(lambdaNorm)
525  double lambdaNorm;
526 
527  // make sure we are in the correct quadrant...
528  double cosLambdaNorm = cos(z) / cos(phiNorm);
529  if (cosLambdaNorm > 1.0) {
530  lambdaNorm = 0.0;
531  }
532  else if (cosLambdaNorm < -1.0) {
533  lambdaNorm = PI; // +/- PI doesn't matter here... same answer either way
534  }
535  else if (x >= 0 && y >= 0) {
536  lambdaNorm = acos(cosLambdaNorm);
537  }
538  else if (x < 0 && y >= 0) {// fix conditional???
539  lambdaNorm = -acos(cosLambdaNorm);
540  }
541  else if (y < 0 && x >= 0) {// fix conditional???
542  lambdaNorm = acos(cosLambdaNorm);
543  }
544  else { // y < 0 && x < 0
545  lambdaNorm = -acos(cosLambdaNorm);
546  }
547 
548  // calculations give positive east longitude
549  m_longitude = (lambdaNorm + m_lambda0) * RAD2DEG;
550  m_latitude = phiNorm * RAD2DEG;
551  }
552 
553  // Cleanup the latitude
554  if (IsPlanetocentric()) {
556  }
557 
558  // Cleanup the longitude
559  if (IsPositiveWest()) {
561  }
562 
563  if (Has180Domain()) {
565  }
566  else {
567  // Do this because longitudeDirection could cause (-360,0)
569  }
570 
571  m_good = true;
572  return m_good;
573  }
574 
575 
612  bool UpturnedEllipsoidTransverseAzimuthal::XYRange(double &minX, double &maxX,
613  double &minY, double &maxY) {
614 
615  // First check combinations of the lat/lon range boundaries
620 
621  double centerLongitude = m_lambda0 * RAD2DEG;
622 
623  bool centerLongitudeInRange = TProjection::inLongitudeRange(centerLongitude);
624  bool centerLongitude90InRange = TProjection::inLongitudeRange(centerLongitude + 90.0);
625  bool centerLongitude180InRange = TProjection::inLongitudeRange(centerLongitude + 180.0);
626  bool centerLongitude270InRange = TProjection::inLongitudeRange(centerLongitude + 270.0);
627 
628  if (centerLongitudeInRange) {
629  XYRangeCheck(m_minimumLatitude, centerLongitude);
630  XYRangeCheck(m_maximumLatitude, centerLongitude);
631  }
632  if (centerLongitude90InRange) {
633  XYRangeCheck(m_minimumLatitude, centerLongitude + 90.0);
634  XYRangeCheck(m_maximumLatitude, centerLongitude + 90.0);
635  }
636  if (centerLongitude180InRange) {
637  XYRangeCheck(m_minimumLatitude, centerLongitude + 180.0);
638  XYRangeCheck(m_maximumLatitude, centerLongitude + 180.0);
639  }
640  if (centerLongitude270InRange) {
641  XYRangeCheck(m_minimumLatitude, centerLongitude + 270.0);
642  XYRangeCheck(m_maximumLatitude, centerLongitude + 270.0);
643  }
644 
645  if (TProjection::inLatitudeRange(0.0)) {
648  if (centerLongitudeInRange) {
649  XYRangeCheck(0.0, centerLongitude);
650  }
651  if (centerLongitude90InRange) {
652  XYRangeCheck(0.0, centerLongitude + 90.0);
653  }
654  if (centerLongitude180InRange) {
655  XYRangeCheck(0.0, centerLongitude + 180.0);
656  }
657  if (centerLongitude270InRange) {
658  XYRangeCheck(0.0, centerLongitude + 270.0);
659  }
660  }
661 
662  // Make sure everything is ordered
663  if (m_minimumX >= m_maximumX) return false;
664  if (m_minimumY >= m_maximumY) return false;
665 
666  // Return X/Y min/maxs
667  minX = m_minimumX;
668  maxX = m_maximumX;
669  minY = m_minimumY;
670  maxY = m_maximumY;
671  return true;
672  }
673 
674 
700  PvlGroup mapping = TProjection::Mapping();
701  mapping += PvlKeyword("CenterLongitude", toString(m_lambda0 * RAD2DEG));
702  return mapping;
703  }
704 
705 
722  }
723 
724 
741  PvlGroup mapping = TProjection::MappingLongitudes();
742  mapping += PvlKeyword("CenterLongitude", toString(m_lambda0 * RAD2DEG));
743  return mapping;
744  }
745 
746 } // end namespace isis
747 
763 extern "C" Isis::Projection *UpturnedEllipsoidTransverseAzimuthalPlugin(Isis::Pvl &lab,
764  bool allowDefaults) {
765  return new Isis::UpturnedEllipsoidTransverseAzimuthal(lab, allowDefaults);
766 }
767 
double EquatorialRadius() const
This returns the equatorial radius of the target.
virtual bool SetGround(const double lat, const double lon)
This method is used to set the latitude/longitude (assumed to be of the correct LatitudeType, LongitudeDirection, and LongitudeDomain.
virtual QString Name() const
This method returns the name of the map projection.
bool inLatitudeRange(double latitude)
Determine whether the given latitude is within the range of the MinimumLatitude and MaximumLatitude r...
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
const double PI
The mathematical constant PI.
Definition: Constants.h:56
virtual bool XYRange(double &minX, double &maxX, double &minY, double &maxY)
This method is used to determine the x/y range which completely covers the area of interest specified...
bool IsPositiveEast() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:57
Namespace for the standard library.
Search child objects.
Definition: PvlObject.h:170
double m_k
The radius of the Equator of the transverse graticule on the Azimuthal projection under the condition...
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition: Projection.h:333
virtual QString Version() const
This method returns the Version of the map projection.
bool inLongitudeRange(double longitude)
Determine whether the given longitude is within the range of the MinimumLongitude and MaximumLongitud...
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
double m_t
Auxiliary value used to reduce calculations.
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:795
double m_latitude
This contains the currently set latitude value.
Definition: TProjection.h:332
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
double m_maximumY
See minimumX description.
Definition: Projection.h:344
double m_longitude
This contains the currently set longitude value.
Definition: TProjection.h:334
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
Definition: TProjection.h:376
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
Definition: TProjection.h:370
static double ToPositiveWest(const double lon, const int domain)
This method converts a longitude into the positive west direction.
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
Definition: TProjection.h:372
Base class for Map Projections.
Definition: Projection.h:171
double m_minimumY
See minimumX description.
Definition: Projection.h:343
double Eccentricity() const
This returns the eccentricity of the target,.
const double TWOPI
Two * PI, a complete revolution.
Definition: Constants.h:58
int m_longitudeDomain
This integer is either 180 or 360 and is read from the labels.
Definition: TProjection.h:347
static double To180Domain(const double lon)
This method converts a longitude into the -180 to 180 domain.
bool Has180Domain() const
This indicates if the longitude domain is -180 to 180 (as opposed to 0 to 360).
Upturned Ellipsoid Transverse Azimuthal Map Projection.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the equatorial radiu...
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
double m_lambda0
The longitude of the center of the projection.
Container for cube-like labels.
Definition: Pvl.h:135
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:59
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition: Projection.h:316
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
bool IsPositiveWest() const
This indicates if the longitude direction type is positive east (as opposed to postive west)...
double PolarRadius() const
This returns the polar radius of the target.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition: Constants.h:60
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
void SetXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:819
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method...
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
Definition: TProjection.h:374
double m_t1
Auxiliary value used to reduce calculations.
double m_maximumX
See minimumX description.
Definition: Projection.h:342
static double ToPositiveEast(const double lon, const int domain)
This method converts a longitude into the positive east direction.