Isis 3 Programmer Reference
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  delete m_mapper;
165  m_mapper = NULL;
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  bool Projection::SetUnboundUniversalGround(const double coord1, const double coord2) {
462  if (coord1 == Null || coord2 == Null) {
463  m_good = false;
464  return m_good;
465  }
466  if (projectionType() == Triaxial) {
467  TProjection *tproj = (TProjection *) this;
468  return tproj->SetUnboundUniversalGround(coord1, coord2);
469  }
470  else {
471  RingPlaneProjection *rproj = (RingPlaneProjection *) this;
472  return rproj->SetUniversalGround(coord1, coord2);
473  }
474  }
475 
476 
490  m_mapper = mapper;
491  }
492 
512  bool Projection::SetWorld(const double worldX, const double worldY) {
513  double projectionX;
514  double projectionY;
515 
516  if (m_mapper != NULL) {
517  projectionX = m_mapper->ProjectionX(worldX);
518  projectionY = m_mapper->ProjectionY(worldY);
519  }
520  else {
521  projectionX = worldX;
522  projectionY = worldY;
523  }
524 
525  return SetCoordinate(projectionX, projectionY);
526  }
527 
539  double Projection::WorldX() const {
540  if (m_mapper != NULL) {
541  return m_mapper->WorldX(m_x);
542  }
543  else {
544  return m_x;
545  }
546  }
547 
559  double Projection::WorldY() const {
560  if (m_mapper != NULL) {
561  return m_mapper->WorldY(m_y);
562  }
563  else {
564  return m_y;
565  }
566  }
567 
581  double Projection::ToWorldX(const double projectionX) const {
582  if (projectionX == Null) {
584  "Unable to convert to world x. The given x-value ["
585  + IString(projectionX) + "] is invalid.",
586  _FILEINFO_);
587  }
588  if (m_mapper != NULL) {
589  return m_mapper->WorldX(projectionX);
590  }
591  else {
592  return projectionX;
593  }
594  }
595 
609  double Projection::ToWorldY(const double projectionY) const {
610  if (projectionY == Null) {
612  "Unable to convert to world y. The given y-value ["
613  + IString(projectionY) + "] is invalid.",
614  _FILEINFO_);
615  }
616  if (m_mapper != NULL) {
617  return m_mapper->WorldY(projectionY);
618  }
619  else {
620  return projectionY;
621  }
622  }
623 
637  double Projection::ToProjectionX(const double worldX) const {
638  if (worldX == Null) {
640  "Unable to convert to projection x. The given x-value ["
641  + IString(worldX) + "] is invalid.",
642  _FILEINFO_);
643  }
644  if (m_mapper != NULL) {
645  return m_mapper->ProjectionX(worldX);
646  }
647  else {
648  return worldX;
649  }
650  }
651 
665  double Projection::ToProjectionY(const double worldY) const {
666  if (worldY == Null) {
668  "Unable to convert to projection y. The given y-value ["
669  + IString(worldY) + "] is invalid.",
670  _FILEINFO_);
671  }
672  if (m_mapper != NULL) {
673  return m_mapper->ProjectionY(worldY);
674  }
675  else {
676  return worldY;
677  }
678  }
679 
690  double Projection::Resolution() const {
691  if (m_mapper != NULL) {
692  return m_mapper->Resolution();
693  }
694  else {
695  return 1.0;
696  }
697  }
698 
699 
708  double Projection::ToHours(double angle) {
709  return angle / 15.0;
710  }
711 
721  QString Projection::ToDMS(double angle) {
722  int iangle = (int)angle;
723  double mins = abs(angle - iangle) * 60.0;
724  int imins = (int)mins;
725  double secs = (mins - imins) * 60.0;
726  int isecs = (int)secs;
727  double frac = (secs - isecs) * 1000.0;
728  if (frac >= 1000.0) {
729  frac -= 1000.0;
730  isecs++;
731  }
732  if (isecs >= 60) {
733  isecs -= 60;
734  imins++;
735  }
736  if (imins >= 60) {
737  imins -= 60;
738  iangle++;
739  }
740  stringstream s;
741  s << iangle << " " << setw(2) << setfill('0')
742  << imins << "m " << setw(2) << setfill('0') << isecs << "." <<
743  setprecision(3) << frac << "s";
744  return s.str().c_str();
745  }
746 
756  QString Projection::ToHMS(double angle) {
757  double tangle = angle;
758  while (tangle < 0.0) tangle += 360.0;
759  while (tangle > 360.0) tangle -= 360.0;
760  double hrs = ToHours(tangle);
761  int ihrs = (int)(hrs);
762  double mins = (hrs - ihrs) * 60.0;
763  int imins = (int)(mins);
764  double secs = (mins - imins) * 60.0;
765  int isecs = (int)(secs);
766  double msecs = (secs - isecs) * 1000.0;
767  int imsecs = (int)(msecs + 0.5);
768  if (imsecs >= 1000) {
769  imsecs -= 1000;
770  isecs++;
771  }
772  if (isecs >= 60) {
773  isecs -= 60;
774  imins++;
775  }
776  if (imins >= 60) {
777  imins -= 60;
778  ihrs++;
779  }
780  stringstream s;
781  s << setw(2) << setfill('0') << ihrs << "h " << setw(2) << setfill('0') <<
782  imins << "m " << setw(2) << setfill('0') << isecs << "." << imsecs << "s";
783  return s.str().c_str();
784  }
785 
795  void Projection::SetComputedXY(double x, double y) {
796  if (x == Null || y == Null) {
797  m_good = false;
798  return;
799  }
800  if (m_rotation == 0.0) {
801  m_x = x;
802  m_y = y;
803  }
804  else {
805  double rot = m_rotation * PI / 180.0;
806  m_x = x * cos(rot) + y * sin(rot);
807  m_y = y * cos(rot) - x * sin(rot);
808  }
809  }
810 
819  void Projection::SetXY(double x, double y) {
820  if (x == Null || y == Null) {
821  m_good = false;
822  }
823  m_x = x;
824  m_y = y;
825  return;
826  }
827 
833  double Projection::GetX() const {
834  if (m_rotation == 0.0) return m_x;
835  double rot = m_rotation * PI / 180.0;
836  return m_x * cos(rot) - m_y * sin(rot);
837  }
838 
844  double Projection::GetY() const {
845  if (m_rotation == 0.0) return m_y;
846  double rot = m_rotation * PI / 180.0;
847  return m_y * cos(rot) + m_x * sin(rot);
848  }
849 
856  return m_pixelResolution;
857  }
858 
859 
860  // /**
861  // * This method is used to find the XY range for oblique aspect projections
862  // * (non-polar projections) by "walking" around each of the min/max lat/lon.
863  // *
864  // * @param minX Minimum x projection coordinate which covers the latitude
865  // * longitude range specified in the labels.
866  // * @param maxX Maximum x projection coordinate which covers the latitude
867  // * longitude range specified in the labels.
868  // * @param minY Minimum y projection coordinate which covers the latitude
869  // * longitude range specified in the labels.
870  // * @param maxY Maximum y projection coordinate which covers the latitude
871  // * longitude range specified in the labels.
872  // *
873  // * @return @b bool Indicates whether the method was successful.
874  // * @see XYRange()
875  // * @author Stephen Lambright
876  // * @internal
877  // * @history 2011-07-02 Jeannie Backer - Moved this code from
878  // * ObliqueCylindrical class to its own method here.
879  // */
880  // bool Projection::xyRangeOblique(double &minX, double &maxX,
881  // double &minY, double &maxY) {
882  // if (minX == Null || maxX == Null || minY == Null || maxY == Null) {
883  // return false;
884  // }
885  // //For oblique, we'll have to walk all 4 sides to find out min/max x/y values
886  // if (!HasGroundRange()) return false; // Don't have min/max lat/lon,
887  // //can't continue
888 
889  // m_specialLatCases.clear();
890  // m_specialLonCases.clear();
891 
892  // // First, search longitude for min X/Y
893  // double minFoundX1, minFoundX2;
894  // double minFoundY1, minFoundY2;
895 
896  // // Search for minX between minlat and maxlat along minlon
897  // doSearch(MinimumLatitude(), MaximumLatitude(),
898  // minFoundX1, MinimumLongitude(), true, true, true);
899  // // Search for minX between minlat and maxlat along maxlon
900  // doSearch(MinimumLatitude(), MaximumLatitude(),
901  // minFoundX2, MaximumLongitude(), true, true, true);
902  // // Search for minY between minlat and maxlat along minlon
903  // doSearch(MinimumLatitude(), MaximumLatitude(),
904  // minFoundY1, MinimumLongitude(), false, true, true);
905  // // Search for minY between minlat and maxlat along maxlon
906  // doSearch(MinimumLatitude(), MaximumLatitude(),
907  // minFoundY2, MaximumLongitude(), false, true, true);
908 
909  // // Second, search latitude for min X/Y
910  // double minFoundX3, minFoundX4;
911  // double minFoundY3, minFoundY4;
912 
913  // // Search for minX between minlon and maxlon along minlat
914  // doSearch(MinimumLongitude(), MaximumLongitude(),
915  // minFoundX3, MinimumLatitude(), true, false, true);
916  // // Search for minX between minlon and maxlon along maxlat
917  // doSearch(MinimumLongitude(), MaximumLongitude(),
918  // minFoundX4, MaximumLatitude(), true, false, true);
919  // // Search for minY between minlon and maxlon along minlat
920  // doSearch(MinimumLongitude(), MaximumLongitude(),
921  // minFoundY3, MinimumLatitude(), false, false, true);
922  // // Search for minY between minlon and maxlon along maxlat
923  // doSearch(MinimumLongitude(), MaximumLongitude(),
924  // minFoundY4, MaximumLatitude(), false, false, true);
925 
926  // // We've searched all possible minimums, go ahead and store the lowest
927  // double minFoundX5 = min(minFoundX1, minFoundX2);
928  // double minFoundX6 = min(minFoundX3, minFoundX4);
929  // m_minimumX = min(minFoundX5, minFoundX6);
930 
931  // double minFoundY5 = min(minFoundY1, minFoundY2);
932  // double minFoundY6 = min(minFoundY3, minFoundY4);
933  // m_minimumY = min(minFoundY5, minFoundY6);
934 
935  // // Search longitude for max X/Y
936  // double maxFoundX1, maxFoundX2;
937  // double maxFoundY1, maxFoundY2;
938 
939  // // Search for maxX between minlat and maxlat along minlon
940  // doSearch(MinimumLatitude(), MaximumLatitude(),
941  // maxFoundX1, MinimumLongitude(), true, true, false);
942  // // Search for maxX between minlat and maxlat along maxlon
943  // doSearch(MinimumLatitude(), MaximumLatitude(),
944  // maxFoundX2, MaximumLongitude(), true, true, false);
945  // // Search for maxY between minlat and maxlat along minlon
946  // doSearch(MinimumLatitude(), MaximumLatitude(),
947  // maxFoundY1, MinimumLongitude(), false, true, false);
948  // // Search for maxY between minlat and maxlat along maxlon
949  // doSearch(MinimumLatitude(), MaximumLatitude(),
950  // maxFoundY2, MaximumLongitude(), false, true, false);
951 
952  // // Search latitude for max X/Y
953  // double maxFoundX3, maxFoundX4;
954  // double maxFoundY3, maxFoundY4;
955 
956  // // Search for maxX between minlon and maxlon along minlat
957  // doSearch(MinimumLongitude(), MaximumLongitude(),
958  // maxFoundX3, MinimumLatitude(), true, false, false);
959  // // Search for maxX between minlon and maxlon along maxlat
960  // doSearch(MinimumLongitude(), MaximumLongitude(),
961  // maxFoundX4, MaximumLatitude(), true, false, false);
962  // // Search for maxY between minlon and maxlon along minlat
963  // doSearch(MinimumLongitude(), MaximumLongitude(),
964  // maxFoundY3, MinimumLatitude(), false, false, false);
965  // // Search for maxY between minlon and maxlon along maxlat
966  // doSearch(MinimumLongitude(), MaximumLongitude(),
967  // maxFoundY4, MaximumLatitude(), false, false, false);
968 
969  // // We've searched all possible maximums, go ahead and store the highest
970  // double maxFoundX5 = max(maxFoundX1, maxFoundX2);
971  // double maxFoundX6 = max(maxFoundX3, maxFoundX4);
972  // m_maximumX = max(maxFoundX5, maxFoundX6);
973 
974  // double maxFoundY5 = max(maxFoundY1, maxFoundY2);
975  // double maxFoundY6 = max(maxFoundY3, maxFoundY4);
976  // m_maximumY = max(maxFoundY5, maxFoundY6);
977 
978  // // Look along discontinuities for more extremes
979  // vector<double> specialLatCases = m_specialLatCases;
980  // for (unsigned int specialLatCase = 0;
981  // specialLatCase < specialLatCases.size();
982  // specialLatCase ++) {
983  // double minX, maxX, minY, maxY;
984 
985  // // Search for minX between minlon and maxlon along latitude discontinuities
986  // doSearch(MinimumLongitude(), MaximumLongitude(),
987  // minX, specialLatCases[specialLatCase], true, false, true);
988  // // Search for minY between minlon and maxlon along latitude discontinuities
989  // doSearch(MinimumLongitude(), MaximumLongitude(),
990  // minY, specialLatCases[specialLatCase], false, false, true);
991  // // Search for maxX between minlon and maxlon along latitude discontinuities
992  // doSearch(MinimumLongitude(), MaximumLongitude(),
993  // maxX, specialLatCases[specialLatCase], true, false, false);
994  // // Search for maxX between minlon and maxlon along latitude discontinuities
995  // doSearch(MinimumLongitude(), MaximumLongitude(),
996  // maxY, specialLatCases[specialLatCase], false, false, false);
997 
998  // m_minimumX = min(minX, m_minimumX);
999  // m_maximumX = max(maxX, m_maximumX);
1000  // m_minimumY = min(minY, m_minimumY);
1001  // m_maximumY = max(maxY, m_maximumY);
1002  // }
1003 
1004  // vector<double> specialLonCases = m_specialLonCases;
1005  // for (unsigned int specialLonCase = 0;
1006  // specialLonCase < specialLonCases.size();
1007  // specialLonCase ++) {
1008  // double minX, maxX, minY, maxY;
1009 
1010  // // Search for minX between minlat and maxlat along longitude discontinuities
1011  // doSearch(MinimumLatitude(), MaximumLatitude(),
1012  // minX, specialLonCases[specialLonCase], true, true, true);
1013  // // Search for minY between minlat and maxlat along longitude discontinuities
1014  // doSearch(MinimumLatitude(), MaximumLatitude(),
1015  // minY, specialLonCases[specialLonCase], false, true, true);
1016  // // Search for maxX between minlat and maxlat along longitude discontinuities
1017  // doSearch(MinimumLatitude(), MaximumLatitude(),
1018  // maxX, specialLonCases[specialLonCase], true, true, false);
1019  // // Search for maxY between minlat and maxlat along longitude discontinuities
1020  // doSearch(MinimumLatitude(), MaximumLatitude(),
1021  // maxY, specialLonCases[specialLonCase], false, true, false);
1022 
1023  // m_minimumX = min(minX, m_minimumX);
1024  // m_maximumX = max(maxX, m_maximumX);
1025  // m_minimumY = min(minY, m_minimumY);
1026  // m_maximumY = max(maxY, m_maximumY);
1027  // }
1028 
1029  // m_specialLatCases.clear();
1030  // m_specialLonCases.clear();
1031 
1032  // // Make sure everything is ordered
1033  // if (m_minimumX >= m_maximumX) return false;
1034  // if (m_minimumY >= m_maximumY) return false;
1035 
1036  // // Return X/Y min/maxs
1037  // minX = m_minimumX;
1038  // maxX = m_maximumX;
1039  // minY = m_minimumY;
1040  // maxY = m_maximumY;
1041 
1042  // return true;
1043  // }
1044 
1082  // void Projection::doSearch(double minBorder, double maxBorder,
1083  // double &extremeVal, const double constBorder,
1084  // bool searchX, bool searchLongitude, bool findMin) {
1085  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1086  // return;
1087  // }
1088  // const double TOLERANCE = m_pixelResolution/2;
1089  // const int NUM_ATTEMPTS = (unsigned int)DBL_DIG; // It's unsafe to go past
1090  // // this precision
1091 
1092  // double minBorderX, minBorderY, maxBorderX, maxBorderY;
1093  // int attempts = 0;
1094 
1095  // do {
1096  // findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
1097  // maxBorderY, constBorder, searchX, searchLongitude, findMin);
1098  // if (minBorderX == Null && maxBorderX == Null
1099  // && minBorderY == Null && maxBorderY == Null ) {
1100  // attempts = NUM_ATTEMPTS;
1101  // continue;
1102  // }
1103  // attempts ++;
1104  // }
1105  // while ((fabs(minBorderX - maxBorderX) > TOLERANCE
1106  // || fabs(minBorderY - maxBorderY) > TOLERANCE)
1107  // && (attempts < NUM_ATTEMPTS));
1108  // // check both x and y distance in case symmetry of map
1109  // // For example, if minBorderX = maxBorderX but minBorderY = -maxBorderY,
1110  // // these points may not be close enough.
1111 
1112  // if (attempts >= NUM_ATTEMPTS) {
1113  // // We zoomed in on a discontinuity because our range never shrank, this
1114  // // will need to be rechecked later.
1115  // // *min and max border should be nearly identical, so it doesn't matter
1116  // // which is used here
1117  // if (searchLongitude) {
1118  // m_specialLatCases.push_back(minBorder);
1119  // }
1120  // else {
1121  // m_specialLonCases.push_back(minBorder);
1122  // }
1123  // }
1124 
1125  // // These values will always be accurate, even over a discontinuity
1126  // if (findMin) {
1127  // if (searchX) extremeVal = min(minBorderX, maxBorderX);
1128  // else extremeVal = min(minBorderY, maxBorderY);
1129  // }
1130  // else {
1131  // if (searchX) extremeVal = max(minBorderX, maxBorderX);
1132  // else extremeVal = max(minBorderY, maxBorderY);
1133  // }
1134  // return;
1135  // }
1136 
1196  // void Projection::findExtreme(double &minBorder, double &maxBorder,
1197  // double &minBorderX, double &minBorderY,
1198  // double &maxBorderX, double &maxBorderY,
1199  // const double constBorder, bool searchX,
1200  // bool searchLongitude, bool findMin) {
1201  // if (minBorder == Null || maxBorder == Null || constBorder == Null) {
1202  // minBorderX = Null;
1203  // minBorderY = minBorderX;
1204  // minBorderX = minBorderX;
1205  // minBorderY = minBorderX;
1206  // return;
1207  // }
1208  // if (!searchLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1209  // // it is impossible to search "along" a pole
1210  // setSearchGround(minBorder, constBorder, searchLongitude);
1211  // minBorderX = XCoord();
1212  // minBorderY = YCoord();
1213  // maxBorderX = minBorderX;
1214  // maxBorderY = minBorderY;
1215  // return;
1216  // }
1217  // // Always do 10 steps
1218  // const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1219  // const double LOOP_END = maxBorder + (STEP_SIZE / 2.0); // This ensures we do
1220  // // all of the steps
1221  // // properly
1222  // double currBorderVal = minBorder;
1223  // setSearchGround(minBorder, constBorder, searchLongitude);
1224 
1225  // // this makes sure that the initial currBorderVal is valid before entering
1226  // // the loop below
1227  // if (!m_good){
1228  // // minBorder = currBorderVal+STEP_SIZE < LOOP_END until setGround is good?
1229  // // then, if still not good return?
1230  // while (!m_good && currBorderVal <= LOOP_END) {
1231  // currBorderVal+=STEP_SIZE;
1232  // if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1233  // currBorderVal = 90.0;
1234  // }
1235  // setSearchGround(currBorderVal, constBorder, searchLongitude);
1236  // }
1237  // if (!m_good) {
1238  // minBorderX = Null;
1239  // minBorderY = minBorderX;
1240  // minBorderX = minBorderX;
1241  // minBorderY = minBorderX;
1242  // return;
1243  // }
1244  // }
1245 
1246  // // save the values of three consecutive steps from the minBorder towards
1247  // // the maxBorder along the constBorder. initialize these three border
1248  // // values (the non-constant lat or lon)
1249  // double border1 = currBorderVal;
1250  // double border2 = currBorderVal;
1251  // double border3 = currBorderVal;
1252 
1253  // // save the coordinate (x or y) values that correspond to the first
1254  // // two borders that are being saved.
1255  // // initialize these two coordinate values (x or y)
1256  // double value1 = (searchX) ? XCoord() : YCoord();
1257  // double value2 = value1;
1258 
1259  // // initialize the extreme coordinate value
1260  // // -- this is the largest coordinate value found so far
1261  // double extremeVal2 = value2;
1262 
1263  // // initialize the extreme border values
1264  // // -- these are the borders on either side of the extreme coordinate value
1265  // double extremeBorder1 = minBorder;
1266  // double extremeBorder3 = minBorder;
1267 
1268  // while (currBorderVal <= LOOP_END) {
1269 
1270  // // this conditional was added to prevent trying to SetGround with an
1271  // // invalid latitude greater than 90 degrees. There is no need check for
1272  // // latitude less than -90 since we start at the minBorder (already
1273  // // assumed to be valid) and step forward toward (and possibly past)
1274  // // maxBorder
1275  // if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1276  // currBorderVal = 90.0;
1277  // }
1278 
1279  // // update the current border value along constBorder
1280  // currBorderVal += STEP_SIZE;
1281  // setSearchGround(currBorderVal, constBorder, searchLongitude);
1282  // if (!m_good){
1283  // continue;
1284  // }
1285 
1286  // // update the border and coordinate values
1287  // border3 = border2;
1288  // border2 = border1;
1289  // border1 = currBorderVal;
1290  // value2 = value1;
1291  // value1 = (searchX) ? XCoord() : YCoord();
1292 
1293  // if ((findMin && value2 < extremeVal2)
1294  // || (!findMin && value2 > extremeVal2)) {
1295  // // Compare the coordinate value associated with the center border with
1296  // // the current extreme. If the updated coordinate value is more extreme
1297  // // (smaller or larger, depending on findMin), then we update the
1298  // // extremeVal and it's borders.
1299  // extremeVal2 = value2;
1300 
1301  // extremeBorder3 = border3;
1302  // extremeBorder1 = border1;
1303  // }
1304  // }
1305 
1306  // // update min/max border values to the values on either side of the most
1307  // // extreme coordinate found in this call to this method
1308 
1309  // minBorder = extremeBorder3; // Border 3 is lagging and thus smaller
1310 
1311  // // since the loop steps past the original maxBorder, we want to retain
1312  // // the original maxBorder value so we don't go outside of the original
1313  // // min/max range given
1314  // if (extremeBorder1 <= maxBorder ) {
1315  // maxBorder = extremeBorder1; // Border 1 is leading and thus larger
1316  // }
1317 
1318  // // update minBorder coordinate values
1319  // setSearchGround(minBorder, constBorder, searchLongitude);
1320  // // if (!m_good){
1321  // // this should not happen since minBorder has already been verified in
1322  // // the while loop above
1323  // // }
1324 
1325  // minBorderX = XCoord();
1326  // minBorderY = YCoord();
1327 
1328  // // update maxBorder coordinate values
1329  // setSearchGround(maxBorder, constBorder, searchLongitude);
1330  // // if (!m_good){
1331  // // this should not happen since maxBorder has already been verified in
1332  // // the while loop above
1333  // // }
1334 
1335  // maxBorderX = XCoord();
1336  // maxBorderY = YCoord();
1337  // return;
1338  // }
1339 
1362  // void Projection::setSearchGround(const double variableBorder,
1363  // const double constBorder,
1364  // bool variableIsLat) {
1365  // if (variableBorder == Null || constBorder == Null) {
1366  // return;
1367  // }
1368  // double lat, lon;
1369  // if (variableIsLat) {
1370  // lat = variableBorder;
1371  // lon = constBorder;
1372  // }
1373  // else {
1374  // lat = constBorder;
1375  // lon = variableBorder;
1376  // }
1377  // SetGround(lat, lon);
1378  // return;
1379  // }
1380 
1389  const Displacement &y) {
1390  PvlKeyword xKeyword("UpperLeftCornerX", toString(x.meters()), "meters");
1391  PvlKeyword yKeyword("UpperLeftCornerY", toString(y.meters()), "meters");
1392  m_mappingGrp.addKeyword(xKeyword,Pvl::Replace);
1393  m_mappingGrp.addKeyword(yKeyword,Pvl::Replace);
1394  }
1395 } //end namespace isis
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 m_y
This contains the rotated Y coordinate for a specific projection at the position indicated by m_latit...
Definition: Projection.h:355
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
Definition: Projection.h:308
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
bool SetUniversalGround(const double lat, const double lon)
This method is used to set the latitude/longitude which must be Planetocentric (latitude) and Positiv...
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
const double PI
The mathematical constant PI.
Definition: Constants.h:56
bool m_sky
Indicates whether projection is sky or land.
Definition: Projection.h:326
virtual double ProjectionY(const double worldY) const =0
This pure virtual method will return a projection Y coordinate in meters given a world Y coordinate...
double m_x
This contains the rotated X coordinate for a specific projection at theposition indicated by m_latitu...
Definition: Projection.h:351
bool operator!=(const Projection &proj)
This method determines whether two map projection objects are not equal.
Definition: Projection.cpp:193
Base class for Map TProjections.
Definition: TProjection.h:182
double Rotation() const
Returns the value of the Rotation keyword from the mapping group.
Definition: Projection.cpp:374
double ToProjectionX(const double worldX) const
This method converts a world x value to a projection x value.
Definition: Projection.cpp:637
double meters() const
Get the displacement in meters.
double PixelResolution() const
Returns the pixel resolution value from the PVL mapping group in meters/pixel.
Definition: Projection.cpp:855
Namespace for the standard library.
virtual bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
Definition: Projection.cpp:461
void SetWorldMapper(WorldMapper *mapper)
If desired the programmer can use this method to set a world mapper to be used in the SetWorld...
Definition: Projection.cpp:489
Search child objects.
Definition: PvlObject.h:170
double GetX() const
Calculates the unrotated form of current x value.
Definition: Projection.cpp:833
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
Definition: Projection.cpp:690
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
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
static QString ToHMS(double angle)
Converts the given angle (in degrees) to hours, minutes, seconds.
Definition: Projection.cpp:756
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
double m_rotation
Rotation of map (usually zero)
Definition: Projection.h:349
double m_maximumY
See minimumX description.
Definition: Projection.h:344
virtual ~Projection()
Destroys the Projection object.
Definition: Projection.cpp:163
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:539
double ToWorldX(const double projectionX) const
This method converts a projection x value to a world x value.
Definition: Projection.cpp:581
Base class for Map Projections.
Definition: Projection.h:171
double m_minimumY
See minimumX description.
Definition: Projection.h:343
bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
Definition: Projection.cpp:364
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
bool IsSky() const
Returns true if projection is sky and false if it is land.
Definition: Projection.cpp:223
double ToProjectionY(const double worldY) const
This method converts a world y value to a projection y value.
Definition: Projection.cpp:665
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:415
Container for cube-like labels.
Definition: Pvl.h:135
void SetUpperLeftCorner(const Displacement &x, const Displacement &y)
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
Definition: Projection.h:316
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:512
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Base class for Map Projections of plane shapes.
Create a mapping between a projection and other coordinate system.
Definition: WorldMapper.h:54
double m_pixelResolution
Pixel resolution value from the PVL mapping group, in meters/pixel.
Definition: Projection.h:360
virtual bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the resolution...
Definition: Projection.cpp:177
static QString ToDMS(double angle)
Converts the given angle (in degrees) to degrees, minutes, seconds.
Definition: Projection.cpp:721
Displacement is a signed length, usually in meters.
Definition: Displacement.h:43
virtual double WorldX(const double projectionX) const =0
This pure virtual method will return a world X coordinate given a projection Y coordinate in meters...
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
Definition: Projection.cpp:432
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
static double ToHours(double angle)
Converts the given angle (in degrees) to hours by using the ratio 15 degrees per hour.
Definition: Projection.cpp:708
double ToWorldY(const double projectionY) const
This method converts a projection y value to a world y value.
Definition: Projection.cpp:609
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...
double GetY() const
Calculates the unrotated form of the current y value.
Definition: Projection.cpp:844
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
virtual bool IsEquatorialCylindrical()
This method returns true if the projection is equatorial cylindrical.
Definition: Projection.cpp:237
virtual double ProjectionX(const double worldX) const =0
This pure virtual method will return a projection X coordinate in meters given a world X coordinate...
virtual double WorldY(const double projectionY) const =0
This pure virtual method will return a world Y coordinate given a projection Y coordinate in meters...
bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the latitude/longitude.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
Definition: Projection.h:182
virtual QString Name() const =0
This method returns the name of the map projection.
double m_maximumX
See minimumX description.
Definition: Projection.h:342
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:559
PvlGroup m_mappingGrp
Mapping group that created this projection.
Definition: Projection.h:345
These projections are used to map triaxial and irregular-shaped bodies.
Definition: Projection.h:182