Isis 3 Programmer Reference
PolarStereographic.cpp
Go to the documentation of this file.
1 
23 #include "PolarStereographic.h"
24 
25 #include <cmath>
26 #include <cfloat>
27 #include <iostream>
28 
29 #include "Constants.h"
30 #include "IException.h"
31 #include "TProjection.h"
32 #include "Pvl.h"
33 #include "PvlGroup.h"
34 #include "PvlKeyword.h"
35 
36 using namespace std;
37 namespace Isis {
58  PolarStereographic::PolarStereographic(Pvl &label, bool allowDefaults) :
59  TProjection::TProjection(label) {
60  try {
61  // Try to read the mapping group
62  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
63 
64  // Compute and write the default center longitude if allowed and
65  // necessary
66  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
67  double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
68  mapGroup += PvlKeyword("CenterLongitude", toString(lon));
69  }
70 
71  // Compute and write the default center latitude if allowed and
72  // necessary
73  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
74  double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
75  if (lat > 0.0) {
76  mapGroup += PvlKeyword("CenterLatitude", toString(90.0));
77  }
78  else {
79  mapGroup += PvlKeyword("CenterLatitude", toString(-90.0));
80  }
81  }
82 
83  // Get the center longitude, convert to radians and adjust for longitude
84  // direction
85  m_centerLongitude = mapGroup["CenterLongitude"];
86  m_centerLongitude *= PI / 180.0;
88 
89  // Get the center latitude, make sure it is ographic, and convert to
90  // radians.
91  m_centerLatitude = mapGroup["CenterLatitude"];
92  if (m_centerLatitude == 0) {
93  QString msg = "Invalid value for keyword [CenterLatitude] in map file.";
94  msg += " CenterLatitude cannot equal 0.0";
96  }
97  if (IsPlanetocentric()) {
99  }
100  m_centerLatitude *= PI / 180.0;
101 
102  // Compute some constants
103  m_e4 = e4Compute();
104  m_signFactor = 1.0;
105  if (m_centerLatitude < 0.0) m_signFactor = -1.0;
106 
107  if ((HALFPI - fabs(m_centerLatitude)) > DBL_EPSILON) {
108  m_poleFlag = true; // We are not at a pole
109  double phi = m_signFactor * m_centerLatitude;
110  double sinphi = sin(phi);
111  double cosphi = cos(phi);
112  m_m = mCompute(sinphi, cosphi);
113  m_t = tCompute(phi, sinphi);
114  if (fabs(m_t) < DBL_EPSILON) m_poleFlag = false;
115  }
116  else {
117  m_poleFlag = false; // Implies we are at a pole
118  m_m = 0;
119  m_t = 0;
120  }
121  }
122  catch(IException &e) {
123  QString message = "Invalid label group [Mapping]";
124  throw IException(e, IException::Unknown, message, _FILEINFO_);
125  }
126  }
127 
128 
131  }
132 
133 
143  if (!Projection::operator==(proj)) return false;
144  // dont do the below it is a recusive plunge
145  // if (Projection::operator!=(proj)) return false;
146  PolarStereographic *pola = (PolarStereographic *) &proj;
147  if (pola->m_centerLongitude != m_centerLongitude) return false;
148  if (pola->m_centerLatitude != m_centerLatitude) return false;
149  return true;
150  }
151 
152 
158  QString PolarStereographic::Name() const {
159  return "PolarStereographic";
160  }
161 
162 
169  QString PolarStereographic::Version() const {
170  return "1.0";
171  }
172 
173 
183  return m_centerLatitude * 180.0 / PI;
184  }
185 
186 
199  bool PolarStereographic::SetGround(const double lat, const double lon) {
200  // Fix up longitude
201  m_longitude = lon;
202  double lonRadians = lon * PI / 180.0;
203  if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
204 
205  // Now do latitude ... it must be planetographic
206  m_latitude = lat;
207  double latRadians = lat;
208  if (IsPlanetocentric()) latRadians = ToPlanetographic(latRadians);
209  latRadians = latRadians * PI / 180.0;
210 
211  // Compute easting and northing
212  double lamda = m_signFactor * (lonRadians - m_centerLongitude);
213  double phi = m_signFactor * latRadians;
214  double sinphi = sin(phi);
215  double t = tCompute(phi, sinphi);
216 
217  double dist;
218  if (m_poleFlag) {
219  dist = m_equatorialRadius * m_m * t / m_t;
220  }
221  else {
222  dist = m_equatorialRadius * 2.0 * t / m_e4;
223  }
224 
225  double x = m_signFactor * dist * sin(lamda);
226  double y = -(m_signFactor * dist * cos(lamda));
227  SetComputedXY(x, y);
228 
229  m_good = true;
230 
231  //So we don't project the wrong pole.
232  if (qFuzzyCompare(lat * m_signFactor, -90.0))
233  m_good = false;
234 
235  return m_good;
236  }
237 
238 
252  bool PolarStereographic::SetCoordinate(const double x, const double y) {
253  // Save the coordinate
254  SetXY(x, y);
255 
256  double east = m_signFactor * GetX();
257  double north = m_signFactor * GetY();
258  double dist = sqrt(east * east + north * north);
259 
260  double t;
261  if (m_poleFlag) {
262  t = dist * m_t / (m_m * m_equatorialRadius); // Snyder eqn (21-40)
263  }
264  else {
265  t = dist * m_e4 / (2.0 * m_equatorialRadius); //Snyder eqn (24-39)
266  //when latitude of true scale is North Polar
267  }
268 
269  // Compute the latitude
270  double phi = phi2Compute(t);
271  m_latitude = m_signFactor * phi;
272 
273  if (fabs(m_latitude) > HALFPI) {
274  QString msg = "X,Y causes latitude to be outside [-90,90] "
275  "in PolarStereographic Class";
277  }
278 
279  // Compute the longitude
280  if (dist == 0.0) {
282  }
283  else {
284  m_longitude = m_signFactor * atan2(east, -north) + m_centerLongitude;
285  }
286 
287  // Cleanup the longitude
288  m_longitude *= 180.0 / PI;
292 
293  // Cleanup the latitude
294  m_latitude *= 180.0 / PI;
296 
297  m_good = true;
298  return m_good;
299  }
300 
301 
325  bool PolarStereographic::XYRange(double &minX, double &maxX,
326  double &minY, double &maxY) {
327  // Check the corners of the lat/lon range
332 
333  // Find the closest longitude >= to the minimum longitude that is offset
334  // from the center longitude by a multiple of 90.
335  double lon1 = m_centerLongitude * 180.0 / PI;
336  if (m_longitudeDirection == PositiveWest) lon1 *= -1.0;
337  while(lon1 > m_minimumLongitude) lon1 -= 90.0;
338  while(lon1 < m_minimumLongitude) lon1 += 90.0;
339 
340  while(lon1 <= m_maximumLongitude) {
343  lon1 += 90.0;
344  }
345 
346  // Make sure everything is ordered
347  if (m_minimumX >= m_maximumX) return false;
348  if (m_minimumY >= m_maximumY) return false;
349 
350  // Return X/Y min/maxs
351  minX = m_minimumX;
352  maxX = m_maximumX;
353  minY = m_minimumY;
354  maxY = m_maximumY;
355  return true;
356  }
357 
358 
365  PvlGroup mapping = TProjection::Mapping();
366 
367  mapping += m_mappingGrp["CenterLatitude"];
368  mapping += m_mappingGrp["CenterLongitude"];
369 
370  return mapping;
371  }
372 
373 
381 
382  mapping += m_mappingGrp["CenterLatitude"];
383 
384  return mapping;
385  }
386 
387 
395 
396  mapping += m_mappingGrp["CenterLongitude"];
397 
398  return mapping;
399  }
400 }
401 
402 
418  bool allowDefaults) {
419  return new Isis::PolarStereographic(lab, allowDefaults);
420 }
double m_centerLatitude
The center latitude for the map projection.
double m_signFactor
If the center latitude is positive, the sign factor is 1.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
double mCompute(const double sinphi, const double cosphi) const
A convience method to compute Snyder&#39;s m equation (14-15) for a given latitude, . ...
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
double tCompute(const double phi, const double sinphi) const
A convience method to compute Snyder&#39;s t equation (15-9) for a given latitude, .
~PolarStereographic()
Destroys the PolarStereographic object.
const double PI
The mathematical constant PI.
Definition: Constants.h:56
Isis::Projection * PolarStereographicPlugin(Isis::Pvl &lab, bool allowDefaults)
This is the function that is called in order to instantiate an PolarStereographic object...
Longitude values increase in the westerly direction.
Definition: TProjection.h:241
Base class for Map TProjections.
Definition: TProjection.h:182
double m_e4
Convenience variable for calculations.
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:57
Namespace for the standard library.
double m_centerLongitude
The center longitude for the map projection.
Search child objects.
Definition: PvlObject.h:170
double GetX() const
Calculates the unrotated form of current x value.
Definition: Projection.cpp:833
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition: Projection.h:333
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
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
Stereographic Map Projection for Polar Aspect.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double m_m
Snyder&#39;s m-value from equation (14-15).
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
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 m_equatorialRadius
Polar radius of the target.
Definition: TProjection.h:351
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.
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#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
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
QString Name() const
Returns the name of the map projection, "PolarStereographic".
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
QString Version() const
Returns the version of the map projection.
double m_t
Snyder&#39;s t-value from equation (15-19).
Container for cube-like labels.
Definition: Pvl.h:135
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
double phi2Compute(const double t) const
A convience method to compute latitude angle phi2 given small t, from Syder&#39;s recursive equation (7-9...
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
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.
double e4Compute() const
A convience method to compute.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
Definition: TProjection.h:340
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
PvlGroup Mapping()
This function returns the keywords that this projection uses.
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
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.
double TrueScaleLatitude() const
Returns the latitude of true scale.
double GetY() const
Calculates the unrotated form of the current y value.
Definition: Projection.cpp:844
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
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
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...
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_poleFlag
Indicates whether the center latitude is at a pole.
double m_maximumX
See minimumX description.
Definition: Projection.h:342
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:345