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 
22 using namespace std;
23 namespace 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 
154  }
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 
191  QString ObliqueCylindrical::Version() const {
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) +
300  cos(poleLatitude) * sin(m_latitude)) + poleLongitude;
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 
373 
374  return mapping;
375  }
376 
384 
385  return mapping;
386  }
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 
449 extern "C" Isis::Projection *ObliqueCylindricalPlugin(Isis::Pvl &lab,
450  bool allowDefaults) {
451  return new Isis::ObliqueCylindrical(lab, allowDefaults);
452 }
Isis::HALFPI
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:41
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_latitude
double m_latitude
This contains the currently set latitude value.
Definition: TProjection.h:316
Isis::ObliqueCylindrical::MappingLatitudes
PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: ObliqueCylindrical.cpp:371
Isis::ObliqueCylindrical::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: ObliqueCylindrical.cpp:345
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::ObliqueCylindrical::operator==
bool operator==(const Isis::Projection &proj)
Compares two Projection objects to see if they are equal.
Definition: ObliqueCylindrical.cpp:164
Isis::TProjection::m_longitudeDirection
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
Definition: TProjection.h:324
Isis::TProjection::PositiveWest
@ PositiveWest
Longitude values increase in the westerly direction.
Definition: TProjection.h:225
Isis::IException::Unknown
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:118
Isis::Projection::GetX
double GetX() const
Calculates the unrotated form of current x value.
Definition: Projection.cpp:818
Isis::TProjection::xyRangeOblique
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...
Definition: TProjection.cpp:1195
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::ObliqueCylindrical::poleLatitude
double poleLatitude() const
Returns the value of the pole latitude.
Definition: ObliqueCylindrical.cpp:394
Isis::NaifStatus::CheckErrors
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Definition: NaifStatus.cpp:28
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::ObliqueCylindrical::m_poleLongitude
double m_poleLongitude
The Oblique Pole Longitude.
Definition: ObliqueCylindrical.h:92
Isis::Projection::m_mappingGrp
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:329
Isis::Projection::GetY
double GetY() const
Calculates the unrotated form of the current y value.
Definition: Projection.cpp:829
Isis::ObliqueCylindrical::poleRotation
double poleRotation() const
Returns the value of the pole rotation.
Definition: ObliqueCylindrical.cpp:414
Isis::PvlObject::Traverse
@ Traverse
Search child objects.
Definition: PvlObject.h:158
Isis::ObliqueCylindrical::SetCoordinate
bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
Definition: ObliqueCylindrical.cpp:267
Isis::ObliqueCylindrical::Mapping
PvlGroup Mapping()
This function returns the keywords that this projection uses.
Definition: ObliqueCylindrical.cpp:356
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::ObliqueCylindrical::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: ObliqueCylindrical.cpp:207
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::ObliqueCylindrical::m_yAxisVector
std::vector< double > m_yAxisVector
The y-axis vector, read from the mapping group in the label.
Definition: ObliqueCylindrical.h:98
Isis::ObliqueCylindrical::m_zAxisVector
std::vector< double > m_zAxisVector
The z-axis vector, read from the mapping group in the label.
Definition: ObliqueCylindrical.h:100
Isis::ObliqueCylindrical::MappingLongitudes
PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition: ObliqueCylindrical.cpp:382
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::ObliqueCylindrical::poleLongitude
double poleLongitude() const
Returns the value of the pole longitude.
Definition: ObliqueCylindrical.cpp:404
Isis::TProjection::MappingLongitudes
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
Definition: TProjection.cpp:1739
Isis::ObliqueCylindrical::Name
QString Name() const
Returns the name of the map projection, "ObliqueCylindrical".
Definition: ObliqueCylindrical.cpp:181
Isis::PvlContainer::deleteKeyword
void deleteKeyword(const QString &name)
Remove a specified keyword.
Definition: PvlContainer.cpp:97
Isis::Projection::SetComputedXY
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:780
Isis::toDouble
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:149
std
Namespace for the standard library.
Isis::TProjection::MappingLatitudes
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
Definition: TProjection.cpp:1723
Isis::TProjection::ToPlanetographic
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
Definition: TProjection.cpp:463
Isis::ObliqueCylindrical::Version
QString Version() const
Returns the version of the map projection.
Definition: ObliqueCylindrical.cpp:191
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::TProjection::IsPlanetocentric
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
Definition: TProjection.cpp:392
Isis::Projection
Base class for Map Projections.
Definition: Projection.h:155
Isis::ObliqueCylindrical::m_xAxisVector
std::vector< double > m_xAxisVector
The x-axis vector, read from the mapping group in the label.
Definition: ObliqueCylindrical.h:96
Isis::ObliqueCylindrical::m_poleRotation
double m_poleRotation
The Oblique Pole Rotation.
Definition: ObliqueCylindrical.h:93
Isis::ObliqueCylindrical::m_poleLatitude
double m_poleLatitude
The Oblique Pole Latitude.
Definition: ObliqueCylindrical.h:91
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::ObliqueCylindrical
Oblique Cylindrical Map Projection.
Definition: ObliqueCylindrical.h:66
Isis::ObliqueCylindrical::~ObliqueCylindrical
~ObliqueCylindrical()
Destroys the ObliqueCylindrical object.
Definition: ObliqueCylindrical.cpp:153