USGS

Isis 3.0 Object Programmers' Reference

Home

Mercator.cpp
Go to the documentation of this file.
1 
23 #include "Mercator.h"
24 
25 #include <cmath>
26 #include <cfloat>
27 
28 #include "IException.h"
29 #include "Constants.h"
30 #include "TProjection.h"
31 #include "Pvl.h"
32 #include "PvlGroup.h"
33 #include "PvlKeyword.h"
34 
35 using namespace std;
36 namespace Isis {
53  Mercator::Mercator(Pvl &label, bool allowDefaults) :
54  TProjection::TProjection(label) {
55  try {
56  // Try to read the mapping group
57  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
58 
59  // Compute and write the default center longitude if allowed and
60  // necessary
61  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
62  double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
63  mapGroup += PvlKeyword("CenterLongitude", toString(lon));
64  }
65 
66  // Compute and write the default center latitude if allowed and
67  // necessary
68  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
69  double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
70  mapGroup += PvlKeyword("CenterLatitude", toString(lat));
71  }
72 
73  // Get the center longitude & latitude
74  m_centerLongitude = mapGroup["CenterLongitude"];
75  m_centerLatitude = mapGroup["CenterLatitude"];
76  if (IsPlanetocentric()) {
78  }
79 
80  // convert to radians, adjust for longitude direction
81  m_centerLongitude *= PI / 180.0;
82  m_centerLatitude *= PI / 180.0;
84 
85  // Compute the scale factor
86  double cos_clat = cos(m_centerLatitude);
87  double sin_clat = sin(m_centerLatitude);
88  double m_eccsq = Eccentricity() * Eccentricity();
89  m_scalefactor = cos_clat / sqrt(1.0 - m_eccsq * sin_clat * sin_clat);
90  }
91  catch (IException &e) {
92  QString message = "Invalid label group [Mapping]";
93  throw IException(e, IException::Io, message, _FILEINFO_);
94  }
95  }
96 
99  }
100 
109  bool Mercator::operator== (const Projection &proj) {
110  if (!Projection::operator==(proj)) return false;
111  // don't do the below it is a recusive plunge
112  // if (Projection::operator!=(proj)) return false;
113  Mercator *merc = (Mercator *) &proj;
114  if ((merc->m_centerLongitude != m_centerLongitude) ||
115  (merc->m_centerLatitude != m_centerLatitude)) return false;
116  return true;
117  }
118 
124  QString Mercator::Name() const {
125  return "Mercator";
126  }
127 
134  QString Mercator::Version() const {
135  return "1.0";
136  }
137 
145  return m_centerLatitude * 180.0 / PI;
146  }
147 
154  return true;
155  }
156 
169  bool Mercator::SetGround(const double lat, const double lon) {
170  // Convert longitude to radians & clean up
171  m_longitude = lon;
172  double lonRadians = lon * PI / 180.0;
173  if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
174 
175  // Now convert latitude to radians & clean up ... it must be planetographic
176  m_latitude = lat;
177  double latRadians = lat;
178  if (IsPlanetocentric()) latRadians = ToPlanetographic(latRadians);
179  latRadians *= PI / 180.0;
180 
181  // Make sure latitude value is not too close to either pole
182  if (fabs(fabs(m_latitude) - 90.0) <= DBL_EPSILON) {
183  m_good = false;
184  return m_good;
185  }
186 
187  // Compute the coordinate
188  double deltaLon = (lonRadians - m_centerLongitude);
189  double x = m_equatorialRadius * deltaLon * m_scalefactor;
190  double sinphi = sin(latRadians);
191  double t = tCompute(latRadians, sinphi);
192  double y = -m_equatorialRadius * m_scalefactor * log(t);
193  SetComputedXY(x, y);
194  m_good = true;
195  return m_good;
196  }
197 
211  bool Mercator::SetCoordinate(const double x, const double y) {
212  // Save the coordinate
213  SetXY(x, y);
214 
215  // Compute Snyder's t
216  double snyders_t = exp(-GetY() / (m_equatorialRadius * m_scalefactor));
217 
218  // Compute latitude and make sure it is not above 90
219  m_latitude = phi2Compute(snyders_t);
220  if (fabs(m_latitude) > HALFPI) {
221  if (fabs(HALFPI - fabs(m_latitude)) > DBL_EPSILON) {
222  m_good = false;
223  return m_good;
224  }
225  else if (m_latitude < 0.0) {
226  m_latitude = -HALFPI;
227  }
228  else {
229  m_latitude = HALFPI;
230  }
231  }
232 
233  // Compute longitude
234  double coslat = cos(m_latitude);
235  if (coslat <= DBL_EPSILON) {
237  }
238  else {
241  }
242 
243  // Convert to degrees
244  m_latitude *= 180.0 / PI;
245  m_longitude *= 180.0 / PI;
246 
247  // Cleanup the longitude
249  // These need to be done for circular type projections
250  // m_longitude = To360Domain (m_longitude);
251  // if (m_longitudeDomain == 180) m_longitude = To180Domain(m_longitude);
252 
253  // Cleanup the latitude
255 
256  m_good = true;
257  return m_good;
258  }
259 
283  bool Mercator::XYRange(double &minX, double &maxX,
284  double &minY, double &maxY) {
285  // Check the corners of the lat/lon range
290 
291  // Make sure everything is ordered
292  if (m_minimumX >= m_maximumX) return false;
293  if (m_minimumY >= m_maximumY) return false;
294 
295  // Return X/Y min/maxs
296  minX = m_minimumX;
297  maxX = m_maximumX;
298  minY = m_minimumY;
299  maxY = m_maximumY;
300  return true;
301  }
302 
309  PvlGroup mapping = TProjection::Mapping();
310 
311  mapping += m_mappingGrp["CenterLatitude"];
312  mapping += m_mappingGrp["CenterLongitude"];
313 
314  return mapping;
315  }
316 
324 
325  mapping += m_mappingGrp["CenterLatitude"];
326 
327  return mapping;
328  }
329 
337 
338  mapping += m_mappingGrp["CenterLongitude"];
339 
340  return mapping;
341  }
342 
343 } // end namespace isis
344 
359  bool allowDefaults) {
360  return new Isis::Mercator(lab, allowDefaults);
361 }
362 
363