USGS

Isis 3.0 Object Programmers' Reference

Home

ObliqueCylindrical.cpp
Go to the documentation of this file.
1 
23 #include "ObliqueCylindrical.h"
24 
25 #include <cfloat>
26 #include <cmath>
27 
28 #include <SpiceUsr.h>
29 
30 #include "Constants.h"
31 #include "IException.h"
32 #include "TProjection.h"
33 #include "Pvl.h"
34 #include "PvlGroup.h"
35 #include "PvlKeyword.h"
36 
37 using namespace std;
38 namespace Isis {
52  ObliqueCylindrical::ObliqueCylindrical(Pvl &label, bool allowDefaults) :
53  TProjection::TProjection(label) {
54  try {
55  // Try to read the mapping group
56  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
57 
58  m_poleLatitude = mapGroup["PoleLatitude"];
59 
60  // All latitudes must be planetographic
61  if (IsPlanetocentric()) {
63  }
64 
65  if (m_poleLatitude < -90 || m_poleLatitude > 90) {
67  "Pole latitude must be between -90 and 90.",
68  _FILEINFO_);
69  }
70 
71  m_poleLongitude = mapGroup["PoleLongitude"];
72 
73  if (m_poleLongitude < -360 || m_poleLongitude > 360) {
75  "Pole longitude must be between -360 and 360.",
76  _FILEINFO_);
77  }
78 
79  m_poleRotation = mapGroup["PoleRotation"];
80 
81  if (m_poleRotation < -360 || m_poleRotation > 360) {
83  "Pole rotation must be between -360 and 360.",
84  _FILEINFO_);
85  }
86 
87  bool calculateVectors = false;
88 
89  // Check vectors for the right array size
90  if (!mapGroup.hasKeyword("XAxisVector")
91  || mapGroup["XAxisVector"].size() != 3) {
92  calculateVectors = true;
93  }
94 
95  if (!mapGroup.hasKeyword("YAxisVector")
96  || mapGroup["YAxisVector"].size() != 3) {
97  calculateVectors = true;
98  }
99 
100  if (!mapGroup.hasKeyword("ZAxisVector")
101  || mapGroup["ZAxisVector"].size() != 3) {
102  calculateVectors = true;
103  }
104 
105  if (!calculateVectors) {
106  // Read in vectors
107  m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][0]));
108  m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][1]));
109  m_xAxisVector.push_back(toDouble(mapGroup["XAxisVector"][2]));
110 
111  m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][0]));
112  m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][1]));
113  m_yAxisVector.push_back(toDouble(mapGroup["YAxisVector"][2]));
114 
115  m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][0]));
116  m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][1]));
117  m_zAxisVector.push_back(toDouble(mapGroup["ZAxisVector"][2]));
118  }
119  else {
120  // Calculate the vectors and store them in the labels
121  // The vectors are useful for processing later on, but are
122  // not actually used here
123  double rotationAngle = m_poleRotation * (PI / 180.0);
124  double latitudeAngle = (90.0 - m_poleLatitude) * (PI / 180.0);
125  double longitudeAngle = (360.0 - m_poleLongitude) * (PI / 180.0);
126  double pvec[3][3];
127 
128  eul2m_c(rotationAngle, latitudeAngle, longitudeAngle, 3, 2, 3, pvec);
129 
130  // Reset the vector keywords
131  if (mapGroup.hasKeyword("XAxisVector")) {
132  mapGroup.deleteKeyword("XAxisVector");
133  }
134  if (mapGroup.hasKeyword("YAxisVector")) {
135  mapGroup.deleteKeyword("YAxisVector");
136  }
137  if (mapGroup.hasKeyword("ZAxisVector")) {
138  mapGroup.deleteKeyword("ZAxisVector");
139  }
140 
141  mapGroup += PvlKeyword("XAxisVector");
142  mapGroup += PvlKeyword("YAxisVector");
143  mapGroup += PvlKeyword("ZAxisVector");
144 
145  // Store calculations both in vector and PVL
146  for (int i = 0; i < 3; i++) {
147  m_xAxisVector.push_back(pvec[0][i]); //X[i]
148  m_yAxisVector.push_back(pvec[1][i]); //Y[i]
149  m_zAxisVector.push_back(pvec[2][i]); //Z[i]
150 
151  mapGroup["XAxisVector"] += toString(pvec[0][i]); //X[i]
152  mapGroup["YAxisVector"] += toString(pvec[1][i]); //Y[i]
153  mapGroup["ZAxisVector"] += toString(pvec[2][i]); //Z[i]
154  }
155  }
156 
157  init();
158  }
159  catch(IException &e) {
160  QString message = "Invalid label group [Mapping]";
161  throw IException(e, IException::Io, message, _FILEINFO_);
162  }
163  }
164 
167  }
168 
178  if (!Projection::operator==(proj)) return false;
179 
180  ObliqueCylindrical *obProjection = (ObliqueCylindrical *) &proj;
181 
182  if (obProjection->poleLatitude() != poleLatitude()) return false;
183  if (obProjection->poleLongitude() != poleLongitude()) return false;
184  if (obProjection->poleRotation() != poleRotation()) return false;
185 
186  return true;
187  }
188 
194  QString ObliqueCylindrical::Name() const {
195  return "ObliqueCylindrical";
196  }
197 
204  QString ObliqueCylindrical::Version() const {
205  return "1.0";
206  }
207 
220  bool ObliqueCylindrical::SetGround(const double lat, const double lon) {
221  double normalLat, normalLon; // normal lat/lon
222  double obliqueLat, obliqueLon; // oblique lat/lon copy
223 
224  // Store lat,lon
225  m_latitude = lat;
226  m_longitude = lon;
227 
228  // Use oblat,oblon as radians version of lat,lon now for calculations
229  normalLat = m_latitude * PI / 180.0;
230  normalLon = m_longitude * PI / 180.0;
231  if (m_longitudeDirection == PositiveWest) normalLon *= -1.0;
232 
233 
234  /***************************************************************************
235  * Calculate the oblique lat/lon from the normal lat/lon
236  ***************************************************************************/
237  double poleLatitude = (m_poleLatitude * PI / 180.0);
238  double poleLongitude = (m_poleLongitude * PI / 180.0);
239  double poleRotation = (m_poleRotation * PI / 180.0);
240 
241  obliqueLat = asin(sin(poleLatitude) * sin(normalLat) +
242  cos(poleLatitude) * cos(normalLat)
243  * cos(normalLon - poleLongitude));
244 
245  obliqueLon = atan2(cos(normalLat) * sin(normalLon - poleLongitude),
246  sin(poleLatitude) * cos(normalLat)
247  * cos(normalLon - poleLongitude) -
248  cos(poleLatitude) * sin(normalLat)) - poleRotation;
249 
250  while(obliqueLon < - PI) {
251  obliqueLon += (2.0 * PI);
252  }
253 
254  while(obliqueLon >= PI) {
255  obliqueLon -= (2.0 * PI);
256  }
257 
258  // Compute the coordinate
259  double x = m_equatorialRadius * obliqueLon;
260  double y = m_equatorialRadius * obliqueLat;
261  SetComputedXY(x, y);
262 
263  m_good = true;
264  return m_good;
265  }
266 
280  bool ObliqueCylindrical::SetCoordinate(const double x, const double y) {
281  // Save the coordinate
282  SetXY(x, y);
283 
284  /***************************************************************************
285  * Calculate the oblique latitude and check to see if it is outside or equal
286  * to [-90,90]. If it is, return with an error.
287  ***************************************************************************/
289 
290  if (abs(abs(m_latitude) - HALFPI) < DBL_EPSILON) {
291  m_good = false;
292  return m_good;
293  }
294 
295  /***************************************************************************
296  * The check to see if m_equatorialRadius == 0 is done in the init function
297  ***************************************************************************/
299 
300  /***************************************************************************
301  * Convert the oblique lat/lon to normal lat/lon
302  ***************************************************************************/
303  double obliqueLat, obliqueLon;
304  double poleLatitude = (m_poleLatitude * PI / 180.0);
305  double poleLongitude = (m_poleLongitude * PI / 180.0);
306  double poleRotation = (m_poleRotation * PI / 180.0);
307 
308  obliqueLat = asin(sin(poleLatitude) * sin(m_latitude) -
309  cos(poleLatitude) * cos(m_latitude) * cos(m_longitude + poleRotation));
310 
311  obliqueLon = atan2(cos(m_latitude) * sin(m_longitude + poleRotation),
312  sin(poleLatitude) * cos(m_latitude) * cos(m_longitude + poleRotation) +
313  cos(poleLatitude) * sin(m_latitude)) + poleLongitude;
314 
315  /***************************************************************************
316  * Convert the latitude/longitude to degrees and apply target longitude
317  * direction correction to the longitude
318  ***************************************************************************/
319  m_latitude = obliqueLat * 180.0 / PI;
320  m_longitude = obliqueLon * 180.0 / PI;
321 
322  // Cleanup the longitude
324 
325  m_good = true;
326  return m_good;
327  }
328 
358  bool ObliqueCylindrical::XYRange(double &minX, double &maxX,
359  double &minY, double &maxY) {
360  return xyRangeOblique(minX, maxX, minY, maxY);
361  }
362 
363 
370  PvlGroup mapping = TProjection::Mapping();
371 
372  mapping += m_mappingGrp["PoleLatitude"];
373  mapping += m_mappingGrp["PoleLongitude"];
374  mapping += m_mappingGrp["PoleRotation"];
375 
376  return mapping;
377  }
378 
386 
387  return mapping;
388  }
389 
397 
398  return mapping;
399  }
400 
408  return m_poleLatitude;
409  }
410 
418  return m_poleLongitude;
419  }
420 
428  return m_poleRotation;
429  }
430 
431  void ObliqueCylindrical::init() {
432  /***************************************************************************
433  * Apply target correction for longitude direction
434  ***************************************************************************/
437 
438  /***************************************************************************
439  * Check that m_equatorialRadius isn't zero because we'll divide by it later
440  ***************************************************************************/
441  if (abs(m_equatorialRadius) <= DBL_EPSILON) {
443  "The input center latitude is too close to a pole "
444  "which will result in a division by zero.",
445  _FILEINFO_);
446  }
447  }
448 
449 } // end namespace isis
450 
463  bool allowDefaults) {
464  return new Isis::ObliqueCylindrical(lab, allowDefaults);
465 }