Isis 3 Programmer Reference
RingPlaneProjection.cpp
Go to the documentation of this file.
1 
22 #include "RingPlaneProjection.h"
23 
24 #include <QObject>
25 
26 #include <cfloat>
27 #include <cmath>
28 #include <iomanip>
29 #include <sstream>
30 #include <vector>
31 
32 #include <SpiceUsr.h>
33 
34 #include "Constants.h"
35 #include "Displacement.h"
36 #include "FileName.h"
37 #include "IException.h"
38 #include "IString.h"
39 #include "Longitude.h"
40 #include "NaifStatus.h"
41 #include "Pvl.h"
42 #include "PvlGroup.h"
43 #include "PvlKeyword.h"
44 #include "SpecialPixel.h"
45 #include "WorldMapper.h"
46 
47 using namespace std;
48 namespace Isis {
84  RingPlaneProjection::RingPlaneProjection(Pvl &label) : Projection::Projection(label) {
85  try {
86  // Mapping group is read by the parent (Projection)
87  // Get the RingLongitude Direction
88  if ((QString) m_mappingGrp["RingLongitudeDirection"] == "Clockwise") {
90  }
91  else if ((QString) m_mappingGrp["RingLongitudeDirection"] == "CounterClockwise") {
93  }
94  else {
95  QString msg = "Projection failed. Invalid value for keyword "
96  "[RingLongitudeDirection] must be "
97  "[Clockwise or CounterClockwise]";
99  }
100 
101  // Get the RingLongitudeDomain
102  if ((QString) m_mappingGrp["RingLongitudeDomain"] == "360") {
103  m_ringLongitudeDomain = 360;
104  }
105  else if ((QString) m_mappingGrp["RingLongitudeDomain"] == "180") {
106  m_ringLongitudeDomain = 180;
107  }
108  else {
109  QString msg = "Projection failed. Invalid value for keyword "
110  "[RingLongitudeDomain] must be [180 or 360]";
112  }
113 
114  // Get the ground range if it exists
115  m_groundRangeGood = false;
116 
117  if ((m_mappingGrp.hasKeyword("MinimumRingLongitude")) &&
118  (m_mappingGrp.hasKeyword("MaximumRingLongitude")) &&
119  (m_mappingGrp.hasKeyword("MaximumRingRadius")) &&
120  (m_mappingGrp.hasKeyword("MinimumRingRadius"))) {
121  m_minimumRingLongitude = m_mappingGrp["MinimumRingLongitude"];
122  m_maximumRingLongitude = m_mappingGrp["MaximumRingLongitude"];
123  m_minimumRingRadius = m_mappingGrp["MinimumRingRadius"];
124  m_maximumRingRadius = m_mappingGrp["MaximumRingRadius"];
125 
126  if (m_minimumRingRadius < 0) {
127  IString msg = "Projection failed. "
128  "[MinimumRingRadius] of ["+ IString(m_minimumRingRadius) + "] is not "
129  + "valid";
131  }
132 
133  if (m_maximumRingRadius < 0) {
134  IString msg = "Projection failed. "
135  "[MaximumRingRadius] of ["+ IString(m_maximumRingRadius) + "] is not "
136  + "valid";
138  }
139 
141  IString msg = "Projection failed. "
142  "[MinimumRingRadius,MaximumRingRadius] of ["
144  + IString(m_maximumRingRadius) + "] are not "
145  + "properly ordered";
147  }
148 
150  IString msg = "Projection failed. "
151  "[MinimumRingLongitude,MaximumRingLongitude] of ["
153  + IString(m_maximumRingLongitude) + "] are not "
154  + "properly ordered";
156  }
157 
158  m_groundRangeGood = true;
159  }
160  else {
161  // if no ground range is given, initialize the min/max ring rad/lon to 0
162  m_minimumRingRadius = 0.0;
163  m_maximumRingRadius = 0.0;
166  }
167 
168  // Initialize miscellaneous protected data elements
169  // initialize the rest of the x,y,ring rad,ring lon
170  // member variables
171  m_ringRadius = Null;
173 
174  // If we made it to this point, we have what we need for a ring plane projection
176  }
177  catch(IException &e) {
178  IString msg = "Projection failed. Invalid label group [Mapping]";
179  throw IException(e, IException::Unknown, msg, _FILEINFO_);
180  }
181  }
182 
185  }
186 
197  if (!Projection::operator==(proj)) return false;
198  RingPlaneProjection *rproj = (RingPlaneProjection *) &proj;
199  if (IsClockwise() != rproj->IsClockwise()) return false;
200  if (Has180Domain() != rproj->Has180Domain()) return false;
201  return true;
202  }
203 
204 
215  return 0.0;
216  }
217 
218 
228  }
229 
239  }
240 
255  double RingPlaneProjection::ToClockwise(const double ringLongitude, const int domain) {
256  if (ringLongitude == Null) {
258  "Unable to convert to Clockwise. The given ring longitude value ["
259  + Isis::toString(ringLongitude) + "] is invalid.",
260  _FILEINFO_);
261  }
262  double myRingLongitude = ringLongitude;
263 
264  myRingLongitude *= -1;
265 
266  if (domain == 360) {
267  myRingLongitude = To360Domain(myRingLongitude);
268  }
269  else if (domain == 180) {
270  myRingLongitude = To180Domain(myRingLongitude);
271  }
272  else {
273  IString msg = "Unable to convert ring longitude. Domain [" + Isis::toString(domain)
274  + "] is not 180 or 360.";
276  }
277 
278  return myRingLongitude;
279  }
280 
295  double RingPlaneProjection::ToCounterClockwise(const double ringLongitude, const int domain) {
296  if (ringLongitude == Null) {
298  "Unable to convert to CounterClockwise. The given ring longitude value ["
299  + IString(ringLongitude) + "] is invalid.",
300  _FILEINFO_);
301  }
302  double myRingLongitude = ringLongitude;
303 
304  myRingLongitude *= -1;
305 
306  if (domain == 360) {
307  myRingLongitude = To360Domain(myRingLongitude);
308  }
309  else if (domain == 180) {
310  myRingLongitude = To180Domain(myRingLongitude);
311  }
312  else {
313  IString msg = "Unable to convert ring longitude. Domain [" + IString(domain)
314  + "] is not 180 or 360.";
316  }
317 
318  return myRingLongitude;
319  }
320 
321 
330  if (m_ringLongitudeDirection == Clockwise) return "Clockwise";
331  return "CounterClockwise";
332  }
333 
342  return m_ringLongitudeDomain == 180;
343  }
344 
353  return m_ringLongitudeDomain == 360;
354  }
355 
367  double RingPlaneProjection::To180Domain(const double ringLongitude) {
368  if (ringLongitude == Null) {
370  "Unable to convert to 180 degree domain. The given ring longitude value ["
371  + IString(ringLongitude) + "] is invalid.",
372  _FILEINFO_);
373  }
374  return Isis::Longitude(ringLongitude, Angle::Degrees).force180Domain().degrees();
375  }
376 
385  double RingPlaneProjection::To360Domain(const double ringLongitude) {
386  if (ringLongitude == Null) {
388  "Unable to convert to 360 degree domain. The given ring longitude value ["
389  + IString(ringLongitude) + "] is invalid.",
390  _FILEINFO_);
391  }
392  double result = ringLongitude;
393 
394  if ( (ringLongitude < 0.0 || ringLongitude > 360.0) &&
395  !qFuzzyCompare(ringLongitude, 0.0) && !qFuzzyCompare(ringLongitude, 360.0)) {
396  result = Isis::Longitude(ringLongitude, Angle::Degrees).force360Domain().degrees();
397  }
398 
399  return result;
400  }
401 
409  if (m_ringLongitudeDomain == 360) return "360";
410  return "180";
411  }
412 
421  return m_minimumRingRadius;
422  }
423 
432  return m_maximumRingRadius;
433  }
434 
443  return m_minimumRingLongitude;
444  }
445 
454  return m_maximumRingLongitude;
455  }
456 
471  bool RingPlaneProjection::SetGround(const double ringRadius, const double ringLongitude) {
472  if (ringRadius == Null || ringLongitude == Null) {
473  m_good = false;
474  return m_good;
475  }
476  else {
477  m_ringRadius = ringRadius;
478  m_ringLongitude = ringLongitude;
479  m_good = true;
480  SetComputedXY(ringLongitude, ringRadius);
481  }
482  return m_good;
483  }
484 
500  bool RingPlaneProjection::SetCoordinate(const double x, const double y) {
501  if (x == Null || y == Null) {
502  m_good = false;
503  }
504  else {
505  m_good = true;
506  SetXY(x, y);
507  m_ringRadius = XCoord();
509  }
510  return m_good;
511  }
512 
513 
522  return m_ringRadius;
523  }
524 
525 
534  return m_ringRadius;
535  }
536 
546  return m_ringLongitude;
547  }
548 
561  bool RingPlaneProjection::SetUniversalGround(const double ringRadius, const double ringLongitude) {
562  if (ringRadius == Null || ringLongitude == Null) {
563  m_good = false;
564  return m_good;
565  }
566  // Deal with the ring longitude first
567  m_ringLongitude = ringLongitude;
568  if (m_ringLongitudeDirection == Clockwise) m_ringLongitude = -ringLongitude;
569  if (m_ringLongitudeDomain == 180) {
571  }
572  else {
573  // Do this because RingLongitudeDirection could cause (-360,0)
575  }
576 
577  // Nothing to do with radius
578 
579  m_ringRadius = ringRadius;
580 
581  // Now the rad/ring longitude are in user defined coordinates so set them
583  }
584 
591  double ringRadius = m_ringRadius;
592  return ringRadius;
593  }
594 
595 
605  double ringLongitude = m_ringLongitude;
606  if (m_ringLongitudeDirection == Clockwise) ringLongitude = -ringLongitude;
607  ringLongitude = To360Domain(ringLongitude);
608  return ringLongitude;
609  }
610 
611 
622  double RingPlaneProjection::Scale() const {
623  if (m_mapper != NULL) {
624  double localRadius = TrueScaleRingRadius();
625  return localRadius / m_mapper->Resolution() * DEG2RAD;
626  // return localRadius / m_mapper->Resolution();
627  }
628  else {
629  return 1.0;
630  }
631  }
632 
633 
671  bool RingPlaneProjection::XYRange(double &minX, double &maxX,
672  double &minY, double &maxY) {
673  if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
674  return false;
675  }
676  if (m_groundRangeGood) {
677  minX = m_minimumRingLongitude;
678  maxX = m_maximumRingLongitude;
679  minY = m_minimumRingRadius;
680  maxY = m_maximumRingRadius;
681  return true;
682  }
683  return false;
684  }
685 
724  void RingPlaneProjection::XYRangeCheck(const double ringRadius, const double ringLongitude) {
725  if (ringRadius == Null || ringLongitude == Null) {
726  m_good = false;
727  return;
728  }
729  SetGround(ringRadius, ringLongitude);
730  if (!IsGood()) return;
731 
732  if (XCoord() < m_minimumX) m_minimumX = XCoord();
733  if (XCoord() > m_maximumX) m_maximumX = XCoord();
734  if (YCoord() < m_minimumY) m_minimumY = YCoord();
735  if (YCoord() > m_maximumY) m_maximumY = YCoord();
736  return;
737  }
738 
760  // bool Projection::xyRangeOblique(double &minX, double &maxX,
761  // double &minY, double &maxY) {
762  // if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
763  // return false;
764  // }
765  // //For oblique, we'll have to walk all 4 sides to find out min/max x/y values
766  // if (!HasGroundRange()) return false; // Don't have min/max ring rad/lon,
767  // //can't continue
768 
769  // m_specialLatCases.clear();
770  // m_specialLonCases.clear();
771 
772  // // First, search ring longitude for
773  // min X/Y double minFoundX1, minFoundX2;
774  // double minFoundY1, minFoundY2;
775 
776  // // Search for minX between minlat and maxlat along minlon
777  // doSearch(MinimumLatitude(), MaximumLatitude(),
778  // minFoundX1, MinimumLongitude(), true, true, true);
779  // // Search for minX between minlat and maxlat along maxlon
780  // doSearch(MinimumLatitude(), MaximumLatitude(),
781  // minFoundX2, MaximumLongitude(), true, true, true);
782  // // Search for minY between minlat and maxlat along minlon
783  // doSearch(MinimumLatitude(), MaximumLatitude(),
784  // minFoundY1, MinimumLongitude(), false, true, true);
785  // // Search for minY between minlat and maxlat along maxlon
786  // doSearch(MinimumLatitude(), MaximumLatitude(),
787  // minFoundY2, MaximumLongitude(), false, true, true);
788 
789  // // Second, search latitude for min X/Y
790  // double minFoundX3, minFoundX4;
791  // double minFoundY3, minFoundY4;
792 
793  // // Search for minX between minlon and maxlon along minlat
794  // doSearch(MinimumLongitude(), MaximumLongitude(),
795  // minFoundX3, MinimumLatitude(), true, false, true);
796  // // Search for minX between minlon and maxlon along maxlat
797  // doSearch(MinimumLongitude(), MaximumLongitude(),
798  // minFoundX4, MaximumLatitude(), true, false, true);
799  // // Search for minY between minlon and maxlon along minlat
800  // doSearch(MinimumLongitude(), MaximumLongitude(),
801  // minFoundY3, MinimumLatitude(), false, false, true);
802  // // Search for minY between minlon and maxlon along maxlat
803  // doSearch(MinimumLongitude(), MaximumLongitude(),
804  // minFoundY4, MaximumLatitude(), false, false, true);
805 
806  // // We've searched all possible minimums, go ahead and store the lowest
807  // double minFoundX5 = min(minFoundX1, minFoundX2);
808  // double minFoundX6 = min(minFoundX3, minFoundX4);
809  // m_minimumX = min(minFoundX5, minFoundX6);
810 
811  // double minFoundY5 = min(minFoundY1, minFoundY2);
812  // double minFoundY6 = min(minFoundY3, minFoundY4);
813  // m_minimumY = min(minFoundY5, minFoundY6);
814 
815  // // Search ring longitude for
816  // max X/Y double maxFoundX1,
817  // maxFoundX2; double maxFoundY1,
818  // maxFoundY2;
819 
820  // // Search for maxX between minlat and maxlat along minlon
821  // doSearch(MinimumLatitude(), MaximumLatitude(),
822  // maxFoundX1, MinimumLongitude(), true, true, false);
823  // // Search for maxX between minlat and maxlat along maxlon
824  // doSearch(MinimumLatitude(), MaximumLatitude(),
825  // maxFoundX2, MaximumLongitude(), true, true, false);
826  // // Search for maxY between minlat and maxlat along minlon
827  // doSearch(MinimumLatitude(), MaximumLatitude(),
828  // maxFoundY1, MinimumLongitude(), false, true, false);
829  // // Search for maxY between minlat and maxlat along maxlon
830  // doSearch(MinimumLatitude(), MaximumLatitude(),
831  // maxFoundY2, MaximumLongitude(), false, true, false);
832 
833  // // Search latitude for max X/Y
834  // double maxFoundX3, maxFoundX4;
835  // double maxFoundY3, maxFoundY4;
836 
837  // // Search for maxX between minlon and maxlon along minlat
838  // doSearch(MinimumLongitude(), MaximumLongitude(),
839  // maxFoundX3, MinimumLatitude(), true, false, false);
840  // // Search for maxX between minlon and maxlon along maxlat
841  // doSearch(MinimumLongitude(), MaximumLongitude(),
842  // maxFoundX4, MaximumLatitude(), true, false, false);
843  // // Search for maxY between minlon and maxlon along minlat
844  // doSearch(MinimumLongitude(), MaximumLongitude(),
845  // maxFoundY3, MinimumLatitude(), false, false, false);
846  // // Search for maxY between minlon and maxlon along maxlat
847  // doSearch(MinimumLongitude(), MaximumLongitude(),
848  // maxFoundY4, MaximumLatitude(), false, false, false);
849 
850  // // We've searched all possible maximums, go ahead and store the highest
851  // double maxFoundX5 = max(maxFoundX1, maxFoundX2);
852  // double maxFoundX6 = max(maxFoundX3, maxFoundX4);
853  // m_maximumX = max(maxFoundX5, maxFoundX6);
854 
855  // double maxFoundY5 = max(maxFoundY1, maxFoundY2);
856  // double maxFoundY6 = max(maxFoundY3, maxFoundY4);
857  // m_maximumY = max(maxFoundY5, maxFoundY6);
858 
859  // // Look along discontinuities for more extremes
860  // vector<double> specialLatCases = m_specialLatCases;
861  // for (unsigned int specialLatCase = 0;
862  // specialLatCase < specialLatCases.size();
863  // specialLatCase ++) {
864  // double minX, maxX, minY, maxY;
865 
866  // // Search for minX between minlon and maxlon along latitude discontinuities
867  // doSearch(MinimumLongitude(), MaximumLongitude(),
868  // minX, specialLatCases[specialLatCase], true, false, true);
869  // // Search for minY between minlon and maxlon along latitude discontinuities
870  // doSearch(MinimumLongitude(), MaximumLongitude(),
871  // minY, specialLatCases[specialLatCase], false, false, true);
872  // // Search for maxX between minlon and maxlon along latitude discontinuities
873  // doSearch(MinimumLongitude(), MaximumLongitude(),
874  // maxX, specialLatCases[specialLatCase], true, false, false);
875  // // Search for maxX between minlon and maxlon along latitude discontinuities
876  // doSearch(MinimumLongitude(), MaximumLongitude(),
877  // maxY, specialLatCases[specialLatCase], false, false, false);
878 
879  // m_minimumX = min(minX, m_minimumX);
880  // m_maximumX = max(maxX, m_maximumX);
881  // m_minimumY = min(minY, m_minimumY);
882  // m_maximumY = max(maxY, m_maximumY);
883  // }
884 
885  // vector<double> specialLonCases = m_specialLonCases;
886  // for (unsigned int specialLonCase = 0;
887  // specialLonCase < specialLonCases.size();
888  // specialLonCase ++) {
889  // double minX, maxX, minY, maxY;
890 
891  // // Search for minX between minlat and maxlat along longitude discontinuities
892  // doSearch(MinimumLatitude(), MaximumLatitude(),
893  // minX, specialLonCases[specialLonCase], true, true, true);
894  // // Search for minY between minlat and maxlat along longitude discontinuities
895  // doSearch(MinimumLatitude(), MaximumLatitude(),
896  // minY, specialLonCases[specialLonCase], false, true, true);
897  // // Search for maxX between minlat and maxlat along longitude discontinuities
898  // doSearch(MinimumLatitude(), MaximumLatitude(),
899  // maxX, specialLonCases[specialLonCase], true, true, false);
900  // // Search for maxY between minlat and maxlat along longitude discontinuities
901  // doSearch(MinimumLatitude(), MaximumLatitude(),
902  // maxY, specialLonCases[specialLonCase], false, true, false);
903 
904  // m_minimumX = min(minX, m_minimumX);
905  // m_maximumX = max(maxX, m_maximumX);
906  // m_minimumY = min(minY, m_minimumY);
907  // m_maximumY = max(maxY, m_maximumY);
908  // }
909 
910  // m_specialLatCases.clear();
911  // m_specialLonCases.clear();
912 
913  // // Make sure everything is ordered
914  // if (m_minimumX >= m_maximumX) return false;
915  // if (m_minimumY >= m_maximumY) return false;
916 
917  // // Return X/Y min/maxs
918  // minX = m_minimumX;
919  // maxX = m_maximumX;
920  // minY = m_minimumY;
921  // maxY = m_maximumY;
922 
923  // return true;
924  // }
925 
963  // void Projection::doSearch(double minBorder, double maxBorder,
964  // double &extremeVal, const double constBorder,
965  // bool searchX, bool searchRingLongitude, bool findMin) {
966  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
967  // return;
968  // }
969  // const double TOLERANCE = m_pixelResolution/2;
970  // const int NUM_ATTEMPTS = (unsigned int)DBL_DIG; // It's unsafe to go past
971  // // this precision
972 
973  // double minBorderX, minBorderY, maxBorderX, maxBorderY;
974  // int attempts = 0;
975 
976  // do {
977  // findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
978  // maxBorderY, constBorder, searchX, searchLongitude, findMin);
979  // if (minBorderX == Null && maxBorderX == Null
980  // && minBorderY == Null && maxBorderY == Null ) {
981  // attempts = NUM_ATTEMPTS;
982  // continue;
983  // }
984  // attempts ++;
985  // }
986  // while ((fabs(minBorderX - maxBorderX) > TOLERANCE
987  // || fabs(minBorderY - maxBorderY) > TOLERANCE)
988  // && (attempts < NUM_ATTEMPTS));
989  // // check both x and y distance in case symmetry of map
990  // // For example, if minBorderX = maxBorderX but minBorderY = -maxBorderY,
991  // // these points may not be close enough.
992 
993  // if (attempts >= NUM_ATTEMPTS) {
994  // // We zoomed in on a discontinuity because our range never shrank, this
995  // // will need to be rechecked later.
996  // // *min and max border should be nearly identical, so it doesn't matter
997  // // which is used here
998  // if (searchLongitude) {
999  // m_specialLatCases.push_back(minBorder);
1000  // }
1001  // else {
1002  // m_specialLonCases.push_back(minBorder);
1003  // }
1004  // }
1005 
1006  // // These values will always be accurate, even over a discontinuity
1007  // if (findMin) {
1008  // if (searchX) extremeVal = min(minBorderX, maxBorderX);
1009  // else extremeVal = min(minBorderY, maxBorderY);
1010  // }
1011  // else {
1012  // if (searchX) extremeVal = max(minBorderX, maxBorderX);
1013  // else extremeVal = max(minBorderY, maxBorderY);
1014  // }
1015  // return;
1016  // }
1017 
1077  // void Projection::findExtreme(double &minBorder, double &maxBorder,
1078  // double &minBorderX, double &minBorderY,
1079  // double &maxBorderX, double &maxBorderY,
1080  // const double constBorder, bool searchX,
1081  // bool searchRingLongitude, bool findMin) {
1082  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1083  // minBorderX = Null;
1084  // minBorderY = minBorderX;
1085  // minBorderX = minBorderX;
1086  // minBorderY = minBorderX;
1087  // return;
1088  // }
1089  // if (!searchRingLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1090  // // it is impossible to search "along" a pole
1091  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1092  // minBorderX = XCoord();
1093  // minBorderY = YCoord();
1094  // maxBorderX = minBorderX;
1095  // maxBorderY = minBorderY;
1096  // return;
1097  // }
1098  // // Always do 10 steps
1099  // const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1100  // const double LOOP_END = maxBorder + (STEP_SIZE / 2.0); // This ensures we do
1101  // // all of the steps
1102  // // properly
1103  // double currBorderVal = minBorder;
1104  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1105 
1106  // // this makes sure that the initial currBorderVal is valid before entering
1107  // // the loop below
1108  // if (!m_good){
1109  // // minBorder = currBorderVal+STEP_SIZE < LOOP_END until setGround is good?
1110  // // then, if still not good return?
1111  // while (!m_good && currBorderVal <= LOOP_END) {
1112  // currBorderVal+=STEP_SIZE;
1113  // if (searchRingLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1114  // currBorderVal = 90.0;
1115  // }
1116  // setSearchGround(currBorderVal, constBorder, searchRingLongitude);
1117  // }
1118  // if (!m_good) {
1119  // minBorderX = Null;
1120  // minBorderY = minBorderX;
1121  // minBorderX = minBorderX;
1122  // minBorderY = minBorderX;
1123  // return;
1124  // }
1125  // }
1126 
1127  // // save the values of three consecutive steps from the minBorder towards
1128  // // the maxBorder along the constBorder. initialize these three border
1129  // // values (the non-constant lat or lon)
1130  // double border1 = currBorderVal;
1131  // double border2 = currBorderVal;
1132  // double border3 = currBorderVal;
1133 
1134  // // save the coordinate (x or y) values that correspond to the first
1135  // // two borders that are being saved.
1136  // // initialize these two coordinate values (x or y)
1137  // double value1 = (searchX) ? XCoord() : YCoord();
1138  // double value2 = value1;
1139 
1140  // // initialize the extreme coordinate value
1141  // // -- this is the largest coordinate value found so far
1142  // double extremeVal2 = value2;
1143 
1144  // // initialize the extreme border values
1145  // // -- these are the borders on either side of the extreme coordinate value
1146  // double extremeBorder1 = minBorder;
1147  // double extremeBorder3 = minBorder;
1148 
1149  // while (currBorderVal <= LOOP_END) {
1150 
1151  // // this conditional was added to prevent trying to SetGround with an
1152  // // invalid latitude greater than 90 degrees. There is no need check for
1153  // // latitude less than -90 since we start at the minBorder (already
1154  // // assumed to be valid) and step forward toward (and possibly past)
1155  // // maxBorder
1156  // if (searchRingLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1157  // currBorderVal = 90.0;
1158  // }
1159 
1160  // // update the current border value along constBorder
1161  // currBorderVal += STEP_SIZE;
1162  // setSearchGround(currBorderVal, constBorder, searchRingLongitude);
1163  // if (!m_good){
1164  // continue;
1165  // }
1166 
1167  // // update the border and coordinate values
1168  // border3 = border2;
1169  // border2 = border1;
1170  // border1 = currBorderVal;
1171  // value2 = value1;
1172  // value1 = (searchX) ? XCoord() : YCoord();
1173 
1174  // if ((findMin && value2 < extremeVal2)
1175  // || (!findMin && value2 > extremeVal2)) {
1176  // // Compare the coordinate value associated with the center border with
1177  // // the current extreme. If the updated coordinate value is more extreme
1178  // // (smaller or larger, depending on findMin), then we update the
1179  // // extremeVal and it's borders.
1180  // extremeVal2 = value2;
1181 
1182  // extremeBorder3 = border3;
1183  // extremeBorder1 = border1;
1184  // }
1185  // }
1186 
1187  // // update min/max border values to the values on either side of the most
1188  // // extreme coordinate found in this call to this method
1189 
1190  // minBorder = extremeBorder3; // Border 3 is lagging and thus smaller
1191 
1192  // // since the loop steps past the original maxBorder, we want to retain
1193  // // the original maxBorder value so we don't go outside of the original
1194  // // min/max range given
1195  // if (extremeBorder1 <= maxBorder ) {
1196  // maxBorder = extremeBorder1; // Border 1 is leading and thus larger
1197  // }
1198 
1199  // // update minBorder coordinate values
1200  // setSearchGround(minBorder, constBorder, searchRingLongitude);
1201  // // if (!m_good){
1202  // // this should not happen since minBorder has already been verified in
1203  // // the while loop above
1204  // // }
1205 
1206  // minBorderX = XCoord();
1207  // minBorderY = YCoord();
1208 
1209  // // update maxBorder coordinate values
1210  // setSearchGround(maxBorder, constBorder, searchRingLongitude);
1211  // // if (!m_good){
1212  // // this should not happen since maxBorder has already been verified in
1213  // // the while loop above
1214  // // }
1215 
1216  // maxBorderX = XCoord();
1217  // maxBorderY = YCoord();
1218  // return;
1219  // }
1220 
1243  // void Projection::setSearchGround(const double variableBorder,
1244  // const double constBorder,
1245  // bool variableIsLat) {
1246  // if (variableBorder == Null || constBorder == Null) {
1247  // return;
1248  // }
1249  // double lat, lon;
1250  // if (variableIsLat) {
1251  // lat = variableBorder;
1252  // lon = constBorder;
1253  // }
1254  // else {
1255  // lat = constBorder;
1256  // lon = variableBorder;
1257  // }
1258  // SetGround(lat, lon);
1259  // return;
1260  // }
1261 
1262 
1269  PvlGroup mapping("Mapping");
1270 
1271  if (m_mappingGrp.hasKeyword("TargetName")) {
1272  mapping += m_mappingGrp["TargetName"];
1273  }
1274 
1275  mapping += m_mappingGrp["ProjectionName"];
1276  mapping += m_mappingGrp["RingLongitudeDirection"];
1277  mapping += m_mappingGrp["RingLongitudeDomain"];
1278 
1279  if (m_mappingGrp.hasKeyword("PixelResolution")) {
1280  mapping += m_mappingGrp["PixelResolution"];
1281  }
1282  if (m_mappingGrp.hasKeyword("Scale")) {
1283  mapping += m_mappingGrp["Scale"];
1284  }
1285  if (m_mappingGrp.hasKeyword("UpperLeftCornerX")) {
1286  mapping += m_mappingGrp["UpperLeftCornerX"];
1287  }
1288  if (m_mappingGrp.hasKeyword("UpperLeftCornerY")) {
1289  mapping += m_mappingGrp["UpperLeftCornerY"];
1290  }
1291 
1292  if (HasGroundRange()) {
1293  mapping += m_mappingGrp["MinimumRingRadius"];
1294  mapping += m_mappingGrp["MaximumRingRadius"];
1295  mapping += m_mappingGrp["MinimumRingLongitude"];
1296  mapping += m_mappingGrp["MaximumRingLongitude"];
1297  }
1298 
1299  if (m_mappingGrp.hasKeyword("Rotation")) {
1300  mapping += m_mappingGrp["Rotation"];
1301  }
1302 
1303  return mapping;
1304  }
1305 
1312  PvlGroup mapping("Mapping");
1313 
1314  if (HasGroundRange()) {
1315  mapping += m_mappingGrp["MinimumRingRadius"];
1316  mapping += m_mappingGrp["MaximumRingRadius"];
1317  }
1318 
1319  return mapping;
1320  }
1321 
1322 
1329  PvlGroup mapping("Mapping");
1330 
1331  if (HasGroundRange()) {
1332  mapping += m_mappingGrp["MinimumRingLongitude"];
1333  mapping += m_mappingGrp["MaximumRingLongitude"];
1334  }
1335 
1336  return mapping;
1337  }
1338 
1339 } //end namespace isis
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
int m_ringLongitudeDomain
This integer is either 180 or 360 and is read from the labels.
bool IsCounterClockwise() const
This indicates if the longitude direction type is positive east (as opposed to postive west)...
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
double LocalRadius() const
This returns a local radius.
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
Definition: Projection.h:308
double m_maximumRingLongitude
Contains the maximum longitude for the entire ground range.
double MaximumRingLongitude() const
This returns the maximum ring longitude of the area of interest.
bool IsClockwise() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
Namespace for the standard library.
virtual PvlGroup MappingRingLongitudes()
This function returns the ring longitude keywords that this projection uses.
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
Definition: Longitude.cpp:302
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround, or SetWorld was with successful or not.
Definition: Projection.cpp:389
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:402
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Definition: Projection.h:333
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
double MinimumRingRadius() const
This returns the minimum radius of the area of interest.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:795
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
Definition: Longitude.cpp:280
virtual PvlGroup Mapping()
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
double m_maximumY
See minimumX description.
Definition: Projection.h:344
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
bool Has360Domain() const
This indicates if the ring longitude domain is 0 to 360 (as opposed to -180 to 180).
Base class for Map Projections.
Definition: Projection.h:171
double m_minimumY
See minimumX description.
Definition: Projection.h:343
These projections are used to map ring planes.
Definition: Projection.h:184
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
RingLongitudeDirection m_ringLongitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
Definition: Projection.cpp:364
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
void setProjectionType(const ProjectionType ptype)
Sets the projection subclass type.
Definition: Projection.cpp:203
bool m_groundRangeGood
Indicates if the ground range (min/max lat/lons) were read from the labels.
Definition: Projection.h:329
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
double Scale() const
This method returns the scale for mapping world coordinates into projection coordinates.
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
virtual double TrueScaleRingRadius() const
This method returns the radius of true scale.
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:415
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...
std::string RingLongitudeDomainString() const
This method returns the ring longitude domain as a string.
static double ToCounterClockwise(const double ringLongitude, const int domain)
This method converts an ring longitude into the counterclockwise direction.
Ring longitude values increase in the counterclockwise direction.
Container for cube-like labels.
Definition: Pvl.h:135
double m_ringLongitude
This contain a ring longitude value.
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:59
double MinimumRingLongitude() const
This returns the minimum ring longitude of the area of interest.
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition: Projection.h:316
double RingRadius() const
This returns a radius.
double m_ringRadius
This contain a ring radius value in m.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void XYRangeCheck(const double ringRadius, const double ringLongitude)
This convience function is established to assist in the development of the XYRange virtual method...
virtual bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the ring longitude d...
Ring longitude values increase in the clockwise direction.
Base class for Map Projections of plane shapes.
double m_maximumRingRadius
Contains the maximum ring radius for the entire ground range.
double MaximumRingRadius() const
This returns the maximum radius of the area of interest.
static double To360Domain(const double lon)
This method converts an ring longitude into the 0 to 360 domain.
static double ToClockwise(const double ringLongitude, const int domain)
This method converts an ring longitude into the clockwise direction.
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
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...
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...
bool Has180Domain() const
This indicates if the longitude domain is -180 to 180 (as opposed to 0 to 360).
void SetXY(double x, double y)
This protected method is a helper for derived classes.
Definition: Projection.cpp:819
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:116
double RingLongitude() const
This returns a ring longitude with correct ring longitude direction and domain as specified in the la...
static double To180Domain(const double lon)
This method converts a ring longitude into the -180 to 180 domain.
double m_maximumX
See minimumX description.
Definition: Projection.h:342
virtual ~RingPlaneProjection()
Destroys the Projection object.
std::string RingLongitudeDirectionString() const
This method returns the ring longitude direction as a string.
double m_minimumRingLongitude
Contains the minimum longitude for the entire ground range.
double UniversalRingLongitude()
This returns a universal ring longitude (clockwise in 0 to 360 domain).
virtual PvlGroup MappingRingRadii()
This function returns the ring radius keywords that this projection uses.
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:345
double m_minimumRingRadius
Contains the minimum ring radius for the entire ground range.