Isis 3 Programmer Reference
RingPlaneProjection.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "RingPlaneProjection.h"
8 
9 #include <QObject>
10 
11 #include <cfloat>
12 #include <cmath>
13 #include <iomanip>
14 #include <sstream>
15 #include <vector>
16 
17 #include <SpiceUsr.h>
18 
19 #include "Constants.h"
20 #include "Displacement.h"
21 #include "FileName.h"
22 #include "IException.h"
23 #include "IString.h"
24 #include "Longitude.h"
25 #include "NaifStatus.h"
26 #include "Pvl.h"
27 #include "PvlGroup.h"
28 #include "PvlKeyword.h"
29 #include "SpecialPixel.h"
30 #include "WorldMapper.h"
31 
32 using namespace std;
33 namespace Isis {
69  RingPlaneProjection::RingPlaneProjection(Pvl &label) : Projection::Projection(label) {
70  try {
71  // Mapping group is read by the parent (Projection)
72  // Get the RingLongitude Direction
73  if ((QString) m_mappingGrp["RingLongitudeDirection"] == "Clockwise") {
75  }
76  else if ((QString) m_mappingGrp["RingLongitudeDirection"] == "CounterClockwise") {
78  }
79  else {
80  QString msg = "Projection failed. Invalid value for keyword "
81  "[RingLongitudeDirection] must be "
82  "[Clockwise or CounterClockwise]";
83  throw IException(IException::Unknown, msg, _FILEINFO_);
84  }
85 
86  // Get the RingLongitudeDomain
87  if ((QString) m_mappingGrp["RingLongitudeDomain"] == "360") {
89  }
90  else if ((QString) m_mappingGrp["RingLongitudeDomain"] == "180") {
92  }
93  else {
94  QString msg = "Projection failed. Invalid value for keyword "
95  "[RingLongitudeDomain] must be [180 or 360]";
96  throw IException(IException::Unknown, msg, _FILEINFO_);
97  }
98 
99  // Get the ground range if it exists
100  m_groundRangeGood = false;
101 
102  if ((m_mappingGrp.hasKeyword("MinimumRingLongitude")) &&
103  (m_mappingGrp.hasKeyword("MaximumRingLongitude")) &&
104  (m_mappingGrp.hasKeyword("MaximumRingRadius")) &&
105  (m_mappingGrp.hasKeyword("MinimumRingRadius"))) {
106  m_minimumRingLongitude = m_mappingGrp["MinimumRingLongitude"];
107  m_maximumRingLongitude = m_mappingGrp["MaximumRingLongitude"];
108  m_minimumRingRadius = m_mappingGrp["MinimumRingRadius"];
109  m_maximumRingRadius = m_mappingGrp["MaximumRingRadius"];
110 
111  if (m_minimumRingRadius < 0) {
112  IString msg = "Projection failed. "
113  "[MinimumRingRadius] of ["+ IString(m_minimumRingRadius) + "] is not "
114  + "valid";
115  throw IException(IException::Unknown, msg, _FILEINFO_);
116  }
117 
118  if (m_maximumRingRadius < 0) {
119  IString msg = "Projection failed. "
120  "[MaximumRingRadius] of ["+ IString(m_maximumRingRadius) + "] is not "
121  + "valid";
122  throw IException(IException::Unknown, msg, _FILEINFO_);
123  }
124 
126  IString msg = "Projection failed. "
127  "[MinimumRingRadius,MaximumRingRadius] of ["
129  + IString(m_maximumRingRadius) + "] are not "
130  + "properly ordered";
131  throw IException(IException::Unknown, msg, _FILEINFO_);
132  }
133 
135  IString msg = "Projection failed. "
136  "[MinimumRingLongitude,MaximumRingLongitude] of ["
138  + IString(m_maximumRingLongitude) + "] are not "
139  + "properly ordered";
140  throw IException(IException::Unknown, msg, _FILEINFO_);
141  }
142 
143  m_groundRangeGood = true;
144  }
145  else {
146  // if no ground range is given, initialize the min/max ring rad/lon to 0
147  m_minimumRingRadius = 0.0;
148  m_maximumRingRadius = 0.0;
151  }
152 
153  // Initialize miscellaneous protected data elements
154  // initialize the rest of the x,y,ring rad,ring lon
155  // member variables
156  m_ringRadius = Null;
158 
159  // If we made it to this point, we have what we need for a ring plane projection
161  }
162  catch(IException &e) {
163  IString msg = "Projection failed. Invalid label group [Mapping]";
164  throw IException(e, IException::Unknown, msg, _FILEINFO_);
165  }
166  }
167 
170  }
171 
182  if (!Projection::operator==(proj)) return false;
183  RingPlaneProjection *rproj = (RingPlaneProjection *) &proj;
184  if (IsClockwise() != rproj->IsClockwise()) return false;
185  if (Has180Domain() != rproj->Has180Domain()) return false;
186  return true;
187  }
188 
189 
200  return 0.0;
201  }
202 
203 
213  }
214 
224  }
225 
240  double RingPlaneProjection::ToClockwise(const double ringLongitude, const int domain) {
241  if (ringLongitude == Null) {
243  "Unable to convert to Clockwise. The given ring longitude value ["
244  + Isis::toString(ringLongitude) + "] is invalid.",
245  _FILEINFO_);
246  }
247  double myRingLongitude = ringLongitude;
248 
249  myRingLongitude *= -1;
250 
251  if (domain == 360) {
252  myRingLongitude = To360Domain(myRingLongitude);
253  }
254  else if (domain == 180) {
255  myRingLongitude = To180Domain(myRingLongitude);
256  }
257  else {
258  IString msg = "Unable to convert ring longitude. Domain [" + Isis::toString(domain)
259  + "] is not 180 or 360.";
260  throw IException(IException::Unknown, msg, _FILEINFO_);
261  }
262 
263  return myRingLongitude;
264  }
265 
280  double RingPlaneProjection::ToCounterClockwise(const double ringLongitude, const int domain) {
281  if (ringLongitude == Null) {
283  "Unable to convert to CounterClockwise. The given ring longitude value ["
284  + IString(ringLongitude) + "] is invalid.",
285  _FILEINFO_);
286  }
287  double myRingLongitude = ringLongitude;
288 
289  myRingLongitude *= -1;
290 
291  if (domain == 360) {
292  myRingLongitude = To360Domain(myRingLongitude);
293  }
294  else if (domain == 180) {
295  myRingLongitude = To180Domain(myRingLongitude);
296  }
297  else {
298  IString msg = "Unable to convert ring longitude. Domain [" + IString(domain)
299  + "] is not 180 or 360.";
300  throw IException(IException::Unknown, msg, _FILEINFO_);
301  }
302 
303  return myRingLongitude;
304  }
305 
306 
315  if (m_ringLongitudeDirection == Clockwise) return "Clockwise";
316  return "CounterClockwise";
317  }
318 
327  return m_ringLongitudeDomain == 180;
328  }
329 
338  return m_ringLongitudeDomain == 360;
339  }
340 
352  double RingPlaneProjection::To180Domain(const double ringLongitude) {
353  if (ringLongitude == Null) {
355  "Unable to convert to 180 degree domain. The given ring longitude value ["
356  + IString(ringLongitude) + "] is invalid.",
357  _FILEINFO_);
358  }
359  return Isis::Longitude(ringLongitude, Angle::Degrees).force180Domain().degrees();
360  }
361 
370  double RingPlaneProjection::To360Domain(const double ringLongitude) {
371  if (ringLongitude == Null) {
373  "Unable to convert to 360 degree domain. The given ring longitude value ["
374  + IString(ringLongitude) + "] is invalid.",
375  _FILEINFO_);
376  }
377  double result = ringLongitude;
378 
379  if ( (ringLongitude < 0.0 || ringLongitude > 360.0) &&
380  !qFuzzyCompare(ringLongitude, 0.0) && !qFuzzyCompare(ringLongitude, 360.0)) {
381  result = Isis::Longitude(ringLongitude, Angle::Degrees).force360Domain().degrees();
382  }
383 
384  return result;
385  }
386 
394  if (m_ringLongitudeDomain == 360) return "360";
395  return "180";
396  }
397 
406  return m_minimumRingRadius;
407  }
408 
417  return m_maximumRingRadius;
418  }
419 
428  return m_minimumRingLongitude;
429  }
430 
439  return m_maximumRingLongitude;
440  }
441 
456  bool RingPlaneProjection::SetGround(const double ringRadius, const double ringLongitude) {
457  if (ringRadius == Null || ringLongitude == Null) {
458  m_good = false;
459  return m_good;
460  }
461  else {
462  m_ringRadius = ringRadius;
463  m_ringLongitude = ringLongitude;
464  m_good = true;
465  SetComputedXY(ringLongitude, ringRadius);
466  }
467  return m_good;
468  }
469 
485  bool RingPlaneProjection::SetCoordinate(const double x, const double y) {
486  if (x == Null || y == Null) {
487  m_good = false;
488  }
489  else {
490  m_good = true;
491  SetXY(x, y);
492  m_ringRadius = XCoord();
494  }
495  return m_good;
496  }
497 
498 
507  return m_ringRadius;
508  }
509 
510 
519  return m_ringRadius;
520  }
521 
531  return m_ringLongitude;
532  }
533 
546  bool RingPlaneProjection::SetUniversalGround(const double ringRadius, const double ringLongitude) {
547  if (ringRadius == Null || ringLongitude == Null) {
548  m_good = false;
549  return m_good;
550  }
551  // Deal with the ring longitude first
552  m_ringLongitude = ringLongitude;
553  if (m_ringLongitudeDirection == Clockwise) m_ringLongitude = -ringLongitude;
554  if (m_ringLongitudeDomain == 180) {
556  }
557  else {
558  // Do this because RingLongitudeDirection could cause (-360,0)
560  }
561 
562  // Nothing to do with radius
563 
564  m_ringRadius = ringRadius;
565 
566  // Now the rad/ring longitude are in user defined coordinates so set them
568  }
569 
576  double ringRadius = m_ringRadius;
577  return ringRadius;
578  }
579 
580 
590  double ringLongitude = m_ringLongitude;
591  if (m_ringLongitudeDirection == Clockwise) ringLongitude = -ringLongitude;
592  ringLongitude = To360Domain(ringLongitude);
593  return ringLongitude;
594  }
595 
596 
607  double RingPlaneProjection::Scale() const {
608  if (m_mapper != NULL) {
609  double localRadius = TrueScaleRingRadius();
610  return localRadius / m_mapper->Resolution() * DEG2RAD;
611  // return localRadius / m_mapper->Resolution();
612  }
613  else {
614  return 1.0;
615  }
616  }
617 
618 
656  bool RingPlaneProjection::XYRange(double &minX, double &maxX,
657  double &minY, double &maxY) {
658  if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
659  return false;
660  }
661  if (m_groundRangeGood) {
662  minX = m_minimumRingLongitude;
663  maxX = m_maximumRingLongitude;
664  minY = m_minimumRingRadius;
665  maxY = m_maximumRingRadius;
666  return true;
667  }
668  return false;
669  }
670 
709  void RingPlaneProjection::XYRangeCheck(const double ringRadius, const double ringLongitude) {
710  if (ringRadius == Null || ringLongitude == Null) {
711  m_good = false;
712  return;
713  }
714  SetGround(ringRadius, ringLongitude);
715  if (!IsGood()) return;
716 
717  if (XCoord() < m_minimumX) m_minimumX = XCoord();
718  if (XCoord() > m_maximumX) m_maximumX = XCoord();
719  if (YCoord() < m_minimumY) m_minimumY = YCoord();
720  if (YCoord() > m_maximumY) m_maximumY = YCoord();
721  return;
722  }
723 
745  // bool Projection::xyRangeOblique(double &minX, double &maxX,
746  // double &minY, double &maxY) {
747  // if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
748  // return false;
749  // }
750  // //For oblique, we'll have to walk all 4 sides to find out min/max x/y values
751  // if (!HasGroundRange()) return false; // Don't have min/max ring rad/lon,
752  // //can't continue
753 
754  // m_specialLatCases.clear();
755  // m_specialLonCases.clear();
756 
757  // // First, search ring longitude for
758  // min X/Y double minFoundX1, minFoundX2;
759  // double minFoundY1, minFoundY2;
760 
761  // // Search for minX between minlat and maxlat along minlon
762  // doSearch(MinimumLatitude(), MaximumLatitude(),
763  // minFoundX1, MinimumLongitude(), true, true, true);
764  // // Search for minX between minlat and maxlat along maxlon
765  // doSearch(MinimumLatitude(), MaximumLatitude(),
766  // minFoundX2, MaximumLongitude(), true, true, true);
767  // // Search for minY between minlat and maxlat along minlon
768  // doSearch(MinimumLatitude(), MaximumLatitude(),
769  // minFoundY1, MinimumLongitude(), false, true, true);
770  // // Search for minY between minlat and maxlat along maxlon
771  // doSearch(MinimumLatitude(), MaximumLatitude(),
772  // minFoundY2, MaximumLongitude(), false, true, true);
773 
774  // // Second, search latitude for min X/Y
775  // double minFoundX3, minFoundX4;
776  // double minFoundY3, minFoundY4;
777 
778  // // Search for minX between minlon and maxlon along minlat
779  // doSearch(MinimumLongitude(), MaximumLongitude(),
780  // minFoundX3, MinimumLatitude(), true, false, true);
781  // // Search for minX between minlon and maxlon along maxlat
782  // doSearch(MinimumLongitude(), MaximumLongitude(),
783  // minFoundX4, MaximumLatitude(), true, false, true);
784  // // Search for minY between minlon and maxlon along minlat
785  // doSearch(MinimumLongitude(), MaximumLongitude(),
786  // minFoundY3, MinimumLatitude(), false, false, true);
787  // // Search for minY between minlon and maxlon along maxlat
788  // doSearch(MinimumLongitude(), MaximumLongitude(),
789  // minFoundY4, MaximumLatitude(), false, false, true);
790 
791  // // We've searched all possible minimums, go ahead and store the lowest
792  // double minFoundX5 = min(minFoundX1, minFoundX2);
793  // double minFoundX6 = min(minFoundX3, minFoundX4);
794  // m_minimumX = min(minFoundX5, minFoundX6);
795 
796  // double minFoundY5 = min(minFoundY1, minFoundY2);
797  // double minFoundY6 = min(minFoundY3, minFoundY4);
798  // m_minimumY = min(minFoundY5, minFoundY6);
799 
800  // // Search ring longitude for
801  // max X/Y double maxFoundX1,
802  // maxFoundX2; double maxFoundY1,
803  // maxFoundY2;
804 
805  // // Search for maxX between minlat and maxlat along minlon
806  // doSearch(MinimumLatitude(), MaximumLatitude(),
807  // maxFoundX1, MinimumLongitude(), true, true, false);
808  // // Search for maxX between minlat and maxlat along maxlon
809  // doSearch(MinimumLatitude(), MaximumLatitude(),
810  // maxFoundX2, MaximumLongitude(), true, true, false);
811  // // Search for maxY between minlat and maxlat along minlon
812  // doSearch(MinimumLatitude(), MaximumLatitude(),
813  // maxFoundY1, MinimumLongitude(), false, true, false);
814  // // Search for maxY between minlat and maxlat along maxlon
815  // doSearch(MinimumLatitude(), MaximumLatitude(),
816  // maxFoundY2, MaximumLongitude(), false, true, false);
817 
818  // // Search latitude for max X/Y
819  // double maxFoundX3, maxFoundX4;
820  // double maxFoundY3, maxFoundY4;
821 
822  // // Search for maxX between minlon and maxlon along minlat
823  // doSearch(MinimumLongitude(), MaximumLongitude(),
824  // maxFoundX3, MinimumLatitude(), true, false, false);
825  // // Search for maxX between minlon and maxlon along maxlat
826  // doSearch(MinimumLongitude(), MaximumLongitude(),
827  // maxFoundX4, MaximumLatitude(), true, false, false);
828  // // Search for maxY between minlon and maxlon along minlat
829  // doSearch(MinimumLongitude(), MaximumLongitude(),
830  // maxFoundY3, MinimumLatitude(), false, false, false);
831  // // Search for maxY between minlon and maxlon along maxlat
832  // doSearch(MinimumLongitude(), MaximumLongitude(),
833  // maxFoundY4, MaximumLatitude(), false, false, false);
834 
835  // // We've searched all possible maximums, go ahead and store the highest
836  // double maxFoundX5 = max(maxFoundX1, maxFoundX2);
837  // double maxFoundX6 = max(maxFoundX3, maxFoundX4);
838  // m_maximumX = max(maxFoundX5, maxFoundX6);
839 
840  // double maxFoundY5 = max(maxFoundY1, maxFoundY2);
841  // double maxFoundY6 = max(maxFoundY3, maxFoundY4);
842  // m_maximumY = max(maxFoundY5, maxFoundY6);
843 
844  // // Look along discontinuities for more extremes
845  // vector<double> specialLatCases = m_specialLatCases;
846  // for (unsigned int specialLatCase = 0;
847  // specialLatCase < specialLatCases.size();
848  // specialLatCase ++) {
849  // double minX, maxX, minY, maxY;
850 
851  // // Search for minX between minlon and maxlon along latitude discontinuities
852  // doSearch(MinimumLongitude(), MaximumLongitude(),
853  // minX, specialLatCases[specialLatCase], true, false, true);
854  // // Search for minY between minlon and maxlon along latitude discontinuities
855  // doSearch(MinimumLongitude(), MaximumLongitude(),
856  // minY, specialLatCases[specialLatCase], false, false, true);
857  // // Search for maxX between minlon and maxlon along latitude discontinuities
858  // doSearch(MinimumLongitude(), MaximumLongitude(),
859  // maxX, specialLatCases[specialLatCase], true, false, false);
860  // // Search for maxX between minlon and maxlon along latitude discontinuities
861  // doSearch(MinimumLongitude(), MaximumLongitude(),
862  // maxY, specialLatCases[specialLatCase], false, false, false);
863 
864  // m_minimumX = min(minX, m_minimumX);
865  // m_maximumX = max(maxX, m_maximumX);
866  // m_minimumY = min(minY, m_minimumY);
867  // m_maximumY = max(maxY, m_maximumY);
868  // }
869 
870  // vector<double> specialLonCases = m_specialLonCases;
871  // for (unsigned int specialLonCase = 0;
872  // specialLonCase < specialLonCases.size();
873  // specialLonCase ++) {
874  // double minX, maxX, minY, maxY;
875 
876  // // Search for minX between minlat and maxlat along longitude discontinuities
877  // doSearch(MinimumLatitude(), MaximumLatitude(),
878  // minX, specialLonCases[specialLonCase], true, true, true);
879  // // Search for minY between minlat and maxlat along longitude discontinuities
880  // doSearch(MinimumLatitude(), MaximumLatitude(),
881  // minY, specialLonCases[specialLonCase], false, true, true);
882  // // Search for maxX between minlat and maxlat along longitude discontinuities
883  // doSearch(MinimumLatitude(), MaximumLatitude(),
884  // maxX, specialLonCases[specialLonCase], true, true, false);
885  // // Search for maxY between minlat and maxlat along longitude discontinuities
886  // doSearch(MinimumLatitude(), MaximumLatitude(),
887  // maxY, specialLonCases[specialLonCase], false, true, false);
888 
889  // m_minimumX = min(minX, m_minimumX);
890  // m_maximumX = max(maxX, m_maximumX);
891  // m_minimumY = min(minY, m_minimumY);
892  // m_maximumY = max(maxY, m_maximumY);
893  // }
894 
895  // m_specialLatCases.clear();
896  // m_specialLonCases.clear();
897 
898  // // Make sure everything is ordered
899  // if (m_minimumX >= m_maximumX) return false;
900  // if (m_minimumY >= m_maximumY) return false;
901 
902  // // Return X/Y min/maxs
903  // minX = m_minimumX;
904  // maxX = m_maximumX;
905  // minY = m_minimumY;
906  // maxY = m_maximumY;
907 
908  // return true;
909  // }
910 
948  // void Projection::doSearch(double minBorder, double maxBorder,
949  // double &extremeVal, const double constBorder,
950  // bool searchX, bool searchRingLongitude, bool findMin) {
951  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
952  // return;
953  // }
954  // const double TOLERANCE = m_pixelResolution/2;
955  // const int NUM_ATTEMPTS = (unsigned int)DBL_DIG; // It's unsafe to go past
956  // // this precision
957 
958  // double minBorderX, minBorderY, maxBorderX, maxBorderY;
959  // int attempts = 0;
960 
961  // do {
962  // findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
963  // maxBorderY, constBorder, searchX, searchLongitude, findMin);
964  // if (minBorderX == Null && maxBorderX == Null
965  // && minBorderY == Null && maxBorderY == Null ) {
966  // attempts = NUM_ATTEMPTS;
967  // continue;
968  // }
969  // attempts ++;
970  // }
971  // while ((fabs(minBorderX - maxBorderX) > TOLERANCE
972  // || fabs(minBorderY - maxBorderY) > TOLERANCE)
973  // && (attempts < NUM_ATTEMPTS));
974  // // check both x and y distance in case symmetry of map
975  // // For example, if minBorderX = maxBorderX but minBorderY = -maxBorderY,
976  // // these points may not be close enough.
977 
978  // if (attempts >= NUM_ATTEMPTS) {
979  // // We zoomed in on a discontinuity because our range never shrank, this
980  // // will need to be rechecked later.
981  // // *min and max border should be nearly identical, so it doesn't matter
982  // // which is used here
983  // if (searchLongitude) {
984  // m_specialLatCases.push_back(minBorder);
985  // }
986  // else {
987  // m_specialLonCases.push_back(minBorder);
988  // }
989  // }
990 
991  // // These values will always be accurate, even over a discontinuity
992  // if (findMin) {
993  // if (searchX) extremeVal = min(minBorderX, maxBorderX);
994  // else extremeVal = min(minBorderY, maxBorderY);
995  // }
996  // else {
997  // if (searchX) extremeVal = max(minBorderX, maxBorderX);
998  // else extremeVal = max(minBorderY, maxBorderY);
999  // }
1000  // return;
1001  // }
1002 
1062  // void Projection::findExtreme(double &minBorder, double &maxBorder,
1063  // double &minBorderX, double &minBorderY,
1064  // double &maxBorderX, double &maxBorderY,
1065  // const double constBorder, bool searchX,
1066  // bool searchRingLongitude, bool findMin) {
1067  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1068  // minBorderX = Null;
1069  // minBorderY = minBorderX;
1070  // minBorderX = minBorderX;
1071  // minBorderY = minBorderX;
1072  // return;
1073  // }
1074  // if (!searchRingLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1075  // // it is impossible to search "along" a pole
1076  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1077  // minBorderX = XCoord();
1078  // minBorderY = YCoord();
1079  // maxBorderX = minBorderX;
1080  // maxBorderY = minBorderY;
1081  // return;
1082  // }
1083  // // Always do 10 steps
1084  // const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1085  // const double LOOP_END = maxBorder + (STEP_SIZE / 2.0); // This ensures we do
1086  // // all of the steps
1087  // // properly
1088  // double currBorderVal = minBorder;
1089  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1090 
1091  // // this makes sure that the initial currBorderVal is valid before entering
1092  // // the loop below
1093  // if (!m_good){
1094  // // minBorder = currBorderVal+STEP_SIZE < LOOP_END until setGround is good?
1095  // // then, if still not good return?
1096  // while (!m_good && currBorderVal <= LOOP_END) {
1097  // currBorderVal+=STEP_SIZE;
1098  // if (searchRingLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1099  // currBorderVal = 90.0;
1100  // }
1101  // setSearchGround(currBorderVal, constBorder, searchRingLongitude);
1102  // }
1103  // if (!m_good) {
1104  // minBorderX = Null;
1105  // minBorderY = minBorderX;
1106  // minBorderX = minBorderX;
1107  // minBorderY = minBorderX;
1108  // return;
1109  // }
1110  // }
1111 
1112  // // save the values of three consecutive steps from the minBorder towards
1113  // // the maxBorder along the constBorder. initialize these three border
1114  // // values (the non-constant lat or lon)
1115  // double border1 = currBorderVal;
1116  // double border2 = currBorderVal;
1117  // double border3 = currBorderVal;
1118 
1119  // // save the coordinate (x or y) values that correspond to the first
1120  // // two borders that are being saved.
1121  // // initialize these two coordinate values (x or y)
1122  // double value1 = (searchX) ? XCoord() : YCoord();
1123  // double value2 = value1;
1124 
1125  // // initialize the extreme coordinate value
1126  // // -- this is the largest coordinate value found so far
1127  // double extremeVal2 = value2;
1128 
1129  // // initialize the extreme border values
1130  // // -- these are the borders on either side of the extreme coordinate value
1131  // double extremeBorder1 = minBorder;
1132  // double extremeBorder3 = minBorder;
1133 
1134  // while (currBorderVal <= LOOP_END) {
1135 
1136  // // this conditional was added to prevent trying to SetGround with an
1137  // // invalid latitude greater than 90 degrees. There is no need check for
1138  // // latitude less than -90 since we start at the minBorder (already
1139  // // assumed to be valid) and step forward toward (and possibly past)
1140  // // maxBorder
1141  // if (searchRingLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1142  // currBorderVal = 90.0;
1143  // }
1144 
1145  // // update the current border value along constBorder
1146  // currBorderVal += STEP_SIZE;
1147  // setSearchGround(currBorderVal, constBorder, searchRingLongitude);
1148  // if (!m_good){
1149  // continue;
1150  // }
1151 
1152  // // update the border and coordinate values
1153  // border3 = border2;
1154  // border2 = border1;
1155  // border1 = currBorderVal;
1156  // value2 = value1;
1157  // value1 = (searchX) ? XCoord() : YCoord();
1158 
1159  // if ((findMin && value2 < extremeVal2)
1160  // || (!findMin && value2 > extremeVal2)) {
1161  // // Compare the coordinate value associated with the center border with
1162  // // the current extreme. If the updated coordinate value is more extreme
1163  // // (smaller or larger, depending on findMin), then we update the
1164  // // extremeVal and it's borders.
1165  // extremeVal2 = value2;
1166 
1167  // extremeBorder3 = border3;
1168  // extremeBorder1 = border1;
1169  // }
1170  // }
1171 
1172  // // update min/max border values to the values on either side of the most
1173  // // extreme coordinate found in this call to this method
1174 
1175  // minBorder = extremeBorder3; // Border 3 is lagging and thus smaller
1176 
1177  // // since the loop steps past the original maxBorder, we want to retain
1178  // // the original maxBorder value so we don't go outside of the original
1179  // // min/max range given
1180  // if (extremeBorder1 <= maxBorder ) {
1181  // maxBorder = extremeBorder1; // Border 1 is leading and thus larger
1182  // }
1183 
1184  // // update minBorder coordinate values
1185  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1186  // // if (!m_good){
1187  // // this should not happen since minBorder has already been verified in
1188  // // the while loop above
1189  // // }
1190 
1191  // minBorderX = XCoord();
1192  // minBorderY = YCoord();
1193 
1194  // // update maxBorder coordinate values
1195  // setSearchGround(maxBorder, constBorder, searchRingLongitude);
1196  // // if (!m_good){
1197  // // this should not happen since maxBorder has already been verified in
1198  // // the while loop above
1199  // // }
1200 
1201  // maxBorderX = XCoord();
1202  // maxBorderY = YCoord();
1203  // return;
1204  // }
1205 
1228  // void Projection::setSearchGround(const double variableBorder,
1229  // const double constBorder,
1230  // bool variableIsLat) {
1231  // if (variableBorder == Null || constBorder == Null) {
1232  // return;
1233  // }
1234  // double lat, lon;
1235  // if (variableIsLat) {
1236  // lat = variableBorder;
1237  // lon = constBorder;
1238  // }
1239  // else {
1240  // lat = constBorder;
1241  // lon = variableBorder;
1242  // }
1243  // SetGround(lat, lon);
1244  // return;
1245  // }
1246 
1247 
1254  PvlGroup mapping("Mapping");
1255 
1256  if (m_mappingGrp.hasKeyword("TargetName")) {
1257  mapping += m_mappingGrp["TargetName"];
1258  }
1259 
1260  mapping += m_mappingGrp["ProjectionName"];
1261  mapping += m_mappingGrp["RingLongitudeDirection"];
1262  mapping += m_mappingGrp["RingLongitudeDomain"];
1263 
1264  if (m_mappingGrp.hasKeyword("PixelResolution")) {
1265  mapping += m_mappingGrp["PixelResolution"];
1266  }
1267  if (m_mappingGrp.hasKeyword("Scale")) {
1268  mapping += m_mappingGrp["Scale"];
1269  }
1270  if (m_mappingGrp.hasKeyword("UpperLeftCornerX")) {
1271  mapping += m_mappingGrp["UpperLeftCornerX"];
1272  }
1273  if (m_mappingGrp.hasKeyword("UpperLeftCornerY")) {
1274  mapping += m_mappingGrp["UpperLeftCornerY"];
1275  }
1276 
1277  if (HasGroundRange()) {
1278  mapping += m_mappingGrp["MinimumRingRadius"];
1279  mapping += m_mappingGrp["MaximumRingRadius"];
1280  mapping += m_mappingGrp["MinimumRingLongitude"];
1281  mapping += m_mappingGrp["MaximumRingLongitude"];
1282  }
1283 
1284  if (m_mappingGrp.hasKeyword("Rotation")) {
1285  mapping += m_mappingGrp["Rotation"];
1286  }
1287 
1288  return mapping;
1289  }
1290 
1297  PvlGroup mapping("Mapping");
1298 
1299  if (HasGroundRange()) {
1300  mapping += m_mappingGrp["MinimumRingRadius"];
1301  mapping += m_mappingGrp["MaximumRingRadius"];
1302  }
1303 
1304  return mapping;
1305  }
1306 
1307 
1314  PvlGroup mapping("Mapping");
1315 
1316  if (HasGroundRange()) {
1317  mapping += m_mappingGrp["MinimumRingLongitude"];
1318  mapping += m_mappingGrp["MaximumRingLongitude"];
1319  }
1320 
1321  return mapping;
1322  }
1323 
1324 } //end namespace isis
Isis::RingPlaneProjection::CounterClockwise
@ CounterClockwise
Ring longitude values increase in the counterclockwise direction.
Definition: RingPlaneProjection.h:180
Isis::Angle::Degrees
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:56
Isis::RingPlaneProjection::SetGround
virtual bool SetGround(const double ringRadius, const double ringLongitude)
This method is used to set the ring radius/longitude (assumed to be of the correct LatitudeType,...
Definition: RingPlaneProjection.cpp:456
Isis::RingPlaneProjection::Has360Domain
bool Has360Domain() const
This indicates if the ring longitude domain is 0 to 360 (as opposed to -180 to 180).
Definition: RingPlaneProjection.cpp:337
Isis::RingPlaneProjection::m_maximumRingLongitude
double m_maximumRingLongitude
Contains the maximum longitude for the entire ground range.
Definition: RingPlaneProjection.h:290
Isis::RingPlaneProjection::UniversalRingLongitude
double UniversalRingLongitude()
This returns a universal ring longitude (clockwise in 0 to 360 domain).
Definition: RingPlaneProjection.cpp:589
Isis::Projection::m_mapper
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
Definition: Projection.h:292
Isis::RingPlaneProjection::MinimumRingRadius
double MinimumRingRadius() const
This returns the minimum radius of the area of interest.
Definition: RingPlaneProjection.cpp:405
Isis::RingPlaneProjection::Mapping
virtual PvlGroup Mapping()
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
Definition: RingPlaneProjection.cpp:1253
Isis::RingPlaneProjection::To360Domain
static double To360Domain(const double lon)
This method converts an ring longitude into the 0 to 360 domain.
Definition: RingPlaneProjection.cpp:370
Isis::DEG2RAD
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:43
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::m_minimumY
double m_minimumY
See minimumX description.
Definition: Projection.h:327
Isis::RingPlaneProjection::RingLongitude
double RingLongitude() const
This returns a ring longitude with correct ring longitude direction and domain as specified in the la...
Definition: RingPlaneProjection.cpp:530
Isis::RingPlaneProjection::LocalRadius
double LocalRadius() const
This returns a local radius.
Definition: RingPlaneProjection.cpp:518
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::RingPlaneProjection::XYRange
virtual 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: RingPlaneProjection.cpp:656
Isis::RingPlaneProjection::Has180Domain
bool Has180Domain() const
This indicates if the longitude domain is -180 to 180 (as opposed to 0 to 360).
Definition: RingPlaneProjection.cpp:326
Isis::WorldMapper::Resolution
virtual double Resolution() const
This virtual method will the resolution of the world system relative to one unit in the projection sy...
Definition: WorldMapper.h:100
Isis::RingPlaneProjection::m_maximumRingRadius
double m_maximumRingRadius
Contains the maximum ring radius for the entire ground range.
Definition: RingPlaneProjection.h:284
Isis::RingPlaneProjection::SetCoordinate
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
Definition: RingPlaneProjection.cpp:485
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::Longitude::force180Domain
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
Definition: Longitude.cpp:289
Isis::RingPlaneProjection::m_ringRadius
double m_ringRadius
This contain a ring radius value in m.
Definition: RingPlaneProjection.h:261
Isis::Projection::m_mappingGrp
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:329
Isis::Projection::setProjectionType
void setProjectionType(const ProjectionType ptype)
Sets the projection subclass type.
Definition: Projection.cpp:188
Isis::RingPlaneProjection::XYRangeCheck
void XYRangeCheck(const double ringRadius, const double ringLongitude)
This convience function is established to assist in the development of the XYRange virtual method.
Definition: RingPlaneProjection.cpp:709
Isis::RingPlaneProjection::MaximumRingRadius
double MaximumRingRadius() const
This returns the maximum radius of the area of interest.
Definition: RingPlaneProjection.cpp:416
Isis::Longitude
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:40
Isis::RingPlaneProjection::RingLongitudeDirectionString
std::string RingLongitudeDirectionString() const
This method returns the ring longitude direction as a string.
Definition: RingPlaneProjection.cpp:314
Isis::RingPlaneProjection::TrueScaleRingRadius
virtual double TrueScaleRingRadius() const
This method returns the radius of true scale.
Definition: RingPlaneProjection.cpp:199
Isis::RingPlaneProjection::RingLongitudeDomainString
std::string RingLongitudeDomainString() const
This method returns the ring longitude domain as a string.
Definition: RingPlaneProjection.cpp:393
Isis::Projection::IsGood
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:374
Isis::RingPlaneProjection
Base class for Map Projections of plane shapes.
Definition: RingPlaneProjection.h:147
Isis::Projection::m_minimumX
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition: Projection.h:317
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::RingPlaneProjection::ToCounterClockwise
static double ToCounterClockwise(const double ringLongitude, const int domain)
This method converts an ring longitude into the counterclockwise direction.
Definition: RingPlaneProjection.cpp:280
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::RingPlaneProjection::IsClockwise
bool IsClockwise() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
Definition: RingPlaneProjection.cpp:211
Isis::RingPlaneProjection::RingRadius
double RingRadius() const
This returns a radius.
Definition: RingPlaneProjection.cpp:506
Isis::RingPlaneProjection::MaximumRingLongitude
double MaximumRingLongitude() const
This returns the maximum ring longitude of the area of interest.
Definition: RingPlaneProjection.cpp:438
Isis::RingPlaneProjection::MinimumRingLongitude
double MinimumRingLongitude() const
This returns the minimum ring longitude of the area of interest.
Definition: RingPlaneProjection.cpp:427
Isis::RingPlaneProjection::MappingRingRadii
virtual PvlGroup MappingRingRadii()
This function returns the ring radius keywords that this projection uses.
Definition: RingPlaneProjection.cpp:1296
Isis::RingPlaneProjection::m_ringLongitude
double m_ringLongitude
This contain a ring longitude value.
Definition: RingPlaneProjection.h:263
Isis::Projection::RingPlane
@ RingPlane
These projections are used to map ring planes.
Definition: Projection.h:168
Isis::RingPlaneProjection::SetUniversalGround
bool SetUniversalGround(const double ringRadius, const double ringLongitude)
This method is used to set the ring radius/longitude which must be PositiveEast/Domain360 (ring longi...
Definition: RingPlaneProjection.cpp:546
Isis::RingPlaneProjection::m_ringLongitudeDirection
RingLongitudeDirection m_ringLongitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
Definition: RingPlaneProjection.h:267
Isis::RingPlaneProjection::IsCounterClockwise
bool IsCounterClockwise() const
This indicates if the longitude direction type is positive east (as opposed to postive west).
Definition: RingPlaneProjection.cpp:222
Isis::RingPlaneProjection::To180Domain
static double To180Domain(const double lon)
This method converts a ring longitude into the -180 to 180 domain.
Definition: RingPlaneProjection.cpp:352
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Projection::m_groundRangeGood
bool m_groundRangeGood
Indicates if the ground range (min/max lat/lons) were read from the labels.
Definition: Projection.h:313
Isis::Null
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:95
Isis::Projection::SetComputedXY
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:780
Isis::RingPlaneProjection::~RingPlaneProjection
virtual ~RingPlaneProjection()
Destroys the Projection object.
Definition: RingPlaneProjection.cpp:169
std
Namespace for the standard library.
Isis::RingPlaneProjection::Scale
double Scale() const
This method returns the scale for mapping world coordinates into projection coordinates.
Definition: RingPlaneProjection.cpp:607
Isis::RingPlaneProjection::operator==
virtual bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the ring longitude d...
Definition: RingPlaneProjection.cpp:181
Isis::Angle::degrees
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:232
Isis::RingPlaneProjection::m_minimumRingRadius
double m_minimumRingRadius
Contains the minimum ring radius for the entire ground range.
Definition: RingPlaneProjection.h:281
Isis::RingPlaneProjection::ToClockwise
static double ToClockwise(const double ringLongitude, const int domain)
This method converts an ring longitude into the clockwise direction.
Definition: RingPlaneProjection.cpp:240
Isis::RingPlaneProjection::MappingRingLongitudes
virtual PvlGroup MappingRingLongitudes()
This function returns the ring longitude keywords that this projection uses.
Definition: RingPlaneProjection.cpp:1313
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::RingPlaneProjection::Clockwise
@ Clockwise
Ring longitude values increase in the clockwise direction.
Definition: RingPlaneProjection.h:178
Isis::Projection::YCoord
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:400
Isis::Projection::m_maximumY
double m_maximumY
See minimumX description.
Definition: Projection.h:328
Isis::RingPlaneProjection::m_minimumRingLongitude
double m_minimumRingLongitude
Contains the minimum longitude for the entire ground range.
Definition: RingPlaneProjection.h:287
Isis::RingPlaneProjection::m_ringLongitudeDomain
int m_ringLongitudeDomain
This integer is either 180 or 360 and is read from the labels.
Definition: RingPlaneProjection.h:275
Isis::Projection
Base class for Map Projections.
Definition: Projection.h:155
Isis::Projection::m_maximumX
double m_maximumX
See minimumX description.
Definition: Projection.h:326
Isis::Longitude::force360Domain
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
Definition: Longitude.cpp:267
Isis::Projection::XCoord
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:387
Isis::Projection::HasGroundRange
virtual bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
Definition: Projection.cpp:349
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::RingPlaneProjection::UniversalRingRadius
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
Definition: RingPlaneProjection.cpp:575