Isis 3 Programmer Reference
Robinson.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "Robinson.h"
8 
9 #include <cmath>
10 #include <cfloat>
11 
12 #include "Constants.h"
13 #include "IException.h"
14 #include "Projection.h"
15 #include "Pvl.h"
16 #include "PvlGroup.h"
17 #include "PvlKeyword.h"
18 
19 const double EPSILON = 1.0e-10;
20 
21 using namespace std;
22 namespace Isis {
23 
40  Robinson::Robinson(Pvl &label, bool allowDefaults) :
41  TProjection::TProjection(label) {
42  try {
43 
44  // Initialize coefficients
45  // PR Add xtra element at beginning to mimic 1-based arrays to match Snyder's code for
46  // easier debugging.
47  m_pr << 0 << -.062 <<
48  0 <<
49  0.062 <<
50  0.124 <<
51  0.186 <<
52  0.248 <<
53  0.310 <<
54  0.372 <<
55  0.434 <<
56  0.4958 <<
57  0.5571 <<
58  0.6176 <<
59  0.6769 <<
60  0.7346 <<
61  0.7903 <<
62  0.8435 <<
63  0.8936 <<
64  0.9394 <<
65  0.9761 <<
66  1.;
67  // XLR
68  m_xlr << 0 << 0.9986 <<
69  1.0 <<
70  0.9986 <<
71  0.9954 <<
72  0.99 <<
73  0.9822 <<
74  0.973 <<
75  0.96 <<
76  0.9427 <<
77  0.9216 <<
78  0.8962 <<
79  0.8679 <<
80  0.835 <<
81  0.7986 <<
82  0.7597 <<
83  0.7186 <<
84  0.6732 <<
85  0.6213 <<
86  0.5722 <<
87  0.5322;
88 
89  // Try to read the mapping group
90  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
91 
92  // Compute and write the default center longitude if allowed and
93  // necessary
94  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
95  double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
96  mapGroup += PvlKeyword("CenterLongitude", toString(lon));
97  }
98 
99  // Get the center longitude
100  m_centerLongitude = mapGroup["CenterLongitude"];
101 
102  // convert to radians, adjust for longitude direction
105  }
106  catch(IException &e) {
107  QString message = "Invalid label group [Mapping]";
108  throw IException(e, IException::Io, message, _FILEINFO_);
109  }
110  }
111 
114  }
115 
124  bool Robinson::operator== (const Projection &proj) {
125  if (!Projection::operator==(proj)) return false;
126  // dont do the below it is a recusive plunge
127  // if (Projection::operator!=(proj)) return false;
128  Robinson *robin = (Robinson *) &proj;
129  if (robin->m_centerLongitude != m_centerLongitude) return false;
130  return true;
131  }
132 
138  QString Robinson::Name() const {
139  return "Robinson";
140  }
141 
148  QString Robinson::Version() const {
149  return "1.0";
150  }
151 
164  bool Robinson::SetGround(const double lat, const double lon) {
165  // Convert to radians
166  m_latitude = lat;
167  m_longitude = lon;
168  double latRadians = lat * DEG2RAD;
169  double lonRadians = lon * DEG2RAD;
170  if (m_longitudeDirection == PositiveWest) lonRadians *= -1.0;
171 
172  // Compute the coordinate
173  double deltaLon = (lonRadians - m_centerLongitude);
174  double p2 = fabs(latRadians / 5.0 / DEG2RAD);
175  long ip1 = (long) (p2 - EPSILON);
176  if (ip1 > 17) {
177  return false;
178  }
179 
180  // Stirling's interpolation formula (using 2nd Diff.)
181  //
182  p2 -= (double) ip1;
183  double x = 0.8487 * m_equatorialRadius * (m_xlr[ip1 + 2] + p2 * (m_xlr[ip1 + 3] -
184  m_xlr[ip1 + 1]) / 2.0 +
185  p2 * p2 * (m_xlr[ip1 + 3] - 2.0 * m_xlr[ip1 + 2] +
186  m_xlr[ip1 + 1])/2.0) * deltaLon;
187 
188  double y = 1.3523 * m_equatorialRadius * (m_pr[ip1 + 2] + p2 * (m_pr[ip1 + 3] -
189  m_pr[ip1 +1]) / 2.0 + p2 * p2 * (m_pr[ip1 + 3] -
190  2.0 * m_pr[ip1 + 2] + m_pr[ip1 + 1]) / 2.0);
191  if (lat < 0) y *= -1.;
192 
193  SetComputedXY(x, y);
194  m_good = true;
195  return m_good;
196  }
197 
198 
212  bool Robinson::SetCoordinate(const double x, const double y) {
213  m_latitude = 0;
214  m_longitude = 0;
215  // Save the coordinate
216  SetXY(x, y);
217 
218  double yy = y / m_equatorialRadius / 1.3523;
219  double phid = yy * 90.0;
220  double p2 = fabs(phid / 5.0);
221  long ip1 = (long) (p2 - EPSILON);
222  if (ip1 == 0) ip1 = 1;
223  if (ip1 > 17) {
224  return false;
225  }
226 
227  // Stirling's interpolation formula as used in forward transformation is
228  // reversed for first estimation of LAT. from rectangular coordinates. LAT.
229  // is then adjusted by iteration until use of forward series provides correct
230  // value of Y within tolerance.
231  //
232  double u, v, t, c;
233  double y1;
234 
235  for (int i = 0;;) {
236  u = m_pr[ip1 + 3] - m_pr[ip1 + 1];
237  v = m_pr[ip1 + 3] - 2.0 * m_pr[ip1 + 2] + m_pr[ip1 + 1];
238  t = 2.0 * (fabs(yy) - m_pr[ip1 + 2]) / u;
239  c = v / u;
240  p2 = t * (1.0 - c * t * (1.0 - 2.0 * c * t));
241 
242  if ((p2 >= 0.0) || (ip1 == 1)) {
243  phid = (p2 + (double) ip1 ) * 5.0;
244  if (y < 0) phid *= -1;
245 
246  do {
247  p2 = fabs(phid / 5.0);
248  ip1 = (long) (p2 - EPSILON);
249  if (ip1 > 17) {
250  return false;
251  }
252  p2 -= (double) ip1;
253 
254  y1 = 1.3523 * m_equatorialRadius * (m_pr[ip1 +2] + p2 *(m_pr[ip1 + 3] -
255  m_pr[ip1 +1]) / 2.0 + p2 * p2 * (m_pr[ip1 + 3] -
256  2.0 * m_pr[ip1 + 2] + m_pr[ip1 + 1])/2.0);
257  if (y < 0) y1 *= -1.;
258 
259  phid -= (90.0 * (y1 - y) / m_equatorialRadius / 1.3523);
260  i++;
261  if (i > 75) {
262  return false;
263  }
264  } while (fabs(y1 - y) > .00001);
265  break;
266  }
267  else {
268  ip1--;
269  if (ip1 < 0) {
270  return false;
271  }
272  }
273  }
274 
275  // Compute latitude and make sure it is not above 90
276  m_latitude = phid;
277 
278  // Calculate longitude. using final latitude. with transposed forward Stirling's
279  // interpolation formula.
280  m_longitude = m_centerLongitude + x / m_equatorialRadius / 0.8487 / (m_xlr[ip1 + 2] +
281  p2 * (m_xlr[ip1 + 3] - m_xlr[ip1 + 1]) / 2.0 +
282  p2 * p2 * (m_xlr[ip1 + 3] - 2.0 * m_xlr[ip1 + 2] +
283  m_xlr[ip1 + 1]) / 2.0);
284  m_longitude *= RAD2DEG;
286 
287  // Our double precision is not good once we pass a certain magnitude of
288  // longitude. Prevent failures down the road by failing now.
289  m_good = (fabs(m_longitude) < 1E10);
290  return m_good;
291  }
292 
293 
317  bool Robinson::XYRange(double &minX, double &maxX,
318  double &minY, double &maxY) {
319 
320  // Check the corners of the lat/lon range
325 
326  // If the latitude crosses the equator check there
327  if ((m_minimumLatitude < 0.0) && (m_maximumLatitude > 0.0)) {
330  }
331 
332  // Make sure everything is ordered
333  if (m_minimumX >= m_maximumX) return false;
334  if (m_minimumY >= m_maximumY) return false;
335 
336  // Return X/Y min/maxs
337  minX = m_minimumX;
338  maxX = m_maximumX;
339  minY = m_minimumY;
340  maxY = m_maximumY;
341  return true;
342  }
343 
344 
351  PvlGroup mapping = TProjection::Mapping();
352 
353  mapping += m_mappingGrp["CenterLongitude"];
354 
355  return mapping;
356  }
357 
365 
366  return mapping;
367  }
368 
376 
377  mapping += m_mappingGrp["CenterLongitude"];
378 
379  return mapping;
380  }
381 
382 } // end namespace isis
383 
396 extern "C" Isis::Projection *RobinsonPlugin(Isis::Pvl &lab,
397  bool allowDefaults) {
398  return new Isis::Robinson(lab, allowDefaults);
399 }
Isis::TProjection::m_maximumLatitude
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
Definition: TProjection.h:356
Isis::Robinson::operator==
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
Definition: Robinson.cpp:124
Isis::TProjection::m_longitude
double m_longitude
This contains the currently set longitude value.
Definition: TProjection.h:318
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::IException::Io
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:155
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::Robinson::Version
QString Version() const
Returns the version of the map projection.
Definition: Robinson.cpp:148
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::DEG2RAD
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:43
Isis::Projection::m_minimumY
double m_minimumY
See minimumX description.
Definition: Projection.h:327
Isis::Robinson::MappingLongitudes
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition: Robinson.cpp:374
Isis::Robinson::m_centerLongitude
double m_centerLongitude
The center longitude for the map projection.
Definition: Robinson.h:73
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::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::Robinson::MappingLatitudes
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: Robinson.cpp:363
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::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::Robinson::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: Robinson.cpp: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::TProjection
Base class for Map TProjections.
Definition: TProjection.h:166
Isis::Robinson::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: Robinson.cpp:164
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Robinson::Mapping
PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition: Robinson.cpp:350
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
std
Namespace for the standard library.
Isis::Robinson::Name
QString Name() const
Returns the name of the map projection, "Robinson".
Definition: Robinson.cpp:138
Isis::Robinson::~Robinson
~Robinson()
Destroys the Robinson object.
Definition: Robinson.cpp:113
Isis::Robinson::SetCoordinate
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
Definition: Robinson.cpp:212
Isis::TProjection::m_maximumLongitude
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
Definition: TProjection.h:360
Isis::TProjection::MappingLatitudes
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: TProjection.cpp:1723
Isis::TProjection::Mapping
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition: TProjection.cpp:1698
Isis::TProjection::m_equatorialRadius
double m_equatorialRadius
Polar radius of the target.
Definition: TProjection.h:335
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::RAD2DEG
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition: Constants.h:44
Isis::Robinson
Robinson Map Projection.
Definition: Robinson.h:52
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16