USGS

Isis 3.0 Object Programmers' Reference

Home

RingCylindrical.cpp
Go to the documentation of this file.
1 
23 #include "RingCylindrical.h"
24 
25 #include <cmath>
26 #include <cfloat>
27 
28 #include "Constants.h"
29 #include "IException.h"
30 #include "Pvl.h"
31 #include "PvlGroup.h"
32 #include "PvlKeyword.h"
33 #include "RingPlaneProjection.h"
34 #include "SpecialPixel.h"
35 
36 using namespace std;
37 namespace Isis {
38 
55  RingCylindrical::RingCylindrical(Pvl &label, bool allowDefaults) :
57  try {
58  // Try to read the mapping group
59  PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);
60 
61  // Compute the default value if allowed and needed
62  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterRingLongitude"))) {
63  double az = (m_minimumRingLongitude + m_maximumRingLongitude) / 2.0;
64  mapGroup += PvlKeyword("CenterRingLongitude", toString(az));
65  }
66 
67  // Compute and write the default center radius if allowed and
68  // necessary
69  if ((allowDefaults) && (!mapGroup.hasKeyword("CenterRingRadius"))) {
70  double radius = (m_minimumRingRadius + m_maximumRingRadius) / 2.0;
71  mapGroup += PvlKeyword("CenterRingRadius", toString(radius));
72  }
73 
74  // Get the center ring radius and center ring longitude.
75  m_centerRingLongitude = mapGroup["CenterRingLongitude"];
76  m_centerRingRadius = mapGroup["CenterRingRadius"];
77 
78  // Because the center radius is used to scale the y values of the projection, it cannot be 0.
79  // For now, we will reset the center to the radius of Saturn.
80  // Perhaps we should fail and issue an error message??? TODO
81  if (m_centerRingRadius == 0.0) {
82  m_centerRingRadius = 18000.;
83  }
84 
85  // Convert to radians, adjust for azimuth direction
88  }
89  catch (IException &e) {
90  string message = "Invalid label group [Mapping]";
91  throw IException(e, IException::Io, message, _FILEINFO_);
92  }
93  }
94 
97  }
98 
108  if (!Projection::operator==(proj)) return false;
109  // dont do the below it is a recusive plunge
110  // if (Projection::operator!=(proj)) return false;
111  RingCylindrical *ringCyl = (RingCylindrical *) &proj;
112  if ((ringCyl->m_centerRingLongitude != m_centerRingLongitude) ||
113  (ringCyl->m_centerRingRadius != m_centerRingRadius)) return false;
114  return true;
115  }
116 
122  QString RingCylindrical::Name() const {
123  return "RingCylindrical";
124  }
125 
131  QString RingCylindrical::Version() const {
132  return "1.0";
133  }
134 
135 
147  return true;
148  }
149 
150 
165  return m_centerRingRadius;
166  }
167 
168 
175  double dir = 1.0;
176  if (m_ringLongitudeDirection == Clockwise) dir = -1.0;
177  return m_centerRingLongitude * RAD2DEG * dir;
178  }
179 
180 
187  return m_centerRingRadius;
188  }
189 
190 
204  bool RingCylindrical::SetGround(const double ringRadius, const double ringLongitude) {
205  //TODO Add scalar to make azimuth distance equivalent to radius distance at center rad
206  // Convert to azimuth to radians and adjust
207  m_ringLongitude = ringLongitude;
208  double ringLongitudeRadians = ringLongitude * DEG2RAD;
209  if (m_ringLongitudeDirection == Clockwise) ringLongitudeRadians *= -1.0;
210 
211  // Check to make sure radius is valid
212  if (ringRadius <= 0) {
213  m_good = false;
214  // cout << "Unable to set radius. The given radius value ["
215  // << IString(ringRadius) << "] is invalid." << endl;
216  // throw IException(IException::Unknown,
217  // "Unable to set radius. The given radius value ["
218  // + IString(ringRadius) + "] is invalid.",
219  // _FILEINFO_);
220  return m_good;
221  }
222  m_ringRadius = ringRadius;
223 
224  // Compute helper variable
225  double deltaAz = (ringLongitudeRadians - m_centerRingLongitude);
226 
227  // Compute the coordinates
228  if (ringRadius ==0) {
229  // TODO How should we handle this case? We should use epsilon probably instead of 0 too
230  m_good = false;
231  return m_good;
232  }
233  double x = deltaAz * m_centerRingRadius;
234  double y = m_centerRingRadius - ringRadius;
235  SetComputedXY(x, y);
236  m_good = true;
237  return m_good;
238  }
239 
255  bool RingCylindrical::SetCoordinate(const double x, const double y) {
256  // Save the coordinate
257  SetXY(x, y);
258 
259  // Compute radius and make sure it is valid
260  // m_ringRadius = GetY() + m_centerRingRadius;
262  if (m_ringRadius < m_minimumRingRadius || m_ringRadius > m_maximumRingRadius) {
263  m_good = false;
264  return m_good;
265  }
266 
267  // Compute azimuth
269 
270  // Convert to degrees
272 
273  // Cleanup the azimuth
275  // Do these if the projection is circular
276  // m_ringLongitude = To360Domain (m_ringLongitude);
277  // if (m_ringLongitudeDomain == 180) m_ringLongitude = To180Domain(m_ringLongitude);
278 
279  m_good = true;
280  return m_good;
281  }
282 
320  bool RingCylindrical::XYRange(double &minX, double &maxX,
321  double &minY, double &maxY) {
322 
323  double rad, az;
324 
325  // Check the corners of the rad/az range
330 
331 // cout << " ************ WALK RADIUS ******************\n";
332 // cout << "MIN RAD: " << m_minimumRingRadius << " MAX RAD: " << m_maximumRingRadius << "\n";
333  // Walk top and bottom edges in half pixel increments
334  double radiusInc = 2. * (m_maximumRingRadius - m_minimumRingRadius) / PixelResolution();
335 
336  for (rad = m_minimumRingRadius; rad <= m_maximumRingRadius; rad += radiusInc) {
337 // cout << "WALKED A STEP - rad: " << rad << "\n";
338  rad = rad;
340  XYRangeCheck(rad, az);
341 
342  rad = rad;
344  XYRangeCheck(rad, az);
345 // cout << "MIN RAD: " << m_minimumRingRadius << " MAX RAD: " << m_maximumRingRadius << "\n";
346  }
347 
348 //cout << " ************ WALK AZIMUTH ******************\n";
349  // Walk left and right edges
350  for (az = m_minimumRingLongitude; az <= m_maximumRingLongitude; az += 0.01) {
351  rad = m_minimumRingRadius;
352  az = az;
353  XYRangeCheck(rad, az);
354 
355  rad = m_maximumRingRadius;
356  az = az;
357  XYRangeCheck(rad, az);
358  }
359 
360  // Walk the limb
361 /*
362  for (double angle = 0.0; angle <= 360.0; angle += 0.01) {
363  double x = m_equatorialRingRadius * cos(angle * PI / 180.0);
364  double y = m_equatorialRingRadius * sin(angle * PI / 180.0);
365  if (SetCoordinate(x, y) == 0) {
366  if (m_latitude > m_maximumLatitude) {
367  continue;
368  }
369  if (m_longitude > m_maximumRingLongitude) {
370  continue;
371  }
372  if (m_latitude < m_minimumLatitude) {
373  continue;
374  }
375  if (m_longitude < m_minimumRingLongitude) {
376  continue;
377  }
378 
379  if (m_minimumX > x) m_minimumX = x;
380  if (m_maximumX < x) m_maximumX = x;
381  if (m_minimumY > y) m_minimumY = y;
382  if (m_maximumY < y) m_maximumY = y;
383  XYRangeCheck(m_latitude, m_longitude);
384  }
385  } */
386 
387  // Make sure everything is ordered
388  if (m_minimumX >= m_maximumX) return false;
389  if (m_minimumY >= m_maximumY) return false;
390 
391  // Return X/Y min/maxs
392  // m_maximumX = m_maximumRingRadius*cos(m_maximumRingLongitude);
393  // m_minimumX = -m_maximumX;
394  // m_maximumY = m_maximumRingRadius*sin(m_maximumRingLongitude);
395  // m_minimumY = -m_maximumY;
396 
397  minX = m_minimumX;
398  maxX = m_maximumX;
399  minY = m_minimumY;
400  maxY = m_maximumY;
401 
402  return true;
403  }
404 
405 
414 
415  mapping += PvlKeyword("CenterRingRadius", toString(m_centerRingRadius));
416  double dir = 1.0;
417  if (m_ringLongitudeDirection == Clockwise) dir = -1.0;
418  double lonDegrees = m_centerRingLongitude*RAD2DEG*dir;
419  mapping += PvlKeyword("CenterRingLongitude", toString(lonDegrees));
420 
421  return mapping;
422  }
423 
432 
433  if (HasGroundRange())
434  mapping += m_mappingGrp["CenterRingRadius"];
435 
436  return mapping;
437  }
438 
439 
448 
449  if (HasGroundRange())
450  mapping += m_mappingGrp["CenterRingLongitude"];
451 
452  return mapping;
453  }
454 
455 } // end namespace isis
456 
470  bool allowDefaults) {
471  return new Isis::RingCylindrical(lab, allowDefaults);
472 }