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
19const double EPSILON = 1.0e-10;
20
21using namespace std;
22namespace 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
115
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);
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
396extern "C" Isis::Projection *RobinsonPlugin(Isis::Pvl &lab,
397 bool allowDefaults) {
398 return new Isis::Robinson(lab, allowDefaults);
399}
Isis exception class.
Definition IException.h:91
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Base class for Map Projections.
Definition Projection.h:155
double m_maximumX
See minimumX description.
Definition Projection.h:326
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition Projection.h:300
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition Projection.h:317
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition Projection.h:329
double m_minimumY
See minimumX description.
Definition Projection.h:327
void SetXY(double x, double y)
This protected method is a helper for derived classes.
double m_maximumY
See minimumX description.
Definition Projection.h:328
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
Robinson Map Projection.
Definition Robinson.h:52
double m_centerLongitude
The center longitude for the map projection.
Definition Robinson.h:73
~Robinson()
Destroys the Robinson object.
Definition Robinson.cpp:113
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
QString Version() const
Returns the version of the map projection.
Definition Robinson.cpp:148
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition Robinson.cpp:363
PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition Robinson.cpp:350
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
Robinson(Pvl &label, bool allowDefaults=false)
Constructs a Robinson object.
Definition Robinson.cpp:40
bool operator==(const Projection &proj)
Compares two Projection objects to see if they are equal.
Definition Robinson.cpp:124
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
Definition Robinson.cpp:212
QString Name() const
Returns the name of the map projection, "Robinson".
Definition Robinson.cpp:138
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition Robinson.cpp:374
Base class for Map TProjections.
double m_longitude
This contains the currently set longitude value.
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
double m_equatorialRadius
Polar radius of the target.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
@ PositiveWest
Longitude values increase in the westerly direction.
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double m_latitude
This contains the currently set latitude value.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition Constants.h:43
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
Namespace for the standard library.