Isis 3 Programmer Reference
ObliqueCylindrical.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ObliqueCylindrical.h"
8
9#include <cfloat>
10#include <cmath>
11
12#include <SpiceUsr.h>
13
14#include "Constants.h"
15#include "IException.h"
16#include "TProjection.h"
17#include "Pvl.h"
18#include "PvlGroup.h"
19#include "PvlKeyword.h"
20#include "NaifStatus.h"
21
22using namespace std;
23namespace Isis {
37 ObliqueCylindrical::ObliqueCylindrical(Pvl &label, bool allowDefaults) :
38 TProjection::TProjection(label) {
39 try {
40 // Try to read the mapping group
41 PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
42
43 m_poleLatitude = mapGroup["PoleLatitude"];
44
45 // All latitudes must be planetographic
46 if (IsPlanetocentric()) {
48 }
49
50 if (m_poleLatitude < -90 || m_poleLatitude > 90) {
52 "Pole latitude must be between -90 and 90.",
53 _FILEINFO_);
54 }
55
56 m_poleLongitude = mapGroup["PoleLongitude"];
57
58 if (m_poleLongitude < -360 || m_poleLongitude > 360) {
60 "Pole longitude must be between -360 and 360.",
61 _FILEINFO_);
62 }
63
64 m_poleRotation = mapGroup["PoleRotation"];
65
66 if (m_poleRotation < -360 || m_poleRotation > 360) {
68 "Pole rotation must be between -360 and 360.",
69 _FILEINFO_);
70 }
71
72 bool calculateVectors = false;
73
74 // Check vectors for the right array size
75 if (!mapGroup.hasKeyword("XAxisVector")
76 || mapGroup["XAxisVector"].size() != 3) {
77 calculateVectors = true;
78 }
79
80 if (!mapGroup.hasKeyword("YAxisVector")
81 || mapGroup["YAxisVector"].size() != 3) {
82 calculateVectors = true;
83 }
84
85 if (!mapGroup.hasKeyword("ZAxisVector")
86 || mapGroup["ZAxisVector"].size() != 3) {
87 calculateVectors = true;
88 }
89
90 if (!calculateVectors) {
91 // Read in vectors
92 m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][0]));
93 m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][1]));
94 m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][2]));
95
96 m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][0]));
97 m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][1]));
98 m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][2]));
99
100 m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][0]));
101 m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][1]));
102 m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][2]));
103 }
104 else {
105 // Calculate the vectors and store them in the labels
106 // The vectors are useful for processing later on, but are
107 // not actually used here
108 double rotationAngle = m_poleRotation * (PI / 180.0);
109 double latitudeAngle = (90.0 - m_poleLatitude) * (PI / 180.0);
110 double longitudeAngle = (360.0 - m_poleLongitude) * (PI / 180.0);
111 double pvec[3][3];
112
114 eul2m_c(rotationAngle, latitudeAngle, longitudeAngle, 3, 2, 3, pvec);
116
117 // Reset the vector keywords
118 if (mapGroup.hasKeyword("XAxisVector")) {
119 mapGroup.deleteKeyword("XAxisVector");
120 }
121 if (mapGroup.hasKeyword("YAxisVector")) {
122 mapGroup.deleteKeyword("YAxisVector");
123 }
124 if (mapGroup.hasKeyword("ZAxisVector")) {
125 mapGroup.deleteKeyword("ZAxisVector");
126 }
127
128 mapGroup += PvlKeyword("XAxisVector");
129 mapGroup += PvlKeyword("YAxisVector");
130 mapGroup += PvlKeyword("ZAxisVector");
131
132 // Store calculations both in vector and PVL
133 for (int i = 0; i < 3; i++) {
134 m_xAxisVector.push_back(pvec[0][i]); //X[i]
135 m_yAxisVector.push_back(pvec[1][i]); //Y[i]
136 m_zAxisVector.push_back(pvec[2][i]); //Z[i]
137
138 mapGroup["XAxisVector"] += toString(pvec[0][i]); //X[i]
139 mapGroup["YAxisVector"] += toString(pvec[1][i]); //Y[i]
140 mapGroup["ZAxisVector"] += toString(pvec[2][i]); //Z[i]
141 }
142 }
143
144 init();
145 }
146 catch(IException &e) {
147 QString message = "Invalid label group [Mapping]";
148 throw IException(e, IException::Io, message, _FILEINFO_);
149 }
150 }
151
155
165 if (!Projection::operator==(proj)) return false;
166
167 ObliqueCylindrical *obProjection = (ObliqueCylindrical *) &proj;
168
169 if (obProjection->poleLatitude() != poleLatitude()) return false;
170 if (obProjection->poleLongitude() != poleLongitude()) return false;
171 if (obProjection->poleRotation() != poleRotation()) return false;
172
173 return true;
174 }
175
181 QString ObliqueCylindrical::Name() const {
182 return "ObliqueCylindrical";
183 }
184
192 return "1.0";
193 }
194
207 bool ObliqueCylindrical::SetGround(const double lat, const double lon) {
208 double normalLat, normalLon; // normal lat/lon
209 double obliqueLat, obliqueLon; // oblique lat/lon copy
210
211 // Store lat,lon
212 m_latitude = lat;
213 m_longitude = lon;
214
215 // Use oblat,oblon as radians version of lat,lon now for calculations
216 normalLat = m_latitude * PI / 180.0;
217 normalLon = m_longitude * PI / 180.0;
218 if (m_longitudeDirection == PositiveWest) normalLon *= -1.0;
219
220
221 /***************************************************************************
222 * Calculate the oblique lat/lon from the normal lat/lon
223 ***************************************************************************/
224 double poleLatitude = (m_poleLatitude * PI / 180.0);
225 double poleLongitude = (m_poleLongitude * PI / 180.0);
226 double poleRotation = (m_poleRotation * PI / 180.0);
227
228 obliqueLat = asin(sin(poleLatitude) * sin(normalLat) +
229 cos(poleLatitude) * cos(normalLat)
230 * cos(normalLon - poleLongitude));
231
232 obliqueLon = atan2(cos(normalLat) * sin(normalLon - poleLongitude),
233 sin(poleLatitude) * cos(normalLat)
234 * cos(normalLon - poleLongitude) -
235 cos(poleLatitude) * sin(normalLat)) - poleRotation;
236
237 while(obliqueLon < - PI) {
238 obliqueLon += (2.0 * PI);
239 }
240
241 while(obliqueLon >= PI) {
242 obliqueLon -= (2.0 * PI);
243 }
244
245 // Compute the coordinate
246 double x = m_equatorialRadius * obliqueLon;
247 double y = m_equatorialRadius * obliqueLat;
248 SetComputedXY(x, y);
249
250 m_good = true;
251 return m_good;
252 }
253
267 bool ObliqueCylindrical::SetCoordinate(const double x, const double y) {
268 // Save the coordinate
269 SetXY(x, y);
270
271 /***************************************************************************
272 * Calculate the oblique latitude and check to see if it is outside or equal
273 * to [-90,90]. If it is, return with an error.
274 ***************************************************************************/
276
277 if (abs(abs(m_latitude) - HALFPI) < DBL_EPSILON) {
278 m_good = false;
279 return m_good;
280 }
281
282 /***************************************************************************
283 * The check to see if m_equatorialRadius == 0 is done in the init function
284 ***************************************************************************/
286
287 /***************************************************************************
288 * Convert the oblique lat/lon to normal lat/lon
289 ***************************************************************************/
290 double obliqueLat, obliqueLon;
291 double poleLatitude = (m_poleLatitude * PI / 180.0);
292 double poleLongitude = (m_poleLongitude * PI / 180.0);
293 double poleRotation = (m_poleRotation * PI / 180.0);
294
295 obliqueLat = asin(sin(poleLatitude) * sin(m_latitude) -
296 cos(poleLatitude) * cos(m_latitude) * cos(m_longitude + poleRotation));
297
298 obliqueLon = atan2(cos(m_latitude) * sin(m_longitude + poleRotation),
299 sin(poleLatitude) * cos(m_latitude) * cos(m_longitude + poleRotation) +
301
302 /***************************************************************************
303 * Convert the latitude/longitude to degrees and apply target longitude
304 * direction correction to the longitude
305 ***************************************************************************/
306 m_latitude = obliqueLat * 180.0 / PI;
307 m_longitude = obliqueLon * 180.0 / PI;
308
309 // Cleanup the longitude
311
312 m_good = true;
313 return m_good;
314 }
315
345 bool ObliqueCylindrical::XYRange(double &minX, double &maxX,
346 double &minY, double &maxY) {
347 return xyRangeOblique(minX, maxX, minY, maxY);
348 }
349
350
357 PvlGroup mapping = TProjection::Mapping();
358
359 mapping += m_mappingGrp["PoleLatitude"];
360 mapping += m_mappingGrp["PoleLongitude"];
361 mapping += m_mappingGrp["PoleRotation"];
362
363 return mapping;
364 }
365
376
387
395 return m_poleLatitude;
396 }
397
405 return m_poleLongitude;
406 }
407
415 return m_poleRotation;
416 }
417
418 void ObliqueCylindrical::init() {
419 /***************************************************************************
420 * Apply target correction for longitude direction
421 ***************************************************************************/
424
425 /***************************************************************************
426 * Check that m_equatorialRadius isn't zero because we'll divide by it later
427 ***************************************************************************/
428 if (abs(m_equatorialRadius) <= DBL_EPSILON) {
430 "The input center latitude is too close to a pole "
431 "which will result in a division by zero.",
432 _FILEINFO_);
433 }
434 }
435
436} // end namespace isis
437
449extern "C" Isis::Projection *ObliqueCylindricalPlugin(Isis::Pvl &lab,
450 bool allowDefaults) {
451 return new Isis::ObliqueCylindrical(lab, allowDefaults);
452}
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Oblique Cylindrical Map Projection.
QString Version() const
Returns the version of the map projection.
std::vector< double > m_xAxisVector
The x-axis vector, read from the mapping group in the label.
~ObliqueCylindrical()
Destroys the ObliqueCylindrical object.
bool SetGround(const double lat, const double lon)
This method is used to set the latitude/longitude (assumed to be of the correct LatitudeType,...
bool operator==(const Isis::Projection &proj)
Compares two Projection objects to see if they are equal.
ObliqueCylindrical(Isis::Pvl &label, bool allowDefaults=false)
Constructs an ObliqueCylindrical object.
std::vector< double > m_yAxisVector
The y-axis vector, read from the mapping group in the label.
std::vector< double > m_zAxisVector
The z-axis vector, read from the mapping group in the label.
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
double poleRotation() const
Returns the value of the pole rotation.
double m_poleLongitude
The Oblique Pole Longitude.
double poleLongitude() const
Returns the value of the pole longitude.
double m_poleLatitude
The Oblique Pole Latitude.
QString Name() const
Returns the name of the map projection, "ObliqueCylindrical".
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...
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double poleLatitude() const
Returns the value of the pole latitude.
PvlGroup Mapping()
This function returns the keywords that this projection uses.
double m_poleRotation
The Oblique Pole Rotation.
Base class for Map Projections.
Definition Projection.h:155
double GetX() const
Calculates the unrotated form of current x value.
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition Projection.h:300
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition Projection.h:329
double GetY() const
Calculates the unrotated form of the current y value.
void SetXY(double x, double y)
This protected method is a helper for derived classes.
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
Base class for Map TProjections.
double m_longitude
This contains the currently set longitude value.
bool xyRangeOblique(double &minX, double &maxX, double &minY, double &maxY)
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
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.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
@ PositiveWest
Longitude values increase in the westerly direction.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
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 HALFPI
The mathematical constant PI/2.
Definition Constants.h:41
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.