USGS

Isis 3.0 Object Programmers' Reference

Home

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 }