Isis 3 Programmer Reference
PolarStereographic.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "PolarStereographic.h"
8 
9 #include <cmath>
10 #include <cfloat>
11 #include <iostream>
12 
13 #include "Constants.h"
14 #include "IException.h"
15 #include "TProjection.h"
16 #include "Pvl.h"
17 #include "PvlGroup.h"
18 #include "PvlKeyword.h"
19 
20 using namespace std;
21 namespace Isis {
42  PolarStereographic::PolarStereographic(Pvl &label, bool allowDefaults) :
43  TProjection::TProjection(label) {
44  try {
45  // Try to read the mapping group
46  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
47 
48  // Compute and write the default center longitude if allowed and
49  // necessary
50  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
51  double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
52  mapGroup += PvlKeyword("CenterLongitude", toString(lon));
53  }
54 
55  // Compute and write the default center latitude if allowed and
56  // necessary
57  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
58  double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
59  if (lat > 0.0) {
60  mapGroup += PvlKeyword("CenterLatitude", toString(90.0));
61  }
62  else {
63  mapGroup += PvlKeyword("CenterLatitude", toString(-90.0));
64  }
65  }
66 
67  // Get the center longitude, convert to radians and adjust for longitude
68  // direction
69  m_centerLongitude = mapGroup["CenterLongitude"];
70  m_centerLongitude *= PI / 180.0;
72 
73  // Get the center latitude, make sure it is ographic, and convert to
74  // radians.
75  m_centerLatitude = mapGroup["CenterLatitude"];
76  if (m_centerLatitude == 0) {
77  QString msg = "Invalid value for keyword [CenterLatitude] in map file.";
78  msg += " CenterLatitude cannot equal 0.0";
79  throw IException(IException::User, msg, _FILEINFO_);
80  }
81  if (IsPlanetocentric()) {
83  }
84  m_centerLatitude *= PI / 180.0;
85 
86  // Compute some constants
87  m_e4 = e4Compute();
88  m_signFactor = 1.0;
89  if (m_centerLatitude < 0.0) m_signFactor = -1.0;
90 
91  if ((HALFPI - fabs(m_centerLatitude)) > DBL_EPSILON) {
92  m_poleFlag = true; // We are not at a pole
93  double phi = m_signFactor * m_centerLatitude;
94  double sinphi = sin(phi);
95  double cosphi = cos(phi);
96  m_m = mCompute(sinphi, cosphi);
97  m_t = tCompute(phi, sinphi);
98  if (fabs(m_t) < DBL_EPSILON) m_poleFlag = false;
99  }
100  else {
101  m_poleFlag = false; // Implies we are at a pole
102  m_m = 0;
103  m_t = 0;
104  }
105  }
106  catch(IException &e) {
107  QString message = "Invalid label group [Mapping]";
108  throw IException(e, IException::Unknown, message, _FILEINFO_);
109  }
110  }
111 
112 
115  }
116 
117 
127  if (!Projection::operator==(proj)) return false;
128  // dont do the below it is a recusive plunge
129  // if (Projection::operator!=(proj)) return false;
130  PolarStereographic *pola = (PolarStereographic *) &proj;
131  if (pola->m_centerLongitude != m_centerLongitude) return false;
132  if (pola->m_centerLatitude != m_centerLatitude) return false;
133  return true;
134  }
135 
136 
142  QString PolarStereographic::Name() const {
143  return "PolarStereographic";
144  }
145 
146 
153  QString PolarStereographic::Version() const {
154  return "1.0";
155  }
156 
157 
167  return m_centerLatitude * 180.0 / PI;
168  }
169 
170 
183  bool PolarStereographic::SetGround(const double lat, const double lon) {
184  // Fix up longitude
185  m_longitude = lon;
186  double lonRadians = lon * PI / 180.0;
187  if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
188 
189  // Now do latitude ... it must be planetographic
190  m_latitude = lat;
191  double latRadians = lat;
192  if (IsPlanetocentric()) latRadians = ToPlanetographic(latRadians);
193  latRadians = latRadians * PI / 180.0;
194 
195  // Compute easting and northing
196  double lamda = m_signFactor * (lonRadians - m_centerLongitude);
197  double phi = m_signFactor * latRadians;
198  double sinphi = sin(phi);
199  double t = tCompute(phi, sinphi);
200 
201  double dist;
202  if (m_poleFlag) {
203  dist = m_equatorialRadius * m_m * t / m_t;
204  }
205  else {
206  dist = m_equatorialRadius * 2.0 * t / m_e4;
207  }
208 
209  double x = m_signFactor * dist * sin(lamda);
210  double y = -(m_signFactor * dist * cos(lamda));
211  SetComputedXY(x, y);
212 
213  m_good = true;
214 
215  //So we don't project the wrong pole.
216  if (qFuzzyCompare(lat * m_signFactor, -90.0))
217  m_good = false;
218 
219  return m_good;
220  }
221 
222 
236  bool PolarStereographic::SetCoordinate(const double x, const double y) {
237  // Save the coordinate
238  SetXY(x, y);
239 
240  double east = m_signFactor * GetX();
241  double north = m_signFactor * GetY();
242  double dist = sqrt(east * east + north * north);
243 
244  double t;
245  if (m_poleFlag) {
246  t = dist * m_t / (m_m * m_equatorialRadius); // Snyder eqn (21-40)
247  }
248  else {
249  t = dist * m_e4 / (2.0 * m_equatorialRadius); //Snyder eqn (24-39)
250  //when latitude of true scale is North Polar
251  }
252 
253  // Compute the latitude
254  double phi = phi2Compute(t);
255  m_latitude = m_signFactor * phi;
256 
257  if (fabs(m_latitude) > HALFPI) {
258  QString msg = "X,Y causes latitude to be outside [-90,90] "
259  "in PolarStereographic Class";
260  throw IException(IException::Programmer, msg, _FILEINFO_);
261  }
262 
263  // Compute the longitude
264  if (dist == 0.0) {
266  }
267  else {
268  m_longitude = m_signFactor * atan2(east, -north) + m_centerLongitude;
269  }
270 
271  // Cleanup the longitude
272  m_longitude *= 180.0 / PI;
276 
277  // Cleanup the latitude
278  m_latitude *= 180.0 / PI;
280 
281  m_good = true;
282  return m_good;
283  }
284 
285 
309  bool PolarStereographic::XYRange(double &minX, double &maxX,
310  double &minY, double &maxY) {
311  // Check the corners of the lat/lon range
316 
317  // Find the closest longitude >= to the minimum longitude that is offset
318  // from the center longitude by a multiple of 90.
319  double lon1 = m_centerLongitude * 180.0 / PI;
320  if (m_longitudeDirection == PositiveWest) lon1 *= -1.0;
321  while(lon1 > m_minimumLongitude) lon1 -= 90.0;
322  while(lon1 < m_minimumLongitude) lon1 += 90.0;
323 
324  while(lon1 <= m_maximumLongitude) {
327  lon1 += 90.0;
328  }
329 
330  // Make sure everything is ordered
331  if (m_minimumX >= m_maximumX) return false;
332  if (m_minimumY >= m_maximumY) return false;
333 
334  // Return X/Y min/maxs
335  minX = m_minimumX;
336  maxX = m_maximumX;
337  minY = m_minimumY;
338  maxY = m_maximumY;
339  return true;
340  }
341 
342 
349  PvlGroup mapping = TProjection::Mapping();
350 
351  mapping += m_mappingGrp["CenterLatitude"];
352  mapping += m_mappingGrp["CenterLongitude"];
353 
354  return mapping;
355  }
356 
357 
365 
366  mapping += m_mappingGrp["CenterLatitude"];
367 
368  return mapping;
369  }
370 
371 
379 
380  mapping += m_mappingGrp["CenterLongitude"];
381 
382  return mapping;
383  }
384 }
385 
386 
401 extern "C" Isis::Projection *PolarStereographicPlugin(Isis::Pvl &lab,
402  bool allowDefaults) {
403  return new Isis::PolarStereographic(lab, allowDefaults);
404 }
Isis::TProjection::m_maximumLatitude
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
Definition: TProjection.h:356
Isis::HALFPI
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:41
Isis::TProjection::m_longitude
double m_longitude
This contains the currently set longitude value.
Definition: TProjection.h:318
Isis::TProjection::m_longitudeDomain
int m_longitudeDomain
This integer is either 180 or 360 and is read from the labels.
Definition: TProjection.h:331
Isis::PolarStereographic::m_centerLatitude
double m_centerLatitude
The center latitude for the map projection.
Definition: PolarStereographic.h:84
Isis::PolarStereographic::m_e4
double m_e4
Convenience variable for calculations.
Definition: PolarStereographic.h:86
Isis::PvlObject::findGroup
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:129
Isis::TProjection::m_minimumLongitude
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
Definition: TProjection.h:358
Isis::TProjection::m_latitude
double m_latitude
This contains the currently set latitude value.
Definition: TProjection.h:316
Isis::PolarStereographic::m_centerLongitude
double m_centerLongitude
The center longitude for the map projection.
Definition: PolarStereographic.h:83
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::TProjection::m_longitudeDirection
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
Definition: TProjection.h:324
Isis::TProjection::m_minimumLatitude
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
Definition: TProjection.h:354
Isis::TProjection::PositiveWest
@ PositiveWest
Longitude values increase in the westerly direction.
Definition: TProjection.h:225
Isis::TProjection::e4Compute
double e4Compute() const
A convience method to compute.
Definition: TProjection.cpp:1891
Isis::IException::Unknown
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:118
Isis::Projection::m_minimumY
double m_minimumY
See minimumX description.
Definition: Projection.h:327
Isis::Projection::GetX
double GetX() const
Calculates the unrotated form of current x value.
Definition: Projection.cpp:818
Isis::TProjection::tCompute
double tCompute(const double phi, const double sinphi) const
A convience method to compute Snyder's t equation (15-9) for a given latitude, .
Definition: TProjection.cpp:1870
Isis::PvlContainer::hasKeyword
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Definition: PvlContainer.cpp:159
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::Projection::SetXY
void SetXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:804
Isis::TProjection::ToPlanetocentric
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
Definition: TProjection.cpp:418
Isis::PolarStereographic::m_m
double m_m
Snyder's m-value from equation (14-15).
Definition: PolarStereographic.h:88
Isis::TProjection::XYRangeCheck
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method.
Definition: TProjection.cpp:1062
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::Projection::m_mappingGrp
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:329
Isis::Projection::GetY
double GetY() const
Calculates the unrotated form of the current y value.
Definition: Projection.cpp:829
Isis::PvlObject::Traverse
@ Traverse
Search child objects.
Definition: PvlObject.h:158
Isis::Projection::m_minimumX
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition: Projection.h:317
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::Projection::m_good
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition: Projection.h:300
Isis::PolarStereographic::Name
QString Name() const
Returns the name of the map projection, "PolarStereographic".
Definition: PolarStereographic.cpp:142
Isis::TProjection
Base class for Map TProjections.
Definition: TProjection.h:166
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::TProjection::To180Domain
static double To180Domain(const double lon)
This method converts a longitude into the -180 to 180 domain.
Definition: TProjection.cpp:657
Isis::PolarStereographic
Stereographic Map Projection for Polar Aspect.
Definition: PolarStereographic.h:64
Isis::PolarStereographic::m_t
double m_t
Snyder's t-value from equation (15-19).
Definition: PolarStereographic.h:87
Isis::PolarStereographic::TrueScaleLatitude
double TrueScaleLatitude() const
Returns the latitude of true scale.
Definition: PolarStereographic.cpp:166
Isis::TProjection::MappingLongitudes
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition: TProjection.cpp:1739
Isis::Projection::SetComputedXY
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:780
Isis::PolarStereographic::MappingLongitudes
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition: PolarStereographic.cpp:377
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
std
Namespace for the standard library.
Isis::PolarStereographic::m_poleFlag
double m_poleFlag
Indicates whether the center latitude is at a pole.
Definition: PolarStereographic.h:91
Isis::PolarStereographic::Version
QString Version() const
Returns the version of the map projection.
Definition: PolarStereographic.cpp:153
Isis::TProjection::m_maximumLongitude
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
Definition: TProjection.h:360
Isis::PolarStereographic::operator==
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
Definition: PolarStereographic.cpp:126
Isis::PolarStereographic::SetCoordinate
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
Definition: PolarStereographic.cpp:236
Isis::PolarStereographic::SetGround
bool SetGround(const double lat, const double lon)
This method is used to set the latitude/longitude (assumed to be of the correct LatitudeType,...
Definition: PolarStereographic.cpp:183
Isis::TProjection::MappingLatitudes
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: TProjection.cpp:1723
Isis::TProjection::ToPlanetographic
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
Definition: TProjection.cpp:463
Isis::TProjection::phi2Compute
double phi2Compute(const double t) const
A convience method to compute latitude angle phi2 given small t, from Syder's recursive equation (7-9...
Definition: TProjection.cpp:1803
Isis::PolarStereographic::XYRange
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...
Definition: PolarStereographic.cpp:309
Isis::PolarStereographic::MappingLatitudes
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: PolarStereographic.cpp:363
Isis::TProjection::Mapping
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition: TProjection.cpp:1698
Isis::PolarStereographic::Mapping
PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition: PolarStereographic.cpp:348
Isis::TProjection::m_equatorialRadius
double m_equatorialRadius
Polar radius of the target.
Definition: TProjection.h:335
Isis::TProjection::To360Domain
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
Definition: TProjection.cpp:675
Isis::TProjection::IsPlanetocentric
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
Definition: TProjection.cpp:392
Isis::PolarStereographic::m_signFactor
double m_signFactor
If the center latitude is positive, the sign factor is 1.
Definition: PolarStereographic.h:89
Isis::Projection::m_maximumY
double m_maximumY
See minimumX description.
Definition: Projection.h:328
Isis::Projection
Base class for Map Projections.
Definition: Projection.h:155
Isis::Projection::m_maximumX
double m_maximumX
See minimumX description.
Definition: Projection.h:326
Isis::TProjection::mCompute
double mCompute(const double sinphi, const double cosphi) const
A convience method to compute Snyder's m equation (14-15) for a given latitude, .
Definition: TProjection.cpp:1847
Isis::PolarStereographic::~PolarStereographic
~PolarStereographic()
Destroys the PolarStereographic object.
Definition: PolarStereographic.cpp:114
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::IException::User
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition: IException.h:126