USGS

Isis 3.0 Object Programmers' Reference

Home

Projection.cpp
Go to the documentation of this file.
1 
22 #include "Projection.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 "RingPlaneProjection.h"
45 #include "SpecialPixel.h"
46 #include "TProjection.h"
47 #include "WorldMapper.h"
48 
49 using namespace std;
50 namespace Isis {
106  Projection::Projection(Pvl &label) : m_mappingGrp("Mapping") {
107  try {
108  // Try to read the mapping group
109  m_mappingGrp = label.findGroup("Mapping", Pvl::Traverse);
110 
111  // TODO** Try to generalize these to keep in parent Projection class and use for both azimuth and longitude
112  // Get the RingLongitudeDomain or LongitudeDomain
113  // if ((string) m_mappingGrp["LongitudeDomain"] == "360") {
114  // m_longitudeDomain = 360;
115  // }
116  // else if ((string) m_mappingGrp["LongitudeDomain"] == "180") {
117  // m_longitudeDomain = 180;
118  // }
119  // else {
120  // IString msg = "Projection failed. Invalid value for keyword "
121  // "[LongitudeDomain] must be [180 or 360]";
122  // throw IException(IException::Unknown, msg, _FILEINFO_);
123  // }
124 
125  // Get the map rotation
126  m_rotation = 0.0;
127  if (m_mappingGrp.hasKeyword("Rotation")) {
128  m_rotation = m_mappingGrp["Rotation"];
129  }
130 
131  // Initialize miscellaneous protected data elements
132  m_good = false;
133 
134  m_pixelResolution = 1.0;
135  if (m_mappingGrp.hasKeyword("PixelResolution")) {
136  m_pixelResolution = m_mappingGrp["PixelResolution"];
137  }
138 
139  m_minimumX = DBL_MAX;
140  m_maximumX = -DBL_MAX;
141  m_minimumY = DBL_MAX;
142  m_maximumY = -DBL_MAX;
143 
144  m_mapper = NULL;
145 
146  m_sky = false;
147  if (m_mappingGrp.hasKeyword("TargetName")) {
148  QString str = m_mappingGrp["TargetName"];
149  if (str.toUpper() == "SKY") m_sky = true;
150  }
151 
152  // initialize the rest of the x,y,lat,lon member variables
153  m_x = Null;
154  m_y = Null;
155  }
156  catch(IException &e) {
157  QString msg = "Projection failed. Invalid label group [Mapping]";
158  throw IException(e, IException::Unknown, msg, _FILEINFO_);
159  }
160  }
161 
164  if(m_mapper) delete m_mapper;
165  }
166 
167 
178  if (Resolution() != proj.Resolution()) return false;
179  if (Name() != proj.Name()) return false;
180  return true;
181  }
182 
183 
194  return !(*this == proj);
195  }
196 
197 
204  m_projectionType = ptype;
205  }
206 
207 
214  return m_projectionType;
215  }
216 
217 
223  bool Projection::IsSky() const {
224  return m_sky;
225  }
226 
227 
238  return false;
239  }
240 
248  // bool Projection::IsPositiveEast() const {
249  // return m_longitudeDirection == PositiveEast;
250  // }
251 
259  // bool Projection::IsPositiveWest() const {
260  // return m_longitudeDirection == PositiveWest;
261  // }
262 
263 
271  // string Projection::LongitudeDirectionString() const {
272  // if (m_longitudeDirection == PositiveEast) return "PositiveEast";
273  // return "PositiveWest";
274  // }
275 
283  // bool Projection::Has180Domain() const {
284  // return m_longitudeDomain == 180;
285 // }
286 
294  // bool Projection::Has360Domain() const {
295  // return m_longitudeDomain == 360;
296  // }
297 
308  // double Projection::To180Domain(const double lon) {
309  // if (lon == Null) {
310  // throw IException(IException::Unknown,
311  // "Unable to convert to 180 degree domain. The given longitude value ["
312  // + IString(lon) + "] is invalid.",
313  // _FILEINFO_);
314  // }
315  // return Isis::Longitude(lon, Angle::Degrees).force180Domain().degrees();
316  // }
317 
326  // double Projection::To360Domain(const double lon) {
327  // if (lon == Null) {
328  // throw IException(IException::Unknown,
329  // "Unable to convert to 360 degree domain. The given longitude value ["
330  // + IString(lon) + "] is invalid.",
331  // _FILEINFO_);
332  // }
333  // double result = lon;
334 
335  // if ( (lon < 0.0 || lon > 360.0) &&
336  // !qFuzzyCompare(lon, 0.0) && !qFuzzyCompare(lon, 360.0)) {
337  // result = Isis::Longitude(lon, Angle::Degrees).force360Domain().degrees();
338  // }
339 
340  // return result;
341  // }
342 
349  // string Projection::LongitudeDomainString() const {
350  // if (m_longitudeDomain == 360) return "360";
351  // return "180";
352  // }
353 
365  return m_groundRangeGood;
366  }
367 
368 
374  double Projection::Rotation() const {
375  return m_rotation;
376  }
377 
378 
389  bool Projection::IsGood() const {
390  return m_good;
391  }
392 
393 
402  double Projection::XCoord() const {
403  return m_x;
404  }
405 
406 
415  double Projection::YCoord() const {
416  return m_y;
417  }
418 
419 
432  bool Projection::SetUniversalGround(const double coord1, const double coord2) {
433  if (coord1 == Null || coord2 == Null) {
434  m_good = false;
435  return m_good;
436  }
437  if (projectionType() == Triaxial) {
438  TProjection *tproj = (TProjection *) this;
439  return tproj->SetUniversalGround(coord1, coord2);
440  }
441  else {
442  RingPlaneProjection *rproj = (RingPlaneProjection *) this;
443  return rproj->SetUniversalGround(coord1, coord2);
444  }
445  }
446 
447 
461  m_mapper = mapper;
462  }
463 
483  bool Projection::SetWorld(const double worldX, const double worldY) {
484  double projectionX;
485  double projectionY;
486 
487  if (m_mapper != NULL) {
488  projectionX = m_mapper->ProjectionX(worldX);
489  projectionY = m_mapper->ProjectionY(worldY);
490  }
491  else {
492  projectionX = worldX;
493  projectionY = worldY;
494  }
495 
496  return SetCoordinate(projectionX, projectionY);
497  }
498 
510  double Projection::WorldX() const {
511  if (m_mapper != NULL) {
512  return m_mapper->WorldX(m_x);
513  }
514  else {
515  return m_x;
516  }
517  }
518 
530  double Projection::WorldY() const {
531  if (m_mapper != NULL) {
532  return m_mapper->WorldY(m_y);
533  }
534  else {
535  return m_y;
536  }
537  }
538 
552  double Projection::ToWorldX(const double projectionX) const {
553  if (projectionX == Null) {
555  "Unable to convert to world x. The given x-value ["
556  + IString(projectionX) + "] is invalid.",
557  _FILEINFO_);
558  }
559  if (m_mapper != NULL) {
560  return m_mapper->WorldX(projectionX);
561  }
562  else {
563  return projectionX;
564  }
565  }
566 
580  double Projection::ToWorldY(const double projectionY) const {
581  if (projectionY == Null) {
583  "Unable to convert to world y. The given y-value ["
584  + IString(projectionY) + "] is invalid.",
585  _FILEINFO_);
586  }
587  if (m_mapper != NULL) {
588  return m_mapper->WorldY(projectionY);
589  }
590  else {
591  return projectionY;
592  }
593  }
594 
608  double Projection::ToProjectionX(const double worldX) const {
609  if (worldX == Null) {
611  "Unable to convert to projection x. The given x-value ["
612  + IString(worldX) + "] is invalid.",
613  _FILEINFO_);
614  }
615  if (m_mapper != NULL) {
616  return m_mapper->ProjectionX(worldX);
617  }
618  else {
619  return worldX;
620  }
621  }
622 
636  double Projection::ToProjectionY(const double worldY) const {
637  if (worldY == Null) {
639  "Unable to convert to projection y. The given y-value ["
640  + IString(worldY) + "] is invalid.",
641  _FILEINFO_);
642  }
643  if (m_mapper != NULL) {
644  return m_mapper->ProjectionY(worldY);
645  }
646  else {
647  return worldY;
648  }
649  }
650 
661  double Projection::Resolution() const {
662  if (m_mapper != NULL) {
663  return m_mapper->Resolution();
664  }
665  else {
666  return 1.0;
667  }
668  }
669 
670 
679  double Projection::ToHours(double angle) {
680  return angle / 15.0;
681  }
682 
692  QString Projection::ToDMS(double angle) {
693  int iangle = (int)angle;
694  double mins = abs(angle - iangle) * 60.0;
695  int imins = (int)mins;
696  double secs = (mins - imins) * 60.0;
697  int isecs = (int)secs;
698  double frac = (secs - isecs) * 1000.0;
699  if (frac >= 1000.0) {
700  frac -= 1000.0;
701  isecs++;
702  }
703  if (isecs >= 60) {
704  isecs -= 60;
705  imins++;
706  }
707  if (imins >= 60) {
708  imins -= 60;
709  iangle++;
710  }
711  stringstream s;
712  s << iangle << " " << setw(2) << setfill('0')
713  << imins << "m " << setw(2) << setfill('0') << isecs << "." <<
714  setprecision(3) << frac << "s";
715  return s.str().c_str();
716  }
717 
727  QString Projection::ToHMS(double angle) {
728  double tangle = angle;
729  while (tangle < 0.0) tangle += 360.0;
730  while (tangle > 360.0) tangle -= 360.0;
731  double hrs = ToHours(tangle);
732  int ihrs = (int)(hrs);
733  double mins = (hrs - ihrs) * 60.0;
734  int imins = (int)(mins);
735  double secs = (mins - imins) * 60.0;
736  int isecs = (int)(secs);
737  double msecs = (secs - isecs) * 1000.0;
738  int imsecs = (int)(msecs + 0.5);
739  if (imsecs >= 1000) {
740  imsecs -= 1000;
741  isecs++;
742  }
743  if (isecs >= 60) {
744  isecs -= 60;
745  imins++;
746  }
747  if (imins >= 60) {
748  imins -= 60;
749  ihrs++;
750  }
751  stringstream s;
752  s << setw(2) << setfill('0') << ihrs << "h " << setw(2) << setfill('0') <<
753  imins << "m " << setw(2) << setfill('0') << isecs << "." << imsecs << "s";
754  return s.str().c_str();
755  }
756 
766  void Projection::SetComputedXY(double x, double y) {
767  if (x == Null || y == Null) {
768  m_good = false;
769  return;
770  }
771  if (m_rotation == 0.0) {
772  m_x = x;
773  m_y = y;
774  }
775  else {
776  double rot = m_rotation * PI / 180.0;
777  m_x = x * cos(rot) + y * sin(rot);
778  m_y = y * cos(rot) - x * sin(rot);
779  }
780  }
781 
790  void Projection::SetXY(double x, double y) {
791  if (x == Null || y == Null) {
792  m_good = false;
793  }
794  m_x = x;
795  m_y = y;
796  return;
797  }
798 
804  double Projection::GetX() const {
805  if (m_rotation == 0.0) return m_x;
806  double rot = m_rotation * PI / 180.0;
807  return m_x * cos(rot) - m_y * sin(rot);
808  }
809 
815  double Projection::GetY() const {
816  if (m_rotation == 0.0) return m_y;
817  double rot = m_rotation * PI / 180.0;
818  return m_y * cos(rot) + m_x * sin(rot);
819  }
820 
827  return m_pixelResolution;
828  }
829 
830 
831  // /**
832  // * This method is used to find the XY range for oblique aspect projections
833  // * (non-polar projections) by "walking" around each of the min/max lat/lon.
834  // *
835  // * @param minX Minimum x projection coordinate which covers the latitude
836  // * longitude range specified in the labels.
837  // * @param maxX Maximum x projection coordinate which covers the latitude
838  // * longitude range specified in the labels.
839  // * @param minY Minimum y projection coordinate which covers the latitude
840  // * longitude range specified in the labels.
841  // * @param maxY Maximum y projection coordinate which covers the latitude
842  // * longitude range specified in the labels.
843  // *
844  // * @return @b bool Indicates whether the method was successful.
845  // * @see XYRange()
846  // * @author Stephen Lambright
847  // * @internal
848  // * @history 2011-07-02 Jeannie Backer - Moved this code from
849  // * ObliqueCylindrical class to its own method here.
850  // */
851  // bool Projection::xyRangeOblique(double &minX, double &maxX,
852  // double &minY, double &maxY) {
853  // if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
854  // return false;
855  // }
856  // //For oblique, we'll have to walk all 4 sides to find out min/max x/y values
857  // if (!HasGroundRange()) return false; // Don't have min/max lat/lon,
858  // //can't continue
859 
860  // m_specialLatCases.clear();
861  // m_specialLonCases.clear();
862 
863  // // First, search longitude for min X/Y
864  // double minFoundX1, minFoundX2;
865  // double minFoundY1, minFoundY2;
866 
867  // // Search for minX between minlat and maxlat along minlon
868  // doSearch(MinimumLatitude(), MaximumLatitude(),
869  // minFoundX1, MinimumLongitude(), true, true, true);
870  // // Search for minX between minlat and maxlat along maxlon
871  // doSearch(MinimumLatitude(), MaximumLatitude(),
872  // minFoundX2, MaximumLongitude(), true, true, true);
873  // // Search for minY between minlat and maxlat along minlon
874  // doSearch(MinimumLatitude(), MaximumLatitude(),
875  // minFoundY1, MinimumLongitude(), false, true, true);
876  // // Search for minY between minlat and maxlat along maxlon
877  // doSearch(MinimumLatitude(), MaximumLatitude(),
878  // minFoundY2, MaximumLongitude(), false, true, true);
879 
880  // // Second, search latitude for min X/Y
881  // double minFoundX3, minFoundX4;
882  // double minFoundY3, minFoundY4;
883 
884  // // Search for minX between minlon and maxlon along minlat
885  // doSearch(MinimumLongitude(), MaximumLongitude(),
886  // minFoundX3, MinimumLatitude(), true, false, true);
887  // // Search for minX between minlon and maxlon along maxlat
888  // doSearch(MinimumLongitude(), MaximumLongitude(),
889  // minFoundX4, MaximumLatitude(), true, false, true);
890  // // Search for minY between minlon and maxlon along minlat
891  // doSearch(MinimumLongitude(), MaximumLongitude(),
892  // minFoundY3, MinimumLatitude(), false, false, true);
893  // // Search for minY between minlon and maxlon along maxlat
894  // doSearch(MinimumLongitude(), MaximumLongitude(),
895  // minFoundY4, MaximumLatitude(), false, false, true);
896 
897  // // We've searched all possible minimums, go ahead and store the lowest
898  // double minFoundX5 = min(minFoundX1, minFoundX2);
899  // double minFoundX6 = min(minFoundX3, minFoundX4);
900  // m_minimumX = min(minFoundX5, minFoundX6);
901 
902  // double minFoundY5 = min(minFoundY1, minFoundY2);
903  // double minFoundY6 = min(minFoundY3, minFoundY4);
904  // m_minimumY = min(minFoundY5, minFoundY6);
905 
906  // // Search longitude for max X/Y
907  // double maxFoundX1, maxFoundX2;
908  // double maxFoundY1, maxFoundY2;
909 
910  // // Search for maxX between minlat and maxlat along minlon
911  // doSearch(MinimumLatitude(), MaximumLatitude(),
912  // maxFoundX1, MinimumLongitude(), true, true, false);
913  // // Search for maxX between minlat and maxlat along maxlon
914  // doSearch(MinimumLatitude(), MaximumLatitude(),
915  // maxFoundX2, MaximumLongitude(), true, true, false);
916  // // Search for maxY between minlat and maxlat along minlon
917  // doSearch(MinimumLatitude(), MaximumLatitude(),
918  // maxFoundY1, MinimumLongitude(), false, true, false);
919  // // Search for maxY between minlat and maxlat along maxlon
920  // doSearch(MinimumLatitude(), MaximumLatitude(),
921  // maxFoundY2, MaximumLongitude(), false, true, false);
922 
923  // // Search latitude for max X/Y
924  // double maxFoundX3, maxFoundX4;
925  // double maxFoundY3, maxFoundY4;
926 
927  // // Search for maxX between minlon and maxlon along minlat
928  // doSearch(MinimumLongitude(), MaximumLongitude(),
929  // maxFoundX3, MinimumLatitude(), true, false, false);
930  // // Search for maxX between minlon and maxlon along maxlat
931  // doSearch(MinimumLongitude(), MaximumLongitude(),
932  // maxFoundX4, MaximumLatitude(), true, false, false);
933  // // Search for maxY between minlon and maxlon along minlat
934  // doSearch(MinimumLongitude(), MaximumLongitude(),
935  // maxFoundY3, MinimumLatitude(), false, false, false);
936  // // Search for maxY between minlon and maxlon along maxlat
937  // doSearch(MinimumLongitude(), MaximumLongitude(),
938  // maxFoundY4, MaximumLatitude(), false, false, false);
939 
940  // // We've searched all possible maximums, go ahead and store the highest
941  // double maxFoundX5 = max(maxFoundX1, maxFoundX2);
942  // double maxFoundX6 = max(maxFoundX3, maxFoundX4);
943  // m_maximumX = max(maxFoundX5, maxFoundX6);
944 
945  // double maxFoundY5 = max(maxFoundY1, maxFoundY2);
946  // double maxFoundY6 = max(maxFoundY3, maxFoundY4);
947  // m_maximumY = max(maxFoundY5, maxFoundY6);
948 
949  // // Look along discontinuities for more extremes
950  // vector<double> specialLatCases = m_specialLatCases;
951  // for (unsigned int specialLatCase = 0;
952  // specialLatCase < specialLatCases.size();
953  // specialLatCase ++) {
954  // double minX, maxX, minY, maxY;
955 
956  // // Search for minX between minlon and maxlon along latitude discontinuities
957  // doSearch(MinimumLongitude(), MaximumLongitude(),
958  // minX, specialLatCases[specialLatCase], true, false, true);
959  // // Search for minY between minlon and maxlon along latitude discontinuities
960  // doSearch(MinimumLongitude(), MaximumLongitude(),
961  // minY, specialLatCases[specialLatCase], false, false, true);
962  // // Search for maxX between minlon and maxlon along latitude discontinuities
963  // doSearch(MinimumLongitude(), MaximumLongitude(),
964  // maxX, specialLatCases[specialLatCase], true, false, false);
965  // // Search for maxX between minlon and maxlon along latitude discontinuities
966  // doSearch(MinimumLongitude(), MaximumLongitude(),
967  // maxY, specialLatCases[specialLatCase], false, false, false);
968 
969  // m_minimumX = min(minX, m_minimumX);
970  // m_maximumX = max(maxX, m_maximumX);
971  // m_minimumY = min(minY, m_minimumY);
972  // m_maximumY = max(maxY, m_maximumY);
973  // }
974 
975  // vector<double> specialLonCases = m_specialLonCases;
976  // for (unsigned int specialLonCase = 0;
977  // specialLonCase < specialLonCases.size();
978  // specialLonCase ++) {
979  // double minX, maxX, minY, maxY;
980 
981  // // Search for minX between minlat and maxlat along longitude discontinuities
982  // doSearch(MinimumLatitude(), MaximumLatitude(),
983  // minX, specialLonCases[specialLonCase], true, true, true);
984  // // Search for minY between minlat and maxlat along longitude discontinuities
985  // doSearch(MinimumLatitude(), MaximumLatitude(),
986  // minY, specialLonCases[specialLonCase], false, true, true);
987  // // Search for maxX between minlat and maxlat along longitude discontinuities
988  // doSearch(MinimumLatitude(), MaximumLatitude(),
989  // maxX, specialLonCases[specialLonCase], true, true, false);
990  // // Search for maxY between minlat and maxlat along longitude discontinuities
991  // doSearch(MinimumLatitude(), MaximumLatitude(),
992  // maxY, specialLonCases[specialLonCase], false, true, false);
993 
994  // m_minimumX = min(minX, m_minimumX);
995  // m_maximumX = max(maxX, m_maximumX);
996  // m_minimumY = min(minY, m_minimumY);
997  // m_maximumY = max(maxY, m_maximumY);
998  // }
999 
1000  // m_specialLatCases.clear();
1001  // m_specialLonCases.clear();
1002 
1003  // // Make sure everything is ordered
1004  // if (m_minimumX >= m_maximumX) return false;
1005  // if (m_minimumY >= m_maximumY) return false;
1006 
1007  // // Return X/Y min/maxs
1008  // minX = m_minimumX;
1009  // maxX = m_maximumX;
1010  // minY = m_minimumY;
1011  // maxY = m_maximumY;
1012 
1013  // return true;
1014  // }
1015 
1053  // void Projection::doSearch(double minBorder, double maxBorder,
1054  // double &extremeVal, const double constBorder,
1055  // bool searchX, bool searchLongitude, bool findMin) {
1056  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1057  // return;
1058  // }
1059  // const double TOLERANCE = m_pixelResolution/2;
1060  // const int NUM_ATTEMPTS = (unsigned int)DBL_DIG; // It's unsafe to go past
1061  // // this precision
1062 
1063  // double minBorderX, minBorderY, maxBorderX, maxBorderY;
1064  // int attempts = 0;
1065 
1066  // do {
1067  // findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
1068  // maxBorderY, constBorder, searchX, searchLongitude, findMin);
1069  // if (minBorderX == Null && maxBorderX == Null
1070  // && minBorderY == Null && maxBorderY == Null ) {
1071  // attempts = NUM_ATTEMPTS;
1072  // continue;
1073  // }
1074  // attempts ++;
1075  // }
1076  // while ((fabs(minBorderX - maxBorderX) > TOLERANCE
1077  // || fabs(minBorderY - maxBorderY) > TOLERANCE)
1078  // && (attempts < NUM_ATTEMPTS));
1079  // // check both x and y distance in case symmetry of map
1080  // // For example, if minBorderX = maxBorderX but minBorderY = -maxBorderY,
1081  // // these points may not be close enough.
1082 
1083  // if (attempts >= NUM_ATTEMPTS) {
1084  // // We zoomed in on a discontinuity because our range never shrank, this
1085  // // will need to be rechecked later.
1086  // // *min and max border should be nearly identical, so it doesn't matter
1087  // // which is used here
1088  // if (searchLongitude) {
1089  // m_specialLatCases.push_back(minBorder);
1090  // }
1091  // else {
1092  // m_specialLonCases.push_back(minBorder);
1093  // }
1094  // }
1095 
1096  // // These values will always be accurate, even over a discontinuity
1097  // if (findMin) {
1098  // if (searchX) extremeVal = min(minBorderX, maxBorderX);
1099  // else extremeVal = min(minBorderY, maxBorderY);
1100  // }
1101  // else {
1102  // if (searchX) extremeVal = max(minBorderX, maxBorderX);
1103  // else extremeVal = max(minBorderY, maxBorderY);
1104  // }
1105  // return;
1106  // }
1107 
1167  // void Projection::findExtreme(double &minBorder, double &maxBorder,
1168  // double &minBorderX, double &minBorderY,
1169  // double &maxBorderX, double &maxBorderY,
1170  // const double constBorder, bool searchX,
1171  // bool searchLongitude, bool findMin) {
1172  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1173  // minBorderX = Null;
1174  // minBorderY = minBorderX;
1175  // minBorderX = minBorderX;
1176  // minBorderY = minBorderX;
1177  // return;
1178  // }
1179  // if (!searchLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1180  // // it is impossible to search "along" a pole
1181  // setSearchGround(minBorder, constBorder, searchLongitude);
1182  // minBorderX = XCoord();
1183  // minBorderY = YCoord();
1184  // maxBorderX = minBorderX;
1185  // maxBorderY = minBorderY;
1186  // return;
1187  // }
1188  // // Always do 10 steps
1189  // const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1190  // const double LOOP_END = maxBorder + (STEP_SIZE / 2.0); // This ensures we do
1191  // // all of the steps
1192  // // properly
1193  // double currBorderVal = minBorder;
1194  // setSearchGround(minBorder, constBorder, searchLongitude);
1195 
1196  // // this makes sure that the initial currBorderVal is valid before entering
1197  // // the loop below
1198  // if (!m_good){
1199  // // minBorder = currBorderVal+STEP_SIZE < LOOP_END until setGround is good?
1200  // // then, if still not good return?
1201  // while (!m_good && currBorderVal <= LOOP_END) {
1202  // currBorderVal+=STEP_SIZE;
1203  // if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1204  // currBorderVal = 90.0;
1205  // }
1206  // setSearchGround(currBorderVal, constBorder, searchLongitude);
1207  // }
1208  // if (!m_good) {
1209  // minBorderX = Null;
1210  // minBorderY = minBorderX;
1211  // minBorderX = minBorderX;
1212  // minBorderY = minBorderX;
1213  // return;
1214  // }
1215  // }
1216 
1217  // // save the values of three consecutive steps from the minBorder towards
1218  // // the maxBorder along the constBorder. initialize these three border
1219  // // values (the non-constant lat or lon)
1220  // double border1 = currBorderVal;
1221  // double border2 = currBorderVal;
1222  // double border3 = currBorderVal;
1223 
1224  // // save the coordinate (x or y) values that correspond to the first
1225  // // two borders that are being saved.
1226  // // initialize these two coordinate values (x or y)
1227  // double value1 = (searchX) ? XCoord() : YCoord();
1228  // double value2 = value1;
1229 
1230  // // initialize the extreme coordinate value
1231  // // -- this is the largest coordinate value found so far
1232  // double extremeVal2 = value2;
1233 
1234  // // initialize the extreme border values
1235  // // -- these are the borders on either side of the extreme coordinate value
1236  // double extremeBorder1 = minBorder;
1237  // double extremeBorder3 = minBorder;
1238 
1239  // while (currBorderVal <= LOOP_END) {
1240 
1241  // // this conditional was added to prevent trying to SetGround with an
1242  // // invalid latitude greater than 90 degrees. There is no need check for
1243  // // latitude less than -90 since we start at the minBorder (already
1244  // // assumed to be valid) and step forward toward (and possibly past)
1245  // // maxBorder
1246  // if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1247  // currBorderVal = 90.0;
1248  // }
1249 
1250  // // update the current border value along constBorder
1251  // currBorderVal += STEP_SIZE;
1252  // setSearchGround(currBorderVal, constBorder, searchLongitude);
1253  // if (!m_good){
1254  // continue;
1255  // }
1256 
1257  // // update the border and coordinate values
1258  // border3 = border2;
1259  // border2 = border1;
1260  // border1 = currBorderVal;
1261  // value2 = value1;
1262  // value1 = (searchX) ? XCoord() : YCoord();
1263 
1264  // if ((findMin && value2 < extremeVal2)
1265  // || (!findMin && value2 > extremeVal2)) {
1266  // // Compare the coordinate value associated with the center border with
1267  // // the current extreme. If the updated coordinate value is more extreme
1268  // // (smaller or larger, depending on findMin), then we update the
1269  // // extremeVal and it's borders.
1270  // extremeVal2 = value2;
1271 
1272  // extremeBorder3 = border3;
1273  // extremeBorder1 = border1;
1274  // }
1275  // }
1276 
1277  // // update min/max border values to the values on either side of the most
1278  // // extreme coordinate found in this call to this method
1279 
1280  // minBorder = extremeBorder3; // Border 3 is lagging and thus smaller
1281 
1282  // // since the loop steps past the original maxBorder, we want to retain
1283  // // the original maxBorder value so we don't go outside of the original
1284  // // min/max range given
1285  // if (extremeBorder1 <= maxBorder ) {
1286  // maxBorder = extremeBorder1; // Border 1 is leading and thus larger
1287  // }
1288 
1289  // // update minBorder coordinate values
1290  // setSearchGround(minBorder, constBorder, searchLongitude);
1291  // // if (!m_good){
1292  // // this should not happen since minBorder has already been verified in
1293  // // the while loop above
1294  // // }
1295 
1296  // minBorderX = XCoord();
1297  // minBorderY = YCoord();
1298 
1299  // // update maxBorder coordinate values
1300  // setSearchGround(maxBorder, constBorder, searchLongitude);
1301  // // if (!m_good){
1302  // // this should not happen since maxBorder has already been verified in
1303  // // the while loop above
1304  // // }
1305 
1306  // maxBorderX = XCoord();
1307  // maxBorderY = YCoord();
1308  // return;
1309  // }
1310 
1333  // void Projection::setSearchGround(const double variableBorder,
1334  // const double constBorder,
1335  // bool variableIsLat) {
1336  // if (variableBorder == Null || constBorder == Null) {
1337  // return;
1338  // }
1339  // double lat, lon;
1340  // if (variableIsLat) {
1341  // lat = variableBorder;
1342  // lon = constBorder;
1343  // }
1344  // else {
1345  // lat = constBorder;
1346  // lon = variableBorder;
1347  // }
1348  // SetGround(lat, lon);
1349  // return;
1350  // }
1351 
1360  const Displacement &y) {
1361  PvlKeyword xKeyword("UpperLeftCornerX", toString(x.meters()), "meters");
1362  PvlKeyword yKeyword("UpperLeftCornerY", toString(y.meters()), "meters");
1363  m_mappingGrp.addKeyword(xKeyword,Pvl::Replace);
1364  m_mappingGrp.addKeyword(yKeyword,Pvl::Replace);
1365  }
1366 } //end namespace isis
1367 
1368