Isis 3 Programmer Reference
Camera.cpp
Go to the documentation of this file.
1 
23 #include "Camera.h"
24 
25 
26 #include <algorithm>
27 #include <cfloat>
28 #include <cmath>
29 #include <iomanip>
30 #include <stdint.h>
31 
32 #include <QDebug>
33 #include <QList>
34 #include <QPair>
35 #include <QString>
36 #include <QTime>
37 #include <QVector>
38 
39 #include "Angle.h"
40 #include "Constants.h"
41 #include "CameraDetectorMap.h"
42 #include "CameraFocalPlaneMap.h"
43 #include "CameraDistortionMap.h"
44 #include "CameraGroundMap.h"
45 #include "CameraSkyMap.h"
46 #include "DemShape.h"
47 #include "IException.h"
48 #include "IString.h"
49 #include "iTime.h"
50 #include "Latitude.h"
51 #include "Longitude.h"
52 #include "NaifStatus.h"
53 #include "Projection.h"
54 #include "ProjectionFactory.h"
55 #include "RingPlaneProjection.h"
56 #include "ShapeModel.h"
57 #include "SpecialPixel.h"
58 #include "SurfacePoint.h"
59 #include "Target.h"
60 #include "TProjection.h"
61 
62 using namespace std;
63 
64 namespace Isis {
65 
70  Camera::Camera(Cube &cube) : Sensor(cube) {
71 
72  m_instrumentId = cube.label()->findGroup("Instrument",
73  PvlObject::FindOptions::Traverse).findKeyword("InstrumentId")[0];
74 
75  m_instrumentNameLong = "Unknown";
76  m_instrumentNameShort = "Unknown";
77  m_spacecraftNameLong = "Unknown";
78  m_spacecraftNameShort = "Unknown";
79  // Get the image size which can be different than the alpha cube size
80  p_lines = cube.lineCount();
81  p_samples = cube.sampleCount();
82  p_bands = cube.bandCount();
83 
85 
86  // Get the AlphaCube information
87  p_alphaCube = new AlphaCube(cube);
88 
89  // Get the projection group if it exists
90  Pvl &lab = *cube.label();
91  if (lab.findObject("IsisCube").hasGroup("Mapping")) {
93  }
94  else {
95  p_projection = NULL;
96  }
97  p_ignoreProjection = false;
98 
99  // Initialize stuff
100  p_focalLength = 0.0;
101  p_pixelPitch = 1.0;
102  p_referenceBand = 0;
103  p_childBand = 1;
104 
105  p_distortionMap = NULL;
106  p_focalPlaneMap = NULL;
107  p_detectorMap = NULL;
108  p_groundMap = NULL;
109  p_skyMap = NULL;
110 
111  // See if we have a reference band
112  PvlGroup &inst = lab.findObject("IsisCube").findGroup("Instrument");
113  if (inst.hasKeyword("ReferenceBand")) {
114  p_referenceBand = inst["ReferenceBand"];
115  }
116 
117  p_groundRangeComputed = false;
118  p_raDecRangeComputed = false;
119  p_ringRangeComputed = false;
120  p_pointComputed = false;
121  }
122 
125  if (p_projection) {
126  delete p_projection;
127  p_projection = NULL;
128  }
129 
130  if (p_alphaCube) {
131  delete p_alphaCube;
132  p_alphaCube = NULL;
133  }
134 
135  if (p_distortionMap) {
136  delete p_distortionMap;
137  p_distortionMap = NULL;
138  }
139 
140  if (p_focalPlaneMap) {
141  delete p_focalPlaneMap;
142  p_focalPlaneMap = NULL;
143  }
144 
145  if (p_detectorMap) {
146  delete p_detectorMap;
147  p_detectorMap = NULL;
148  }
149 
150  if (p_groundMap) {
151  delete p_groundMap;
152  p_groundMap = NULL;
153  }
154 
155  if (p_skyMap) {
156  delete p_skyMap;
157  p_skyMap = NULL;
158  }
159  }
160 
161 
170  bool Camera::SetImage(const double sample, const double line) {
171  p_childSample = sample;
172  p_childLine = line;
173  p_pointComputed = true;
174 
175  // get shape
176  // TODO: we need to validate this pointer (somewhere)
177  ShapeModel *shape = target()->shape();
178  shape->clearSurfacePoint(); // Set initial condition for ShapeModel
179 
180  // Case of no map projection
181  if (p_projection == NULL || p_ignoreProjection) {
182  // Convert to parent coordinate (remove crop, pad, shrink, enlarge)
183  double parentSample = p_alphaCube->AlphaSample(sample);
184  double parentLine = p_alphaCube->AlphaLine(line);
185  bool success = false;
186  success = p_detectorMap->SetParent(parentSample, parentLine);
187  // Convert from parent to detector
188  if (success) {
189  double detectorSample = p_detectorMap->DetectorSample();
190  double detectorLine = p_detectorMap->DetectorLine();
191  success = p_focalPlaneMap->SetDetector(detectorSample, detectorLine);
192  // Now Convert from detector to distorted focal plane
193  if (success) {
194  double focalPlaneX = p_focalPlaneMap->FocalPlaneX();
195  double focalPlaneY = p_focalPlaneMap->FocalPlaneY();
196  success = p_distortionMap->SetFocalPlane(focalPlaneX, focalPlaneY);
197  // Remove optical distortion
198  if (success) {
199  // Map to the ground
203  return p_groundMap->SetFocalPlane(x, y, z);
204  }
205  }
206  }
207  }
208 
209  // The projection is a sky map
210  else if (p_projection->IsSky()) {
211  return SetImageSkyMapProjection(sample, line, shape);
212  }
213 
214  // We have map projected camera model
215  else {
216  return SetImageMapProjection(sample, line, shape);
217  }
218 
219  // failure
220  shape->clearSurfacePoint();
221  return false;
222  }
223 
224 
244  bool Camera::SetImage(const double sample, const double line, const double deltaT) {
245  p_childSample = sample;
246  p_childLine = line;
247  p_pointComputed = true;
248 
249  // get shape
250  // TODO: we need to validate this pointer (somewhere)
251  ShapeModel *shape = target()->shape();
252  shape->clearSurfacePoint(); // Set initial condition for ShapeModel
253 
254  // Case of no map projection
255  if (p_projection == NULL || p_ignoreProjection) {
256  // Convert to parent coordinate (remove crop, pad, shrink, enlarge)
257  double parentSample = p_alphaCube->AlphaSample(sample);
258  double parentLine = p_alphaCube->AlphaLine(line);
259  bool success = false;
260  success = p_detectorMap->SetParent(parentSample, parentLine, deltaT);
261  // Convert from parent to detector
262  if (success) {
263  double detectorSample = p_detectorMap->DetectorSample();
264  double detectorLine = p_detectorMap->DetectorLine();
265  success = p_focalPlaneMap->SetDetector(detectorSample, detectorLine);
266  // Now Convert from detector to distorted focal plane
267  if (success) {
268  double focalPlaneX = p_focalPlaneMap->FocalPlaneX();
269  double focalPlaneY = p_focalPlaneMap->FocalPlaneY();
270  success = p_distortionMap->SetFocalPlane(focalPlaneX, focalPlaneY);
271  // Remove optical distortion
272  if (success) {
273  // Map to the ground
277  return p_groundMap->SetFocalPlane(x, y, z);
278  }
279  }
280  }
281  }
282 
283  // The projection is a sky map
284  else if (p_projection->IsSky()) {
285  return SetImageSkyMapProjection(sample, line, shape);
286  }
287 
288  // We have map projected camera model
289  else {
290  return SetImageMapProjection(sample, line, shape);
291  }
292 
293  // failure
294  shape->clearSurfacePoint();
295  return false;
296  }
297 
298 
310  bool Camera::SetImageMapProjection(const double sample, const double line, ShapeModel *shape) {
311  Latitude lat;
312  Longitude lon;
313  Distance rad;
314  if (shape->name() != "Plane") { // this is the normal behavior
315  if (p_projection->SetWorld(sample, line)) {
316  TProjection *tproj = (TProjection *) p_projection;
317  lat = Latitude(tproj->UniversalLatitude(), Angle::Degrees);
319  rad = Distance(LocalRadius(lat, lon));
320  if (!rad.isValid()) {
321  shape->setHasIntersection(false);
322  return false;
323  }
324  SurfacePoint surfPt(lat, lon, rad);
325  if (SetGround(surfPt)) {
326  p_childSample = sample;
327  p_childLine = line;
328 
329  shape->setHasIntersection(true);
330  return true;
331  }
332  }
333  }
334  else { // shape is ring plane
335  if (p_projection->SetWorld(sample, line)) {
337  lat = Latitude(0.0, Angle::Degrees);
340 
341  if (!rad.isValid()) {
342  shape->setHasIntersection(false);
343  return false;
344  }
345  SurfacePoint surfPt(lat, lon, rad);
346  if (SetGround(surfPt)) {
347  p_childSample = sample;
348  p_childLine = line;
349 
350  shape->setHasIntersection(true);
351  return true;
352  }
353  }
354  }
355  shape->clearSurfacePoint();
356  return false;
357  }
358 
359 
371  bool Camera::SetImageSkyMapProjection(const double sample, const double line, ShapeModel *shape) {
372  TProjection *tproj = (TProjection *) p_projection;
373  if (tproj->SetWorld(sample, line)) {
375  tproj->UniversalLatitude())) {
376  p_childSample = sample;
377  p_childLine = line;
378 
379  return HasSurfaceIntersection();
380  }
381  }
382  shape->clearSurfacePoint();
383  return false;
384  }
385 
386 
396  bool Camera::SetUniversalGround(const double latitude, const double longitude) {
397  // Convert lat/lon or rad/az (i.e. ring rad / ring lon) to undistorted focal plane x/y
399  Longitude(longitude, Angle::Degrees))) {
400  return RawFocalPlanetoImage();
401  }
402 
404  return false;
405  }
406 
407 
417  bool Camera::SetGround(Latitude latitude, Longitude longitude) {
418  ShapeModel *shape = target()->shape();
419  Distance localRadius;
420 
421  if (shape->name() != "Plane") { // this is the normal behavior
422  localRadius = LocalRadius(latitude, longitude);
423  }
424  else {
425  localRadius = Distance(latitude.degrees(),Distance::Kilometers);
426  latitude = Latitude(0.,Angle::Degrees);
427  }
428 
429  if (!localRadius.isValid()) {
431  return false;
432  }
433 
434  return SetGround(SurfacePoint(latitude, longitude, localRadius));
435  }
436 
437 
438 
447  bool Camera::SetGround(const SurfacePoint & surfacePt) {
448  ShapeModel *shape = target()->shape();
449  if (!surfacePt.Valid()) {
450  shape->clearSurfacePoint();
451  return false;
452  }
453 
454  // Convert lat/lon to undistorted focal plane x/y
455  if (p_groundMap->SetGround(surfacePt)) {
456  return RawFocalPlanetoImage();
457  }
458 
459  shape->clearSurfacePoint();
460  return false;
461  }
462 
463 
472  double ux = p_groundMap->FocalPlaneX();
473  double uy = p_groundMap->FocalPlaneY();
474 
475  // get shape
476  // TODO: we need to validate this pointer (somewhere)
477  ShapeModel *shape = target()->shape();
478 
479  //cout << "undistorted focal plane: " << ux << " " << uy << endl; //debug
480  //cout.precision(15);
481  //cout << "Backward Time: " << Time().Et() << endl;
482  // Convert undistorted x/y to distorted x/y
483  bool success = p_distortionMap->SetUndistortedFocalPlane(ux, uy);
484  if (success) {
485  double focalPlaneX = p_distortionMap->FocalPlaneX();
486  double focalPlaneY = p_distortionMap->FocalPlaneY();
487  //cout << "focal plane: " << focalPlaneX << " " << focalPlaneY << endl; //debug
488  // Convert distorted x/y to detector position
489  success = p_focalPlaneMap->SetFocalPlane(focalPlaneX, focalPlaneY);
490  if (success) {
491  double detectorSample = p_focalPlaneMap->DetectorSample();
492  double detectorLine = p_focalPlaneMap->DetectorLine();
493  //cout << "detector: " << detectorSample << " " << detectorLine << endl;
494  // Convert detector to parent position
495  success = p_detectorMap->SetDetector(detectorSample, detectorLine);
496  if (success) {
497  double parentSample = p_detectorMap->ParentSample();
498  double parentLine = p_detectorMap->ParentLine();
499  //cout << "cube: " << parentSample << " " << parentLine << endl; //debug
500  if (p_projection == NULL || p_ignoreProjection) {
501  p_childSample = p_alphaCube->BetaSample(parentSample);
502  p_childLine = p_alphaCube->BetaLine(parentLine);
503  p_pointComputed = true;
504  shape->setHasIntersection(true);
505  return true;
506  }
507  else if (p_projection->IsSky()) {
508  if (p_projection->SetGround(Declination(), RightAscension())) {
511  p_pointComputed = true;
512  shape->setHasIntersection(true);
513  return true;
514  }
515  }
520  p_pointComputed = true;
521  shape->setHasIntersection(true);
522  return true;
523  }
524  }
525  else { // ring plane
526  // UniversalLongitude should return azimuth (ring longitude) in this case
527  // TODO:
528  // when we make the change to real azimuths this value may need to be adjusted or
529  // code changed in the shapemodel or surfacepoint class.
533  p_pointComputed = true;
534  shape->setHasIntersection(true);
535  return true;
536  }
537  }
538  }
539  }
540  }
541 
542  shape->clearSurfacePoint();
543  return false;
544  }
545 
546 
547 
558  bool Camera::SetUniversalGround(const double latitude, const double longitude,
559  const double radius) {
560  // Convert lat/lon to undistorted focal plane x/y
562  Longitude(longitude, Angle::Degrees),
563  Distance(radius, Distance::Meters)))) {
564  return RawFocalPlanetoImage(); // sets p_hasIntersection
565  }
566 
568  return false;
569  }
570 
571 
572 
599 
600 
602 
603  double thetaRad;
604  thetaRad = EmissionAngle()*DEG2RAD;
605 
606  if (thetaRad < HALFPI) {
607  return DetectorResolution()/cos(thetaRad);
608 
609  }
610  return Isis::Null;
611 
612  }
613 
614  return Isis::Null;
615 
616  }
617 
618 
625  if (HasSurfaceIntersection()) {
626  double sB[3];
627  instrumentPosition(sB);
628  double pB[3];
629  Coordinate(pB);
630  double a = sB[0] - pB[0];
631  double b = sB[1] - pB[1];
632  double c = sB[2] - pB[2];
633  double dist = sqrt(a * a + b * b + c * c) * 1000.0;
634  return dist / (p_focalLength / p_pixelPitch);
635  }
636  return Isis::Null;
637  }
638 
639 
646 
648  }
649 
657 
659  }
660 
661 
669  }
670 
671 
680 
682  }
683 
684 
690  double lineRes = LineResolution();
691  double sampRes = SampleResolution();
692  if (lineRes < 0.0) return Isis::Null;
693  if (sampRes < 0.0) return Isis::Null;
694  return (lineRes + sampRes) / 2.0;
695  }
696 
697 
705  double lineRes = ObliqueLineResolution();
706  double sampRes = ObliqueSampleResolution();
707  if (lineRes < 0.0) return Isis::Null;
708  if (sampRes < 0.0) return Isis::Null;
709  return (lineRes + sampRes) / 2.0;
710  }
711 
712 
720  return p_maxres;
721  }
722 
723 
731  return p_minres;
732  }
733 
734 
742  return p_minobliqueres;
743  }
744 
745 
753  return p_maxobliqueres;
754  }
755 
756 
761  // Software adjustment is needed if we get here -- call RingRangeResolution instead
762  if (target()->shape()->name() == "Plane") {
763  IString msg = "Images with plane targets should use Camera method RingRangeResolution ";
764  msg += "instead of GroundRangeResolution";
766  }
767 
768  // Have we already done this
769  if (p_groundRangeComputed) return;
770  p_groundRangeComputed = true;
771 
772  bool computed = p_pointComputed;
773  double originalSample = Sample();
774  double originalLine = Line();
775  int originalBand = Band();
776 
777  // Initializations
778  p_minlat = DBL_MAX;
779  p_minlon = DBL_MAX;
780  p_minlon180 = DBL_MAX;
781  p_maxlat = -DBL_MAX;
782  p_maxlon = -DBL_MAX;
783  p_maxlon180 = -DBL_MAX;
784  p_minres = DBL_MAX;
785  p_maxres = -DBL_MAX;
786  p_minobliqueres = DBL_MAX;
787  p_maxobliqueres = -DBL_MAX;
788 
789  // See if we have band dependence and loop for the appropriate number of bands
790  int eband = p_bands;
791  if (IsBandIndependent()) eband = 1;
792  for (int band = 1; band <= eband; band++) {
793  SetBand(band);
794 
795  // Loop for each line testing the left and right sides of the image
796  for (int line = 1; line <= p_lines + 1; line++) {
797  // Look for the first good lat/lon on the left edge of the image
798  // If it is the first or last line then test the whole line
799  int samp;
800  for (samp = 1; samp <= p_samples + 1; samp++) {
801 
802  if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
803  double lat = UniversalLatitude();
804  double lon = UniversalLongitude();
805  if (lat < p_minlat) p_minlat = lat;
806  if (lat > p_maxlat) p_maxlat = lat;
807  if (lon < p_minlon) p_minlon = lon;
808  if (lon > p_maxlon) p_maxlon = lon;
809 
810  if (lon > 180.0) lon -= 360.0;
811  if (lon < p_minlon180) p_minlon180 = lon;
812  if (lon > p_maxlon180) p_maxlon180 = lon;
813 
814  double res = PixelResolution();
815  if (res > 0.0) {
816  if (res < p_minres) p_minres = res;
817  if (res > p_maxres) p_maxres = res;
818  }
819  // Determine min/max oblique resolution
820  double obliqueres = ObliquePixelResolution();
821  if (obliqueres > 0.0) {
822  if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
823  if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
824 
825  }
826  if ((line != 1) && (line != p_lines + 1)) break;
827  }
828  } // end loop through samples
829 
830  //We've already checked the first and last lines.
831  if (line == 1) continue;
832  if (line == p_lines + 1) continue;
833 
834  // Look for the first good lat/lon on the right edge of the image
835  if (samp < p_samples + 1) {
836  for (samp = p_samples + 1; samp >= 1; samp--) {
837  if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
838  double lat = UniversalLatitude();
839  double lon = UniversalLongitude();
840  if (lat < p_minlat) p_minlat = lat;
841  if (lat > p_maxlat) p_maxlat = lat;
842  if (lon < p_minlon) p_minlon = lon;
843  if (lon > p_maxlon) p_maxlon = lon;
844 
845  if (lon > 180.0) lon -= 360.0;
846  if (lon < p_minlon180) p_minlon180 = lon;
847  if (lon > p_maxlon180) p_maxlon180 = lon;
848 
849  double res = PixelResolution();
850  if (res > 0.0) {
851  if (res < p_minres) p_minres = res;
852  if (res > p_maxres) p_maxres = res;
853  }
854 
855  // Determine min/max oblique resolution
856  double obliqueres = ObliquePixelResolution();
857  if (obliqueres > 0.0) {
858  if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
859  if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
860 
861  }
862  break;
863  }
864  }
865  }
866  } // end loop through lines
867 
868  // Test at the sub-spacecraft point to see if we have a
869  // better resolution
870  double lat, lon;
871 
872  subSpacecraftPoint(lat, lon);
873  Latitude latitude(lat, Angle::Degrees);
874  Longitude longitude(lon, Angle::Degrees);
875  // get the local radius for the subspacecraft point
876  Distance radius(LocalRadius(latitude, longitude));
877  SurfacePoint testPoint;
878 
879  if (radius.isValid()) {
880 
881  testPoint = SurfacePoint(latitude, longitude, radius);
882 
883  if (SetGround(testPoint)) {
884  if (Sample() >= 0.5 && Line() >= 0.5 &&
885  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
886  double res = PixelResolution();
887  if (res > 0.0) {
888  if (res < p_minres) p_minres = res;
889  if (res > p_maxres) p_maxres = res;
890  }
891 
892  double obliqueres = ObliquePixelResolution();
893  if (obliqueres > 0.0) {
894  if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
895  if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
896 
897  }
898  }
899  }
900  } // end valid local (subspacecraft) radius
901 
902  // Special test for ground range to see if either pole is in the image
903  latitude = Latitude(90, Angle::Degrees);
904  longitude = Longitude(0.0, Angle::Degrees);
905  // get radius for north pole
906  radius = LocalRadius(latitude, longitude);
907 
908  if (radius.isValid()) {
909 
910  testPoint = SurfacePoint(latitude, longitude, radius);
911 
912  if (SetGround(testPoint)) {
913  if (Sample() >= 0.5 && Line() >= 0.5 &&
914  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
915  p_maxlat = 90.0;
916  p_minlon = 0.0;
917  p_maxlon = 360.0;
918  p_minlon180 = -180.0;
919  p_maxlon180 = 180.0;
920  }
921  }
922  } // end valid north polar radius
923 
924  latitude = Latitude(-90, Angle::Degrees);
925  // get radius for south pole
926  radius = LocalRadius(latitude, longitude);
927 
928  if (radius.isValid()) {
929 
930  testPoint = SurfacePoint(latitude, longitude, radius);
931  if (SetGround(testPoint)) {
932  if (Sample() >= 0.5 && Line() >= 0.5 &&
933  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
934  p_minlat = -90.0;
935  p_minlon = 0.0;
936  p_maxlon = 360.0;
937  p_minlon180 = -180.0;
938  p_maxlon180 = 180.0;
939  }
940  }
941  } // end valid south polar radius
942 
943  // Another special test for ground range as we could have the
944  // 0-360 seam running right through the image so
945  // test it as well (the increment may not be fine enough !!!)
948  lat += Angle((p_maxlat - p_minlat) / 10.0, Angle::Degrees)) {
949  if (SetGround(lat, Longitude(0.0, Angle::Degrees))) {
950  if (Sample() >= 0.5 && Line() >= 0.5 &&
951  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
952  p_minlon = 0.0;
953  p_maxlon = 360.0;
954  break;
955  }
956  } // end if set ground (lat, 0)
957 
958  // Another special test for ground range as we could have the
959  // -180-180 seam running right through the image so
960  // test it as well (the increment may not be fine enough !!!)
961  if (SetGround(lat, Longitude(180.0, Angle::Degrees))) {
962  if (Sample() >= 0.5 && Line() >= 0.5 &&
963  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
964  p_minlon180 = -180.0;
965  p_maxlon180 = 180.0;
966  break;
967  }
968  } // end if set ground (lat, 180)
969  } // end for loop (latitudes from min to max)
970  } // end for loop through bands
971 
972  SetBand(originalBand);
973 
974  if(computed) {
975  SetImage(originalSample, originalLine);
976  }
977  else {
978  p_pointComputed = false;
979  }
980 
981  if (p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX || p_maxlat == -DBL_MAX) {
982  string message = "Camera missed planet or SPICE data off.";
983  throw IException(IException::Unknown, message, _FILEINFO_);
984  }
985 
986 
987  // Checks for invalid lat/lon ranges
988 // if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX
989 // || p_maxlat == -DBL_MAX)
990 // {
991 // string message = "Camera missed planet or SPICE data off.";
992 // throw IException(IException::Unknown, message, _FILEINFO_);
993 // }
994  }
995 
996 
1002  // TODO Add test to make sure we have a ring plane image **
1003 
1004  // Have we already done this
1005  if (p_ringRangeComputed) return;
1006 
1007  p_ringRangeComputed = true;
1008 
1009  bool computed = p_pointComputed;
1010  double originalSample = Sample();
1011  double originalLine = Line();
1012  int originalBand = Band();
1013 
1014  // Initializations
1015  p_minRingRadius = DBL_MAX;
1016  p_minRingLongitude = DBL_MAX;
1017  p_minRingLongitude180 = DBL_MAX;
1018  p_maxRingRadius = -DBL_MAX;
1019  p_maxRingLongitude = -DBL_MAX;
1020  p_maxRingLongitude180 = -DBL_MAX;
1021  p_minres = DBL_MAX;
1022  p_maxres = -DBL_MAX;
1023 
1024  // See if we have band dependence and loop for the appropriate number of bands
1025  int eband = p_bands;
1026  if (IsBandIndependent())
1027  eband = 1;
1028 
1029  for (int band = 1; band <= eband; band++) {
1030  SetBand(band);
1031 
1032  // Loop for each line testing the left and right sides of the image
1033  for (int line = 1; line <= p_lines + 1; line++) {
1034 
1035  // Look for the first good radius/azimuth on the left edge of the image
1036  // If it is the first or last line then test the whole line
1037  int samp;
1038  for (samp = 1; samp <= p_samples + 1; samp++) {
1039 
1040  if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
1041  double radius = LocalRadius().meters();
1042  double azimuth = UniversalLongitude();
1043  if (radius < p_minRingRadius) p_minRingRadius = radius;
1044  if (radius > p_maxRingRadius) p_maxRingRadius = radius;
1045  if (azimuth < p_minRingLongitude) p_minRingLongitude = azimuth;
1046  if (azimuth > p_maxRingLongitude) p_maxRingLongitude = azimuth;
1047 
1048  if (azimuth > 180.0) azimuth -= 360.0;
1049  if (azimuth < p_minRingLongitude180) p_minRingLongitude180 = azimuth;
1050  if (azimuth > p_maxRingLongitude180) p_maxRingLongitude180 = azimuth;
1051 
1052  double res = PixelResolution();
1053  if (res > 0.0) {
1054  if (res < p_minres) p_minres = res;
1055  if (res > p_maxres) p_maxres = res;
1056  }
1057  if ((line != 1) && (line != p_lines + 1)) break;
1058  }
1059  }
1060  //We've already checked the first and last lines.
1061  if (line == 1) continue;
1062  if (line == p_lines + 1) continue;
1063 
1064  // Look for the first good rad/azimuth on the right edge of the image
1065  if (samp < p_samples + 1) {
1066  for(samp = p_samples + 1; samp >= 1; samp--) {
1067  if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
1068  double radius = LocalRadius().meters();
1069  double azimuth = UniversalLongitude();
1070  if (radius < p_minRingRadius) p_minRingRadius = radius;
1071  if (radius > p_maxRingRadius) p_maxRingRadius = radius;
1072  if (azimuth < p_minRingLongitude) p_minRingLongitude = azimuth;
1073  if (azimuth > p_maxRingLongitude) p_maxRingLongitude = azimuth;
1074 
1075  if (azimuth > 180.0) azimuth -= 360.0;
1076  if (azimuth < p_minRingLongitude180) p_minRingLongitude180 = azimuth;
1077  if (azimuth > p_maxRingLongitude180) p_maxRingLongitude180 = azimuth;
1078 
1079  double res = PixelResolution();
1080  if (res > 0.0) {
1081  if (res < p_minres) p_minres = res;
1082  if (res > p_maxres) p_maxres = res;
1083  }
1084  break;
1085  }
1086  }
1087  }
1088  }
1089 
1090  // Test at the sub-spacecraft point to see if we have a
1091  // better resolution
1092  // TODO: is there something to this analogous for ring images?
1093 // double rad, lon;
1094 
1095 // subSpacecraftPoint(lat, lon);
1096 // Latitude latitude(lat, Angle::Degrees);
1097 // Longitude longitude(lon, Angle::Degrees);
1098 // Distance radius(LocalRadius(latitude, longitude));
1099 // SurfacePoint testPoint;
1100 
1101 // if (radius.isValid()) {
1102 
1103 // testPoint = SurfacePoint(latitude, longitude, radius);
1104 
1105 // if(SetGround(testPoint)) {
1106 // if(Sample() >= 0.5 && Line() >= 0.5 &&
1107 // Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1108 // double res = PixelResolution();
1109 // if(res > 0.0) {
1110 // if(res < p_minres) p_minres = res;
1111 // if(res > p_maxres) p_maxres = res;
1112 // }
1113 // }
1114 // }
1115 // }
1116 
1117  // Another special test for ring range as we could have the
1118  // 0-360 seam running right through the image so
1119  // test it as well (the increment may not be fine enough !!!)
1122  radius += Distance((p_maxRingRadius - p_minRingRadius) / 10.0, Distance::Meters)) {
1124  if (Sample() >= 0.5 && Line() >= 0.5 &&
1125  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1126  p_minRingLongitude = 0.0;
1127  p_maxRingLongitude = 360.0;
1128  break;
1129  }
1130  }
1131 
1132  // for (Latitude lat = Latitude(p_minlat, Angle::Degrees);
1133  // lat <= Latitude(p_maxlat, Angle::Degrees);
1134  // lat += Angle((p_maxlat - p_minlat) / 10.0, Angle::Degrees)) {
1135  // if (SetGround(lat, Longitude(0.0, Angle::Degrees))) {
1136  // if (Sample() >= 0.5 && Line() >= 0.5 &&
1137  // Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1138  // p_minlon = 0.0;
1139  // p_maxlon = 360.0;
1140  // break;
1141  // }
1142  // }
1143 
1144  // Another special test for ring range as we could have the
1145  // -180-180 seam running right through the image so
1146  // test it as well (the increment may not be fine enough !!!)
1148  if (Sample() >= 0.5 && Line() >= 0.5 &&
1149  Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1150  p_minRingLongitude180 = -180.0;
1151  p_maxRingLongitude180 = 180.0;
1152  break;
1153  }
1154  }
1155  }
1156  } // end loop over bands
1157 
1158  SetBand(originalBand);
1159 
1160  if (computed) {
1161  SetImage(originalSample, originalLine);
1162  }
1163  else {
1164  p_pointComputed = false;
1165  }
1166 
1167  // Checks for invalid radius/lon ranges
1168  if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX
1169  || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) {
1170  string message = "RingPlane ShapeModel - Camera missed plane or SPICE data off.";
1171  throw IException(IException::Unknown, message, _FILEINFO_);
1172  }
1173  }
1174 
1175 
1185  double minlat, minlon, maxlat, maxlon;
1186  return GroundRange(minlat, maxlat, minlon, maxlon, pvl);
1187  }
1188 
1201  bool Camera::GroundRange(double &minlat, double &maxlat,
1202  double &minlon, double &maxlon,
1203  Pvl &pvl) {
1204  // Compute the ground range and resolution
1206 
1207  // Get the default radii
1208  Distance localRadii[3];
1209  radii(localRadii);
1210  Distance &a = localRadii[0];
1211  Distance &b = localRadii[2];
1212 
1213  // See if the PVL overrides the radii
1214  PvlGroup map = pvl.findGroup("Mapping", Pvl::Traverse);
1215 
1216  if(map.hasKeyword("EquatorialRadius"))
1217  a = Distance(toDouble(map["EquatorialRadius"][0]), Distance::Meters);
1218 
1219  if(map.hasKeyword("PolarRadius"))
1220  b = Distance(toDouble(map["PolarRadius"][0]), Distance::Meters);
1221 
1222  // Convert to planetographic if necessary
1223  minlat = p_minlat;
1224  maxlat = p_maxlat;
1225  if(map.hasKeyword("LatitudeType")) {
1226  QString latType = (QString) map["LatitudeType"];
1227  if (latType.toUpper() == "PLANETOGRAPHIC") {
1228  if (abs(minlat) < 90.0) { // So tan doesn't fail
1229  minlat *= PI / 180.0;
1230  minlat = atan(tan(minlat) * (a / b) * (a / b));
1231  minlat *= 180.0 / PI;
1232  }
1233 
1234  if(abs(maxlat) < 90.0) { // So tan doesn't fail
1235  maxlat *= PI / 180.0;
1236  maxlat = atan(tan(maxlat) * (a / b) * (a / b));
1237  maxlat *= 180.0 / PI;
1238  }
1239  }
1240  }
1241 
1242  // Assume 0 to 360 domain but change it if necessary
1243  minlon = p_minlon;
1244  maxlon = p_maxlon;
1245  bool domain360 = true;
1246  if(map.hasKeyword("LongitudeDomain")) {
1247  QString lonDomain = (QString) map["LongitudeDomain"];
1248  if(lonDomain.toUpper() == "180") {
1249  minlon = p_minlon180;
1250  maxlon = p_maxlon180;
1251  domain360 = false;
1252  }
1253  }
1254 
1255  // Convert to the proper longitude direction
1256  if(map.hasKeyword("LongitudeDirection")) {
1257  QString lonDirection = (QString) map["LongitudeDirection"];
1258  if(lonDirection.toUpper() == "POSITIVEWEST") {
1259  double swap = minlon;
1260  minlon = -maxlon;
1261  maxlon = -swap;
1262  }
1263  }
1264 
1265  // Convert to the proper longitude domain
1266  if(domain360) {
1267  while(minlon < 0.0) {
1268  minlon += 360.0;
1269  maxlon += 360.0;
1270  }
1271  while(minlon > 360.0) {
1272  minlon -= 360.0;
1273  maxlon -= 360.0;
1274  }
1275  }
1276  else {
1277  while(minlon < -180.0) {
1278  minlon += 360.0;
1279  maxlon += 360.0;
1280  }
1281  while(minlon > 180.0) {
1282  minlon -= 360.0;
1283  maxlon -= 360.0;
1284  }
1285  }
1286 
1287  // Now return if it crosses the longitude domain boundary
1288  if((maxlon - minlon) > 359.0) return true;
1289  return false;
1290  }
1291 
1305  bool Camera::ringRange(double &minRingRadius, double &maxRingRadius,
1306  double &minRingLongitude, double &maxRingLongitude, Pvl &pvl) {
1307  // Compute the ring range and resolution
1309 
1310  // Get the mapping group
1311  PvlGroup map = pvl.findGroup("Mapping", Pvl::Traverse);
1312 
1313  // Get the ring radius range
1314  minRingRadius = p_minRingRadius;
1315  maxRingRadius = p_maxRingRadius;
1316 
1317  // Assume 0 to 360 domain but change it if necessary
1318  minRingLongitude = p_minRingLongitude;
1319  maxRingLongitude = p_maxRingLongitude;
1320  bool domain360 = true;
1321  if (map.hasKeyword("RingLongitudeDomain")) {
1322  QString ringLongitudeDomain = (QString) map["RingLongitudeDomain"];
1323  if (ringLongitudeDomain == "180") {
1324  minRingLongitude = p_minRingLongitude180;
1325  maxRingLongitude = p_maxRingLongitude180;
1326  domain360 = false;
1327  }
1328  }
1329 
1330  // Convert to the proper azimuth direction
1331  if (map.hasKeyword("RingLongitudeDirection")) {
1332  QString ringLongitudeDirection = (QString) map["RingLongitudeDirection"];
1333  if (ringLongitudeDirection.toUpper() == "Clockwise") {
1334  double swap = minRingLongitude;
1335  minRingLongitude = -maxRingLongitude;
1336  maxRingLongitude = -swap;
1337  }
1338  }
1339 
1340  // Convert to the proper azimuth domain
1341  if (domain360) {
1342  while (minRingLongitude < 0.0) {
1343  minRingLongitude += 360.0;
1344  maxRingLongitude += 360.0;
1345  }
1346  while (minRingLongitude > 360.0) {
1347  minRingLongitude -= 360.0;
1348  maxRingLongitude -= 360.0;
1349  }
1350  }
1351  else {
1352  while (minRingLongitude < -180.0) {
1353  minRingLongitude += 360.0;
1354  maxRingLongitude += 360.0;
1355  }
1356  while (minRingLongitude > 180.0) {
1357  minRingLongitude -= 360.0;
1358  maxRingLongitude -= 360.0;
1359  }
1360  }
1361 
1362  // Now return if it crosses the azimuth domain boundary
1363  if ((maxRingLongitude - minRingLongitude) > 359.0) {
1364  return true;
1365  }
1366  return false;
1367  }
1368 
1369 
1376  PvlGroup map("Mapping");
1377  map += PvlKeyword("TargetName", target()->name());
1378 
1379  std::vector<Distance> radii = target()->radii();
1380  map += PvlKeyword("EquatorialRadius", toString(radii[0].meters()), "meters");
1381  map += PvlKeyword("PolarRadius", toString(radii[2].meters()), "meters");
1382 
1383  map += PvlKeyword("LatitudeType", "Planetocentric");
1384  map += PvlKeyword("LongitudeDirection", "PositiveEast");
1385  map += PvlKeyword("LongitudeDomain", "360");
1386 
1388  map += PvlKeyword("MinimumLatitude", toString(p_minlat));
1389  map += PvlKeyword("MaximumLatitude", toString(p_maxlat));
1390  map += PvlKeyword("MinimumLongitude", toString(p_minlon));
1391  map += PvlKeyword("MaximumLongitude", toString(p_maxlon));
1392  map += PvlKeyword("PixelResolution", toString(p_minres));
1393 
1394  map += PvlKeyword("ProjectionName", "Sinusoidal");
1395  pvl.addGroup(map);
1396  }
1397 
1398 
1405  if (target()->shape()->name() != "Plane") {
1406  // If we get here and we don't have a plane, throw an error
1407  IString msg = "A ring plane projection has been requested on an image whose shape is not a ring plane. ";
1408  msg += "Rerun spiceinit with shape=RINGPLANE. ";
1409  throw IException(IException::User, msg, _FILEINFO_);
1410  }
1411 
1412  PvlGroup map("Mapping");
1413  map += PvlKeyword("TargetName", target()->name());
1414 
1415  map += PvlKeyword("RingLongitudeDirection", "CounterClockwise");
1416  map += PvlKeyword("RingLongitudeDomain", "360");
1417 
1419  map += PvlKeyword("MinimumRingRadius", toString(p_minRingRadius));
1420  map += PvlKeyword("MaximumRingRadius", toString(p_maxRingRadius));
1421  map += PvlKeyword("MinimumRingLongitude", toString(p_minRingLongitude));
1422  map += PvlKeyword("MaximumRingLongitude", toString(p_maxRingLongitude));
1423  map += PvlKeyword("PixelResolution", toString(p_minres));
1424 
1425  map += PvlKeyword("ProjectionName", "Planar");
1426  pvl.addGroup(map);
1427  }
1428 
1431  int code = naifIkCode();
1432  QString key = "INS" + toString(code) + "_FOCAL_LENGTH";
1434  }
1435 
1438  int code = naifIkCode();
1439  QString key = "INS" + toString(code) + "_PIXEL_PITCH";
1441  }
1442 
1443 
1444 
1454  bool Camera::SetRightAscensionDeclination(const double ra, const double dec) {
1455  if (p_skyMap->SetSky(ra, dec)) {
1456  double ux = p_skyMap->FocalPlaneX();
1457  double uy = p_skyMap->FocalPlaneY();
1459  double dx = p_distortionMap->FocalPlaneX();
1460  double dy = p_distortionMap->FocalPlaneY();
1461  if (p_focalPlaneMap->SetFocalPlane(dx, dy)) {
1462  double detectorSamp = p_focalPlaneMap->DetectorSample();
1463  double detectorLine = p_focalPlaneMap->DetectorLine();
1464  if (p_detectorMap->SetDetector(detectorSamp, detectorLine)) {
1465  double parentSample = p_detectorMap->ParentSample();
1466  double parentLine = p_detectorMap->ParentLine();
1467 
1468  if (p_projection == NULL || p_ignoreProjection) {
1469  p_childSample = p_alphaCube->BetaSample(parentSample);
1470  p_childLine = p_alphaCube->BetaLine(parentLine);
1471  p_pointComputed = true;
1472  return true;
1473  }
1474  else if (p_projection->IsSky()) {
1475  if (p_projection->SetGround(dec, ra)) {
1478  p_pointComputed = true;
1479  return true;
1480  }
1481  }
1482  else if (target()->shape()->hasIntersection()) {
1484  UniversalLongitude())) {
1487  p_pointComputed = true;
1488  return true;
1489  }
1490  }
1491  }
1492  }
1493  }
1494  }
1495 
1496  return false;
1497  }
1498 
1499 
1507  void Camera::GetLocalNormal(double normal[3]) {
1508 
1509  ShapeModel *shapeModel = target()->shape();
1510  if ( !shapeModel->hasIntersection()) {
1511  // if the shape is not intersected, then clearly there is no normal
1512  normal[0] = normal[1] = normal[2] = 0.0;
1513  return;
1514  }
1515 
1516  // The DEM shape model (and it's child classes) will use 4 surrounding neighbor
1517  // points to find the local normal. The SetImage() calls used to find the
1518  // neighbors is potentially expensive, so we will not calculate the neighbors
1519  // for shape models whose calculateLocalNormal() method won't use them.
1520  bool computed = p_pointComputed;
1521  if (!shapeModel->isDEM()) {
1522  // Non-DEM case: Ellipsoid, NAIF DSK, or Plane --
1523  // Pass in a vector where all of the "neighbors" are the origin (shape model center).
1524  // We do this so that if the implementation of the calculateLocalNormal() method in
1525  // any of the non-DEM shape model classes is modified to use this vector, then an error
1526  // should be thrown instead of a segmentation fault.
1527  QVector<double *> unusedNeighborPoints(4);
1528  double origin[3] = {0, 0, 0};
1529  unusedNeighborPoints.fill(origin);
1530  shapeModel->calculateLocalNormal(unusedNeighborPoints);
1531  }
1532  else { // attempt to find local normal for DEM shapes using 4 surrounding points on the image
1533  QVector<double *> cornerNeighborPoints(4);
1534 
1535  // As documented in the doxygen above, the goal of this method is to
1536  // calculate a normal vector to the surface using the 4 corner surrounding points.
1537  double samp = Sample();
1538  double line = Line();
1539 
1540  // order of points in vector is top, bottom, left, right
1541  QList< QPair< double, double > > surroundingPoints;
1542  surroundingPoints.append(qMakePair(samp, line - 0.5));
1543  surroundingPoints.append(qMakePair(samp, line + 0.5 - DBL_MIN));
1544  surroundingPoints.append(qMakePair(samp - 0.5, line));
1545  surroundingPoints.append(qMakePair(samp + 0.5 - DBL_MIN, line));
1546 
1547  // save input state to be restored on return
1548  double originalSample = samp;
1549  double originalLine = line;
1550 
1551  // now we have all four points in the image, so find the same points on the surface
1552  for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1553  cornerNeighborPoints[i] = new double[3];
1554  }
1555 
1556  Latitude lat;
1557  Longitude lon;
1558  Distance radius;
1559 
1560  // if this is a dsk, we only need to use the existing intercept point (plate) normal then return
1561  for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1562  // If a surrounding point fails, set it to the original point
1563  if (!(SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1564  surroundingPoints[i].first = samp;
1565  surroundingPoints[i].second = line;
1566 
1567  // If the original point fails too, we can't get a normal. Clean up and return.
1568  if (!(SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1569 
1570  normal[0] = normal[1] = normal[2] = 0.0;
1571 
1572  // restore input state
1573  if (computed) {
1574  SetImage(originalSample, originalLine);
1575  }
1576  else {
1577  p_pointComputed = false;
1578  }
1579 
1580  // free memory
1581  for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1582  delete [] cornerNeighborPoints[i];
1583  }
1584 
1585  return;
1586  }
1587  }
1588 
1589  SurfacePoint surfacePoint = GetSurfacePoint();
1590  lat = surfacePoint.GetLatitude();
1591  lon = surfacePoint.GetLongitude();
1592  radius = LocalRadius(lat, lon);
1593 
1594  latrec_c(radius.kilometers(), lon.radians(), lat.radians(), cornerNeighborPoints[i]);
1595  }
1596 
1597  // if the first 2 surrounding points match or the last 2 surrounding points match,
1598  // we can't get a normal. Clean up and return.
1599  if ((surroundingPoints[0].first == surroundingPoints[1].first &&
1600  surroundingPoints[0].second == surroundingPoints[1].second) ||
1601  (surroundingPoints[2].first == surroundingPoints[3].first &&
1602  surroundingPoints[2].second == surroundingPoints[3].second)) {
1603 
1604  normal[0] = normal[1] = normal[2] = 0.0;
1605 
1606  // restore input state
1607  if (!computed) {
1608  SetImage(originalSample, originalLine);
1609  }
1610  else {
1611  p_pointComputed = false;
1612  }
1613 
1614  // free memory
1615  for (int i = 0; i < cornerNeighborPoints.size(); i++)
1616  delete [] cornerNeighborPoints[i];
1617 
1618  return;
1619  }
1620 
1621  // Restore input state to original point before calculating normal
1622  SetImage(originalSample, originalLine);
1623  shapeModel->calculateLocalNormal(cornerNeighborPoints);
1624 
1625  // free memory
1626  for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1627  delete [] cornerNeighborPoints[i];
1628  }
1629 
1630  }
1631 
1632  // restore input state if calculation failed and clean up.
1633  if (!shapeModel->hasNormal()) {
1634  p_pointComputed = false;
1635  return;
1636  }
1637 
1638  // restore failed computed state
1639  if (!computed) {
1640  p_pointComputed = false;
1641  }
1642 
1643  // Set the method normal values
1644  std::vector<double> localNormal(3);
1645  localNormal = shapeModel->normal();
1646  memcpy(normal, (double *) &localNormal[0], sizeof(double) * 3);
1647  }
1648 
1649 
1661  void Camera::LocalPhotometricAngles(Angle & phase, Angle & incidence,
1662  Angle & emission, bool &success) {
1663 
1664  // get local normal vector
1665  double normal[3];
1666  GetLocalNormal(normal);
1667  success = true;
1668 
1669  // Check to make sure normal is valid
1670  SpiceDouble mag;
1671  unorm_c(normal,normal,&mag);
1672  if (mag == 0.) {
1673  success = false;
1674  return;
1675  }
1676 
1677  // get a normalized surface spacecraft vector
1678  SpiceDouble surfSpaceVect[3], unitizedSurfSpaceVect[3], dist;
1679  std::vector<double> sB = bodyRotation()->ReferenceVector(
1681 
1682  SpiceDouble pB[3];
1683  SurfacePoint surfacePoint = GetSurfacePoint();
1684  pB[0] = surfacePoint.GetX().kilometers();
1685  pB[1] = surfacePoint.GetY().kilometers();
1686  pB[2] = surfacePoint.GetZ().kilometers();
1687 
1688  vsub_c((SpiceDouble *) &sB[0], pB, surfSpaceVect);
1689  unorm_c(surfSpaceVect, unitizedSurfSpaceVect, &dist);
1690 
1691  // get a normalized surface sun vector
1692  SpiceDouble surfaceSunVect[3];
1693  vsub_c(m_uB, pB, surfaceSunVect);
1694  SpiceDouble unitizedSurfSunVect[3];
1695  unorm_c(surfaceSunVect, unitizedSurfSunVect, &dist);
1696 
1697  // use normalized surface spacecraft and surface sun vectors to calculate
1698  // the phase angle (in radians)
1699  phase = Angle(vsep_c(unitizedSurfSpaceVect, unitizedSurfSunVect),
1700  Angle::Radians);
1701 
1702  // use normalized surface spacecraft and local normal vectors to calculate
1703  // the emission angle (in radians)
1704  emission = Angle(vsep_c(unitizedSurfSpaceVect, normal),
1705  Angle::Radians);
1706 
1707  // use normalized surface sun and normal vectors to calculate the incidence
1708  // angle (in radians)
1709  incidence = Angle(vsep_c(unitizedSurfSunVect, normal),
1710  Angle::Radians);
1711 
1712 
1713  }
1714 
1715 
1726  bool Camera::RaDecRange(double &minra, double &maxra,
1727  double &mindec, double &maxdec) {
1728 
1729 
1730  bool computed = p_pointComputed;
1731  double originalSample = Sample();
1732  double originalLine = Line();
1733  int originalBand = Band();
1734 
1735  // Have we already done this
1736  if (!p_raDecRangeComputed) {
1737  p_raDecRangeComputed = true;
1738 
1739  // Initializations
1740  p_mindec = DBL_MAX;
1741  p_minra = DBL_MAX;
1742  p_minra180 = DBL_MAX;
1743  p_maxdec = -DBL_MAX;
1744  p_maxra = -DBL_MAX;
1745  p_maxra180 = -DBL_MAX;
1746 
1747  // See if we have band dependence and loop for the appropriate number of bands
1748  int eband = p_bands;
1749  if (IsBandIndependent()) eband = 1;
1750  for (int band = 1; band <= eband; band++) {
1751  this->SetBand(band);
1752 
1753  for (int line = 1; line <= p_lines; line++) {
1754  // Test left, top, and bottom sides
1755  int samp;
1756  for (samp = 1; samp <= p_samples; samp++) {
1757  SetImage((double)samp, (double)line);
1758  double ra = RightAscension();
1759  double dec = Declination();
1760  if (ra < p_minra) p_minra = ra;
1761  if (ra > p_maxra) p_maxra = ra;
1762  if (dec < p_mindec) p_mindec = dec;
1763  if (dec > p_maxdec) p_maxdec = dec;
1764 
1765  if (ra > 180.0) ra -= 360.0;
1766  if (ra < p_minra180) p_minra180 = ra;
1767  if (ra > p_maxra180) p_maxra180 = ra;
1768 
1769  if ((line != 1) && (line != p_lines)) break;
1770  }
1771 
1772  // Test right side
1773  if (samp < p_samples) {
1774  for (samp = p_samples; samp >= 1; samp--) {
1775  SetImage((double)samp, (double)line);
1776  double ra = RightAscension();
1777  double dec = Declination();
1778  if (ra < p_minra) p_minra = ra;
1779  if (ra > p_maxra) p_maxra = ra;
1780  if (dec < p_mindec) p_mindec = dec;
1781  if (dec > p_maxdec) p_maxdec = dec;
1782 
1783  if (ra > 180.0) ra -= 360.0;
1784  if (ra < p_minra180) p_minra180 = ra;
1785  if (ra > p_maxra180) p_maxra180 = ra;
1786 
1787  break;
1788  }
1789  }
1790  }
1791 
1792  // Special test for ground range to see if either pole is in the image
1793  if (SetRightAscensionDeclination(0.0, 90.0)) {
1794  if ((Line() >= 0.5) && (Line() <= p_lines) &&
1795  (Sample() >= 0.5) && (Sample() <= p_samples)) {
1796  p_maxdec = 90.0;
1797  p_minra = 0.0;
1798  p_maxra = 360.0;
1799  p_minra180 = -180.0;
1800  p_maxra180 = 180.0;
1801  }
1802  }
1803 
1804  if (SetRightAscensionDeclination(0.0, -90.0)) {
1805  if ((Line() >= 0.5) && (Line() <= p_lines) &&
1806  (Sample() >= 0.5) && (Sample() <= p_samples)) {
1807  p_mindec = -90.0;
1808  p_minra = 0.0;
1809  p_maxra = 360.0;
1810  p_minra180 = -180.0;
1811  p_maxra180 = 180.0;
1812  }
1813  }
1814 
1815  // Another special test for ground range as we could have the
1816  // 0-360 seam running right through the image so
1817  // test it as well (the increment may not be fine enough !!!)
1818  for (double dec = p_mindec; dec <= p_maxdec; dec += (p_maxdec - p_mindec) / 10.0) {
1819  if (SetRightAscensionDeclination(0.0, dec)) {
1820  if ((Line() >= 0.5) && (Line() <= p_lines) &&
1821  (Sample() >= 0.5) && (Sample() <= p_samples)) {
1822  p_minra = 0.0;
1823  p_maxra = 360.0;
1824  break;
1825  }
1826  }
1827  }
1828 
1829  // Another special test for ground range as we could have the
1830  // 0-360 seam running right through the image so
1831  // test it as well (the increment may not be fine enough !!!)
1832  for (double dec = p_mindec; dec <= p_maxdec; dec += (p_maxdec - p_mindec) / 10.0) {
1833  if (SetRightAscensionDeclination(180.0, dec)) {
1834  if ((Line() >= 0.5) && (Line() <= p_lines) &&
1835  (Sample() >= 0.5) && (Sample() <= p_samples)) {
1836  p_minra180 = -180.0;
1837  p_maxra180 = 180.0;
1838  break;
1839  }
1840  }
1841  }
1842  }
1843  }
1844 
1845  minra = p_minra;
1846  maxra = p_maxra;
1847  mindec = p_mindec;
1848  maxdec = p_maxdec;
1849 
1850  SetBand(originalBand);
1851 
1852  if (computed) {
1853  SetImage(originalSample, originalLine);
1854  }
1855  else {
1856  p_pointComputed = false;
1857  }
1858 
1859  return true;
1860  }
1861 
1862 
1869 
1870  bool computed = p_pointComputed;
1871  double originalSample = Sample();
1872  double originalLine = Line();
1873  int originalBand = Band();
1874 
1875  SetImage(1.0, 1.0);
1876  double ra1 = RightAscension();
1877  double dec1 = Declination();
1878 
1879  SetImage(1.0, (double)p_lines);
1880  double ra2 = RightAscension();
1881  double dec2 = Declination();
1882 
1883  double dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1884  dist = sqrt(dist);
1885  double lineRes = dist / (p_lines - 1);
1886 
1887  SetImage((double)p_samples, 1.0);
1888  ra2 = RightAscension();
1889  dec2 = Declination();
1890 
1891  dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1892  dist = sqrt(dist);
1893  double sampRes = dist / (p_samples - 1);
1894 
1895  SetBand(originalBand);
1896 
1897  if (computed) {
1898  SetImage(originalSample, originalLine);
1899  }
1900  else {
1901  p_pointComputed = false;
1902  }
1903 
1904  return (sampRes < lineRes) ? sampRes : lineRes;
1905  }
1906 
1913  if (target()->shape()->name() == "Plane") {
1914  QString msg = "North Azimuth is not available for plane target shapes.";
1916  }
1917  // Get the latitude of your current location using the shape model
1918  // specified in the image Kernels
1919  double lat = UniversalLatitude();
1920  // We are in northern hemisphere
1921  if (lat >= 0.0) {
1922  return ComputeAzimuth(90.0, 0.0);
1923  }
1924  // We are in southern hemisphere
1925  else {
1926  double azimuth = ComputeAzimuth(-90.0, 0.0) + 180.0;
1927  if (azimuth > 360.0) azimuth = azimuth - 360.0;
1928  return azimuth;
1929  }
1930  }
1931 
1940  double lat, lon;
1941  subSolarPoint(lat, lon);
1942  return ComputeAzimuth(lat, lon);
1943  }
1944 
1945 
1954  double lat, lon;
1955  subSpacecraftPoint(lat, lon);
1956  return ComputeAzimuth(lat, lon);
1957  }
1958 
1959 
2059  double Camera::ComputeAzimuth(const double lat, const double lon) {
2060  // Make sure we are on the planet, if not, north azimuth is meaningless
2061  if (!HasSurfaceIntersection()) return Isis::Null;
2062 
2063  // Need to save the "state" of the camera so we can restore it when the
2064  // method is done
2065  bool computed = p_pointComputed;
2066 
2068 
2069  // Get the azimuth's origin point (the current position) and its radius
2070  SpiceDouble azimuthOrigin[3];
2071  Coordinate(azimuthOrigin);
2072  Distance originRadius = LocalRadius();
2073  if (!originRadius.isValid()) {
2074  return Isis::Null;
2075  }
2076 
2077  // Convert the point of interest to rectangular coordinates (x,y,z) in the
2078  // body-fixed coordinate system and use the azimuth's origin radius to avoid the
2079  // situation where the DEM does not cover the entire planet
2080  SpiceDouble pointOfInterestFromBodyCenter[3];
2081  latrec_c(originRadius.kilometers(), lon * PI / 180.0,
2082  lat * PI / 180.0, pointOfInterestFromBodyCenter);
2083 
2084  // Get the difference vector with its tail at the azimuth origin and its
2085  // head at the point of interest by subtracting vectors the vectors that
2086  // originate at the body center
2087  //
2088  // pointOfInterest = pointOfInterestFromBodyCenter - azimuthOriginFromBodyCenter
2089  //
2090  SpiceDouble pointOfInterest[3];
2091  vsub_c(pointOfInterestFromBodyCenter, azimuthOrigin, pointOfInterest);
2092 
2093  // Get the component of the difference vector pointOfInterestFromAzimuthOrigin that is
2094  // perpendicular to the origin point (i.e. project perpendicularly onto the reference plane).
2095  // This will result in a point of interest vector that is in the plane tangent to the surface at
2096  // the origin point
2097  SpiceDouble pointOfInterestProj[3];
2098  vperp_c(pointOfInterest, azimuthOrigin, pointOfInterestProj);
2099 
2100  // Unitize the tangent vector to a 1 km length vector
2101  SpiceDouble pointOfInterestProjUnit[3];
2102  vhat_c(pointOfInterestProj, pointOfInterestProjUnit);
2103 
2104  // Scale the vector to within a pixel of the azimuth's origin point.
2105  // Get pixel scale in km/pixel and divide by 2 to insure that we stay within
2106  // a pixel of the origin point
2107  double scale = (PixelResolution() / 1000.0) / 2.0;
2108  SpiceDouble pointOfInterestProjUnitScaled[3];
2109  vscl_c(scale, pointOfInterestProjUnit, pointOfInterestProjUnitScaled);
2110 
2111  // Compute the adjusted point of interest vector from the body center. This point
2112  // will be within a pixel of the origin and in the same direction as the requested
2113  // raw point of interest vector
2114  SpiceDouble adjustedPointOfInterestFromBodyCenter[3];
2115  vadd_c(azimuthOrigin, pointOfInterestProjUnitScaled, adjustedPointOfInterestFromBodyCenter);
2116 
2117  // Get the origin image coordinate
2118  double azimuthOriginSample = Sample();
2119  double azimuthOriginLine = Line();
2120 
2121  // Convert the point to a lat/lon and find out its image coordinate
2122  double adjustedPointOfInterestRad, adjustedPointOfInterestLon, adjustedPointOfInterestLat;
2123  reclat_c(adjustedPointOfInterestFromBodyCenter,
2124  &adjustedPointOfInterestRad,
2125  &adjustedPointOfInterestLon,
2126  &adjustedPointOfInterestLat);
2127  adjustedPointOfInterestLat = adjustedPointOfInterestLat * 180.0 / PI;
2128  adjustedPointOfInterestLon = adjustedPointOfInterestLon * 180.0 / PI;
2129  if (adjustedPointOfInterestLon < 0) adjustedPointOfInterestLon += 360.0;
2130 
2131  // Use the radius of the azimuth's origin point
2132  // (rather than that of the adjusted point of interest location)
2133  // to avoid the effects of topography on the calculation
2134  bool success = SetUniversalGround(adjustedPointOfInterestLat,
2135  adjustedPointOfInterestLon,
2136  originRadius.meters());
2137  if (!success) {
2138  // if the adjusted lat/lon values for the point of origin fail to be set, we can not compute
2139  // an azimuth. reset to the original sample/line and return null.
2140  SetImage(azimuthOriginSample, azimuthOriginLine);
2141  return Isis::Null;
2142  }
2143 
2144  double adjustedPointOfInterestSample = Sample();
2145  double adjustedPointOfInterestLine = Line();
2146 
2147  // TODO: Write PushState and PopState method to ensure the
2148  // internals of the class are set based on SetImage or SetGround
2149 
2150  // We now have the information needed to calculate an arctangent
2151  //
2152  //
2153  // point of interest
2154  // |\ |
2155  // | \ |
2156  // | \ | tan(A) = (delta line) / (delta sample)
2157  // delta line | \ | A = arctan( (delta line) / (delta sample) )
2158  // | \ |
2159  // | \ |
2160  // | \ |
2161  // ___________|_____A_\|_______________
2162  // delta sample |origin point
2163  // |
2164  // |
2165  // |
2166  // |
2167  // |
2168  //
2169  // in this example, the azimuth is the angle indicated by the A plus 180 degrees, since we begin
2170  // the angle rotation at the positive x-axis
2171  // This quadrant issue (i.e.need to add 180 degrees) is handled by the atan2 program
2172  //
2173  double deltaSample = adjustedPointOfInterestSample - azimuthOriginSample;
2174  double deltaLine = adjustedPointOfInterestLine - azimuthOriginLine;
2175 
2176  // Compute the angle; the azimuth is the arctangent of the line difference divided by the
2177  // sample difference; the atan2 function is used because it determines which quadrant we
2178  // are in based on the sign of the 2 arguments; the arctangent is measured in a positive
2179  // clockwise direction because the lines in the image increase downward; the arctangent
2180  // uses the 3 o'clock axis (positive sample direction) as its reference line (line of
2181  // zero degrees); a good place to read about the atan2 function is at
2182  // http://en.wikipedia.org/wiki/Atan2
2183  double azimuth = 0.0;
2184  if (deltaSample != 0.0 || deltaLine != 0.0) {
2185  azimuth = atan2(deltaLine, deltaSample);
2186  azimuth *= 180.0 / PI;
2187  }
2188 
2189  // Azimuth is limited to the range of 0 to 360
2190  if (azimuth < 0.0) azimuth += 360.0;
2191  if (azimuth > 360.0) azimuth -= 360.0;
2192 
2194 
2195  // computed is true if the sample/line or lat/lon were reset in this method
2196  // to find the location of the point of interest
2197  // If so, reset "state" of camera to the original sample/line
2198  if (computed) {
2199  SetImage(azimuthOriginSample, azimuthOriginLine);
2200  }
2201  else {
2202  p_pointComputed = false;
2203  }
2204 
2205  return azimuth;
2206  }
2207 
2208 
2216 
2217  // Get the xyz coordinates for the spacecraft and point we are interested in
2218  double coord[3], spCoord[3];
2219  Coordinate(coord);
2220  instrumentPosition(spCoord);
2221 
2222  // Get the angle between the 2 points and convert to degrees
2223  double a = vsep_c(coord, spCoord) * 180.0 / PI;
2224  double b = 180.0 - EmissionAngle();
2225 
2226  // The three angles in a triangle must add up to 180 degrees
2227  double c = 180.0 - (a + b);
2228 
2230 
2231  return c;
2232  }
2233 
2234 
2256  double Camera::GroundAzimuth(double glat, double glon,
2257  double slat, double slon) {
2258  double a;
2259  double b;
2260  if (glat >= 0.0) {
2261  a = (90.0 - slat) * PI / 180.0;
2262  b = (90.0 - glat) * PI / 180.0;
2263  }
2264  else {
2265  a = (90.0 + slat) * PI / 180.0;
2266  b = (90.0 + glat) * PI / 180.0;
2267  }
2268 
2269  double cslon = slon;
2270  double cglon = glon;
2271  if (cslon > cglon) {
2272  if ((cslon-cglon) > 180.0) {
2273  while ((cslon-cglon) > 180.0) cslon = cslon - 360.0;
2274  }
2275  }
2276  if (cglon > cslon) {
2277  if ((cglon-cslon) > 180.0) {
2278  while ((cglon-cslon) > 180.0) cglon = cglon - 360.0;
2279  }
2280  }
2281 
2282  // Which quadrant are we in?
2283  int quad;
2284  if (slat > glat) {
2285  if (cslon > cglon) {
2286  quad = 1;
2287  }
2288  else if (cslon < cglon) {
2289  quad = 2;
2290  }
2291  else {
2292  quad = 1;
2293  }
2294  }
2295  else if (slat < glat) {
2296  if (cslon > cglon) {
2297  quad = 4;
2298  }
2299  else if (cslon < cglon) {
2300  quad = 3;
2301  }
2302  else {
2303  quad = 4;
2304  }
2305  }
2306  else {
2307  if (cslon > cglon) {
2308  quad = 1;
2309  }
2310  else if (cslon < cglon) {
2311  quad = 2;
2312  }
2313  else {
2314  return 0.0;
2315  }
2316  }
2317 
2318  double C = (cglon - cslon) * PI / 180.0;
2319  if (C < 0) C = -C;
2320  double c = acos(cos(a)*cos(b) + sin(a)*sin(b)*cos(C));
2321  double azimuth = 0.0;
2322  if (sin(b) == 0.0 || sin(c) == 0.0) {
2323  return azimuth;
2324  }
2325  double A = acos((cos(a) - cos(b)*cos(c))/(sin(b)*sin(c))) * 180.0 / PI;
2326  //double B = acos((cos(b) - cos(c)*cos(a))/(sin(c)*sin(a))) * 180.0 / PI;
2327  if (glat >= 0.0) {
2328  if (quad == 1 || quad == 4) {
2329  azimuth = A;
2330  }
2331  else if (quad == 2 || quad == 3) {
2332  azimuth = 360.0 - A;
2333  }
2334  }
2335  else {
2336  if (quad == 1 || quad == 4) {
2337  azimuth = 180.0 - A;
2338  }
2339  else if (quad == 2 || quad == 3) {
2340  azimuth = 180.0 + A;
2341  }
2342  }
2343 
2344  return azimuth;
2345  }
2346 
2347 
2354  void Camera::SetDistortionMap(CameraDistortionMap *map, bool deleteExisting) {
2355  if (deleteExisting && p_distortionMap) {
2356  delete p_distortionMap;
2357  }
2358 
2359  p_distortionMap = map;
2360  }
2361 
2362 
2370  if (p_focalPlaneMap) {
2371  delete p_focalPlaneMap;
2372  }
2373 
2374  p_focalPlaneMap = map;
2375  }
2376 
2377 
2385  if (p_detectorMap) {
2386  delete p_detectorMap;
2387  }
2388 
2389  p_detectorMap = map;
2390  }
2391 
2392 
2400  if (p_groundMap) {
2401  delete p_groundMap;
2402  }
2403 
2404  p_groundMap = map;
2405  }
2406 
2407 
2414  if (p_skyMap) {
2415  delete p_skyMap;
2416  }
2417 
2418  p_skyMap = map;
2419  }
2420 
2421 
2433  // We want to stay in unprojected space for this process
2434  bool projIgnored = p_ignoreProjection;
2435  p_ignoreProjection = true;
2436 
2437  // get the cache variables
2438  pair<double,double> ephemerisTimes = StartEndEphemerisTimes();
2439  int cacheSize = CacheSize(ephemerisTimes.first, ephemerisTimes.second);
2440 
2441  // Set a position in the image so that the PixelResolution can be calculated
2443  double tol = PixelResolution() / 100.; //meters/pix/100.
2444 
2445  if (tol < 0.0) {
2446  // Alternative calculation of ground resolution of a pixel/100
2447  double altitudeMeters;
2448  if (target()->isSky()) { // Use the unit sphere as the target
2449  altitudeMeters = 1.0;
2450  }
2451  else {
2452  altitudeMeters = SpacecraftAltitude() * 1000.;
2453  }
2454  tol = PixelPitch() * altitudeMeters / FocalLength() / 100.;
2455  }
2456 
2457  p_ignoreProjection = projIgnored;
2458 
2459  Spice::createCache(ephemerisTimes.first, ephemerisTimes.second,
2460  cacheSize, tol);
2461 
2462  setTime(ephemerisTimes.first);
2463 
2464  // Reset to band 1
2465  SetBand(1);
2466 
2467  return;
2468  }
2469 
2470 
2491  pair<double, double> Camera::StartEndEphemerisTimes() {
2492  pair<double,double> ephemerisTimes;
2493  double startTime = -DBL_MAX;
2494  double endTime = -DBL_MAX;
2495 
2496  for (int band = 1; band <= Bands(); band++) {
2497  SetBand(band);
2498  SetImage(0.5, 0.5);
2499  double etStart = time().Et();
2500  SetImage(p_alphaCube->BetaSamples() + 0.5,
2501  p_alphaCube->BetaLines() + 0.5); // need to do something if SetImage returns false???
2502  double etEnd = time().Et();
2503  if (band == 1) {
2504  startTime = min(etStart, etEnd);
2505  endTime = max(etStart, etEnd);
2506  }
2507  startTime = min(startTime, min(etStart, etEnd));
2508  endTime = max(endTime, max(etStart, etEnd));
2509  }
2510  if (startTime == -DBL_MAX || endTime == -DBL_MAX) {
2511  string msg = "Unable to find time range for the spice kernels";
2513  }
2514  ephemerisTimes.first = startTime;
2515  ephemerisTimes.second = endTime;
2516  return ephemerisTimes;
2517  }
2518 
2519 
2539  int Camera::CacheSize(double startTime, double endTime) {
2540  int cacheSize;
2541  // BetaLines() + 1 so we get at least 2 points for interpolation
2542  cacheSize = p_alphaCube->BetaLines() + 1;
2543  if (startTime == endTime) {
2544  cacheSize = 1;
2545  }
2546  return cacheSize;
2547  }
2548 
2549 
2566  void Camera::SetGeometricTilingHint(int startSize, int endSize) {
2567  // verify the start size is a multiple of 2 greater than 2
2568  int powerOf2 = 2;
2569 
2570  // No hint if 2's are passed in
2571  if (startSize == 2 && endSize == 2) {
2574  return;
2575  }
2576 
2577  if (endSize > startSize) {
2578  IString message = "Camera::SetGeometricTilingHint End size must be smaller than the start size";
2579  throw IException(IException::Programmer, message, _FILEINFO_);
2580  }
2581 
2582  if (startSize < 4) {
2583  IString message = "Camera::SetGeometricTilingHint Start size must be at least 4";
2584  throw IException(IException::Programmer, message, _FILEINFO_);
2585  }
2586 
2587  bool foundEnd = false;
2588  while (powerOf2 > 0 && startSize != powerOf2) {
2589  if (powerOf2 == endSize) foundEnd = true;
2590  powerOf2 *= 2;
2591  }
2592 
2593  // Didnt find a solution, the integer became negative first, must not be
2594  // a power of 2
2595  if (powerOf2 < 0) {
2596  IString message = "Camera::SetGeometricTilingHint Start size must be a power of 2";
2597  throw IException(IException::Programmer, message, _FILEINFO_);
2598  }
2599 
2600  if (!foundEnd) {
2601  IString message = "Camera::SetGeometricTilingHint End size must be a power of 2 less than the start size, but greater than 2";
2602  throw IException(IException::Programmer, message, _FILEINFO_);
2603  }
2604 
2605  p_geometricTilingStartSize = startSize;
2606  p_geometricTilingEndSize = endSize;
2607  }
2608 
2609 
2617  void Camera::GetGeometricTilingHint(int &startSize, int &endSize) {
2618  startSize = p_geometricTilingStartSize;
2619  endSize = p_geometricTilingEndSize;
2620  }
2621 
2622 
2632  if (Sample() < 0.5 || Line() < 0.5) {
2633  return false;
2634  }
2635 
2636  if (Sample() > Samples() + 0.5 || Line() > Lines() + 0.5) {
2637  return false;
2638  }
2639 
2640  return true;
2641  }
2642 
2643 
2651  return p_projection != 0;
2652  }
2653 
2654 
2662  return true;
2663  }
2664 
2665 
2672  return p_referenceBand;
2673  }
2674 
2675 
2683  return p_referenceBand != 0;
2684  }
2685 
2686 
2692  void Camera::SetBand(const int band) {
2693  p_childBand = band;
2694  }
2695 
2696 
2702  double Camera::Sample() {
2703  return p_childSample;
2704  }
2705 
2706 
2713  return p_childBand;
2714  }
2715 
2716 
2722  double Camera::Line() {
2723  return p_childLine;
2724  }
2725 
2726 
2733  return PixelResolution();
2734  }
2735 
2736 
2737 
2738 
2744  double Camera::FocalLength() const {
2745  return p_focalLength;
2746  }
2747 
2748 
2754  double Camera::PixelPitch() const {
2755  return p_pixelPitch;
2756  }
2757 
2758 
2768 
2769  QList<QPointF> offsets;
2770  offsets.append(QPointF(-PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2771  -PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2772  offsets.append(QPointF(PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2773  -PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2774  offsets.append(QPointF(PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2775  PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2776  offsets.append(QPointF(-PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2777  PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2778 
2779  return offsets;
2780  }
2781 
2782 
2788  int Camera::Samples() const {
2789  return p_samples;
2790  }
2791 
2792 
2798  int Camera::Lines() const {
2799  return p_lines;
2800  }
2801 
2802 
2808  int Camera::Bands() const {
2809  return p_bands;
2810  }
2811 
2812 
2818  int Camera::ParentLines() const {
2819  return p_alphaCube->AlphaLines();
2820  }
2821 
2822 
2829  return p_alphaCube->AlphaSamples();
2830  }
2831 
2832 
2839  return p_distortionMap;
2840  }
2841 
2842 
2849  return p_focalPlaneMap;
2850  }
2851 
2852 
2859  return p_detectorMap;
2860  }
2861 
2862 
2869  return p_groundMap;
2870  }
2871 
2872 
2879  return p_skyMap;
2880  }
2881 
2882 
2889  return m_instrumentId;
2890  }
2891 
2892 
2898  QString Camera::instrumentNameLong() const {
2899  return m_instrumentNameLong;
2900  }
2901 
2902 
2909  return m_instrumentNameShort;
2910  }
2911 
2912 
2918  QString Camera::spacecraftNameLong() const {
2919  return m_spacecraftNameLong;
2920  }
2921 
2922 
2929  return m_spacecraftNameShort;
2930  }
2931 
2937  void Camera::IgnoreProjection(bool ignore) {
2938  p_ignoreProjection = ignore;
2939  }
2975  int Camera::SpkTargetId() const {
2976  return (naifSpkCode());
2977  }
2978 
3017  int Camera::SpkCenterId() const {
3018  return (naifBodyCode());
3019  }
3020 
3026  void Camera::SetFocalLength(double v) {
3027  p_focalLength = v;
3028  }
3029 
3035  void Camera::SetPixelPitch(double v) {
3036  p_pixelPitch = v;
3037  }
3038 
3050  double orgLine = Line();
3051  double orgSample = Sample();
3052  double orgDec = Declination();
3053  double orgRa = RightAscension();
3054 
3055  SetRightAscensionDeclination(orgRa, orgDec + (2 * RaDecResolution()));
3056  double y = Line() - orgLine;
3057  double x = Sample() - orgSample;
3058  double celestialNorthClockAngle = atan2(-y, x) * 180.0 / Isis::PI;
3059  celestialNorthClockAngle = 90.0 - celestialNorthClockAngle;
3060 
3061  if (celestialNorthClockAngle < 0.0) {
3062  celestialNorthClockAngle += 360.0;
3063  }
3064 
3065  SetImage(orgSample, orgLine);
3066  return celestialNorthClockAngle;
3067  }
3068 
3069 
3075  double Camera::exposureDuration() const {
3077  }
3078 
3079 
3089  double Camera::exposureDuration(const double sample, const double line, const int band) const {
3090 
3091  //If band defaults to -1, use the camera's stored band.
3092  if (band < 0) {
3093  return p_detectorMap->exposureDuration(sample, line, p_childBand);
3094  }
3095  return p_detectorMap->exposureDuration(sample, line, band);
3096  }
3097 
3098 // end namespace isis
3099 }
3100 
3101 
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:148
void LocalPhotometricAngles(Angle &phase, Angle &incidence, Angle &emission, bool &success)
Calculates LOCAL photometric angles using the DEM (not ellipsoid).
Definition: Camera.cpp:1661
SpicePosition * instrumentPosition() const
Accessor method for the instrument position.
Definition: Spice.cpp:1467
virtual bool SetFocalPlane(const double ux, const double uy, const double uz)
Compute ground position from focal plane coordinate.
double p_maxlat
The maximum latitude.
Definition: Camera.h:528
std::vector< double > normal()
Returns the local surface normal at the current intersection point.
Definition: ShapeModel.cpp:395
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Definition: Sensor.cpp:211
QString instrumentNameShort() const
This method returns the shortened instrument name.
Definition: Camera.cpp:2908
void SetFocalLength()
Reads the focal length from the instrument kernel.
Definition: Camera.cpp:1430
double RightAscension()
Returns the right ascension angle (sky longitude).
Definition: Sensor.cpp:576
double meters() const
Get the distance in meters.
Definition: Distance.cpp:97
CameraDetectorMap * DetectorMap()
Returns a pointer to the CameraDetectorMap object.
Definition: Camera.cpp:2858
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
int CacheSize(double startTime, double endTime)
This method calculates the spice cache size.
Definition: Camera.cpp:2539
void SetSkyMap(CameraSkyMap *map)
Sets the Sky Map.
Definition: Camera.cpp:2413
double ObliqueLineResolution()
Returns the oblique line resolution at the current position in meters.
Definition: Camera.cpp:679
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
virtual int SpkTargetId() const
Provides target code for instruments SPK NAIF kernel.
Definition: Camera.cpp:2975
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
virtual bool SetParent(const double sample, const double line)
Compute detector position from a parent image coordinate.
double p_mindec
The minimum declination.
Definition: Camera.h:551
double p_minlon
The minimum longitude.
Definition: Camera.h:529
double p_minobliqueres
The minimum oblique resolution.
Definition: Camera.h:533
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
int p_referenceBand
The reference band.
Definition: Camera.h:546
double p_minra180
The minimum right ascension in the 180 domain.
Definition: Camera.h:555
double FocalPlaneY() const
double SunAzimuth()
Returns the Sun Azimuth.
Definition: Camera.cpp:1939
bool ringRange(double &minRingRadius, double &maxRingRadius, double &minRingLongitude, double &maxRingLongitude, Pvl &pvl)
Analogous to the above Ground Range method.
Definition: Camera.cpp:1305
ProjectionType projectionType() const
Returns an enum value for the projection type.
Definition: Projection.cpp:213
void SetDetectorMap(CameraDetectorMap *map)
Sets the Detector Map.
Definition: Camera.cpp:2384
const double PI
The mathematical constant PI.
Definition: Constants.h:56
CameraDistortionMap * DistortionMap()
Returns a pointer to the CameraDistortionMap object.
Definition: Camera.cpp:2838
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
int BetaLines() const
Returns the number of lines in the beta cube.
Definition: AlphaCube.h:103
double UndistortedFocalPlaneZ() const
Gets the z-value in the undistorted focal plane coordinate system.
virtual bool SetFocalPlane(const double dx, const double dy)
Compute detector position (sample,line) from focal plane coordinates.
int p_lines
The number of lines in the image.
Definition: Camera.h:543
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition: Camera.cpp:2399
double FocalPlaneY() const
Definition: CameraSkyMap.h:70
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
Base class for Map TProjections.
Definition: TProjection.h:182
QString m_instrumentNameLong
Full instrument name.
Definition: Camera.h:507
double p_maxRingLongitude
The maximum ring longitude (azimuth)
Definition: Camera.h:563
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
double SpacecraftAzimuth()
Return the Spacecraft Azimuth.
Definition: Camera.cpp:1953
int sampleCount() const
Definition: Cube.cpp:1452
bool SetRightAscensionDeclination(const double ra, const double dec)
Sets the right ascension declination.
Definition: Camera.cpp:1454
bool HasProjection()
Checks to see if the camera object has a projection.
Definition: Camera.cpp:2650
bool hasIntersection()
Returns intersection status.
Definition: ShapeModel.cpp:362
SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition: Spice.cpp:1478
double p_maxra180
The maximum right ascension in the 180 domain.
Definition: Camera.h:556
void basicRingMapping(Pvl &map)
Writes the basic mapping group for ring plane to the specified Pvl.
Definition: Camera.cpp:1404
double OffNadirAngle()
Return the off nadir angle in degrees.
Definition: Camera.cpp:2214
int AlphaLines() const
Returns the number of lines in the alpha cube.
Definition: AlphaCube.h:83
virtual double resolution()
Returns the resolution of the camera.
Definition: Camera.cpp:2732
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Definition: PvlObject.h:198
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition: Camera.cpp:2631
const double HALFPI
The mathematical constant PI/2.
Definition: Constants.h:57
void SetPixelPitch()
Reads the Pixel Pitch from the instrument kernel.
Definition: Camera.cpp:1437
Namespace for the standard library.
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
Class for computing sensor ground coordinates.
Definition: Sensor.h:183
double p_maxlon180
The maximum longitude in the 180 domain.
Definition: Camera.h:536
The distance is being specified in kilometers.
Definition: Distance.h:58
double p_focalLength
The focal length, in units of millimeters.
Definition: Camera.h:524
Search child objects.
Definition: PvlObject.h:170
double ObliquePixelResolution()
Returns the oblique pixel resolution at the current position in meters/pixel.
Definition: Camera.cpp:704
virtual ~Camera()
Destroys the Camera Object.
Definition: Camera.cpp:124
QString instrumentNameLong() const
This method returns the full instrument name.
Definition: Camera.cpp:2898
double p_maxobliqueres
The maximum oblique resolution.
Definition: Camera.h:534
virtual double exposureDuration(const double sample, const double line, const int band) const
This virtual method is for returning the exposure duration of a given pixel.
CameraDistortionMap * p_distortionMap
A pointer to the DistortionMap.
Definition: Camera.h:573
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
void createCache(iTime startTime, iTime endTime, const int size, double tol)
This method creates an internal cache of spacecraft and sun positions over a specified time range...
Definition: Spice.cpp:574
double ObliqueSampleResolution()
Returns the oblique sample resolution at the current position in m.
Definition: Camera.cpp:656
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
double kilometers() const
Get the distance in kilometers.
Definition: Distance.cpp:118
int AlphaSamples() const
Returns the number of samples in the alpha cube.
Definition: AlphaCube.h:93
double p_minRingLongitude180
The minimum ring longitude in the 180 domain.
Definition: Camera.h:564
bool IntersectsLongitudeDomain(Pvl &pvl)
Checks whether the ground range intersects the longitude domain or not.
Definition: Camera.cpp:1184
double DetectorSample() const
Return detector sample.
Distance measurement, usually in meters.
Definition: Distance.h:47
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
bool RawFocalPlanetoImage()
Computes the image coordinate for the current universal ground point.
Definition: Camera.cpp:471
double p_maxres
The maximum resolution.
Definition: Camera.h:532
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
static double GroundAzimuth(double glat, double glon, double slat, double slon)
Computes and returns the ground azimuth between the ground point and another point of interest...
Definition: Camera.cpp:2256
virtual bool SetDetector(const double sample, const double line)
Compute distorted focal plane coordinate from detector position (sampel,line)
bool SetGround(Latitude latitude, Longitude longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:417
double BetaLine(double alphaLine)
Returns a beta line given an alpha line.
Definition: AlphaCube.h:149
int ParentLines() const
Returns the number of lines in the parent alphacube.
Definition: Camera.cpp:2818
This class is used to rewrite the "alpha" keywords out of the AlphaCube group or Instrument group...
Definition: AlphaCube.h:62
virtual double SampleScaleFactor() const
Return scaling factor for computing sample resolution.
CameraSkyMap * SkyMap()
Returns a pointer to the CameraSkyMap object.
Definition: Camera.cpp:2878
double AlphaLine(double betaLine)
Returns an alpha line given a beta line.
Definition: AlphaCube.h:125
double p_minRingLongitude
The minimum ring longitude (azimuth)
Definition: Camera.h:562
int p_bands
The number of bands in the image.
Definition: Camera.h:544
bool HasReferenceBand() const
Checks to see if the Camera object has a reference band.
Definition: Camera.cpp:2682
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition: Sensor.cpp:282
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:396
void setHasIntersection(bool b)
Sets the flag to indicate whether this ShapeModel has an intersection.
Definition: ShapeModel.cpp:548
double EmissionAngle() const
Returns the emission angle in degrees.
Definition: Sensor.cpp:339
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:539
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:170
Convert between parent image coordinates and detector coordinates.
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
bool p_ignoreProjection
Whether or no to ignore the Projection.
Definition: Camera.h:549
virtual bool SetGround(const Latitude &lat, const Longitude &lon)
Compute undistorted focal plane coordinate from ground position.
CameraDetectorMap * p_detectorMap
A pointer to the DetectorMap.
Definition: Camera.h:575
Convert between undistorted focal plane and ground coordinates.
double p_minlat
The minimum latitude.
Definition: Camera.h:527
double FocalPlaneY() const
Gets the y-value in the focal plane coordinate system.
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
Convert between distorted focal plane and detector coordinates.
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
Target * target() const
Returns a pointer to the target object.
Definition: Spice.cpp:1290
QString m_instrumentNameShort
Shortened instrument name.
Definition: Camera.h:508
CameraGroundMap * GroundMap()
Returns a pointer to the CameraGroundMap object.
Definition: Camera.cpp:2868
virtual bool SetUndistortedFocalPlane(double ux, double uy)
Compute distorted focal plane x/y.
QString instrumentId()
This method returns the InstrumentId as it appears in the cube.
Definition: Camera.cpp:2888
virtual bool SetSky(const double ra, const double dec)
Compute undistorted focal plane coordinate from ra/dec.
double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
void ringRangeResolution()
Analogous to above GroundRangeResolution method.
Definition: Camera.cpp:1001
void subSolarPoint(double &lat, double &lon)
Returns the sub-solar latitude/longitude in universal coordinates (0-360 positive east...
Definition: Spice.cpp:1251
double HighestImageResolution()
Returns the highest/best resolution in the entire image.
Definition: Camera.cpp:729
double p_pixelPitch
The pixel pitch, in millimeters per pixel.
Definition: Camera.h:525
SpiceInt naifIkCode() const
This returns the NAIF IK code to use when reading from instrument kernels.
Definition: Spice.cpp:893
bool GroundRange(double &minlat, double &maxlat, double &minlon, double &maxlon, Pvl &pvl)
Computes the Ground Range.
Definition: Camera.cpp:1201
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
bool RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec)
Computes the RaDec range.
Definition: Camera.cpp:1726
virtual bool SetFocalPlane(double dx, double dy)
Compute undistorted focal plane x/y.
bool IsSky() const
Returns true if projection is sky and false if it is land.
Definition: Projection.cpp:223
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2702
double AlphaSample(double betaSample)
Returns an alpha sample given a beta sample.
Definition: AlphaCube.h:137
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
A single keyword-value pair.
Definition: PvlKeyword.h:98
int BetaSamples() const
Returns the number of samples in the beta cube.
Definition: AlphaCube.h:113
CameraFocalPlaneMap * p_focalPlaneMap
A pointer to the FocalPlaneMap.
Definition: Camera.h:574
QString m_instrumentId
The InstrumentId as it appears on the cube.
Definition: Camera.h:505
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
double FocalLength() const
Returns the focal length.
Definition: Camera.cpp:2744
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
void SetFocalPlaneMap(CameraFocalPlaneMap *map)
Sets the Focal Plane Map.
Definition: Camera.cpp:2369
int p_childBand
Band value for child.
Definition: Camera.h:572
void GetLocalNormal(double normal[3])
This method will find the local normal at the current (sample, line) and set it to the passed in arra...
Definition: Camera.cpp:1507
double HighestObliqueImageResolution()
Returns the highest/best oblique resolution in the entire image.
Definition: Camera.cpp:751
double FocalPlaneX() const
QString spacecraftNameLong() const
This method returns the full spacecraft name.
Definition: Camera.cpp:2918
Distort/undistort focal plane coordinates.
double NorthAzimuth()
Returns the North Azimuth.
Definition: Camera.cpp:1912
std::pair< double, double > StartEndEphemerisTimes()
Calculates the start and end ephemeris times.
Definition: Camera.cpp:2491
double p_childSample
Sample value for child.
Definition: Camera.h:570
AlphaCube * p_alphaCube
A pointer to the AlphaCube.
Definition: Camera.h:569
double PixelPitch() const
Returns the pixel pitch.
Definition: Camera.cpp:2754
int ParentSamples() const
Returns the number of samples in the parent alphacube.
Definition: Camera.cpp:2828
bool isValid() const
Test if this distance has been initialized or not.
Definition: Distance.cpp:204
ShapeModel * shape() const
Return the shape.
Definition: Target.cpp:615
void setTime(const iTime &time)
By setting the time you essential set the position of the spacecraft and body as indicated in the cla...
Definition: Sensor.cpp:112
virtual bool isDEM() const =0
Indicates whether this shape model is from a DEM.
void BasicMapping(Pvl &map)
Writes the basic mapping group to the specified Pvl.
Definition: Camera.cpp:1375
Container for cube-like labels.
Definition: Pvl.h:135
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
virtual void clearSurfacePoint()
Clears or resets the current surface point.
Definition: ShapeModel.cpp:380
double SpacecraftAltitude()
Returns the distance from the spacecraft to the subspacecraft point in km.
Definition: Sensor.cpp:712
double ParentSample() const
Return parent sample.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition: Constants.h:59
CameraFocalPlaneMap * FocalPlaneMap()
Returns a pointer to the CameraFocalPlaneMap object.
Definition: Camera.cpp:2848
int Band()
Returns the current band.
Definition: Camera.cpp:2712
void LoadCache()
This loads the spice cache big enough for this image.
Definition: Camera.cpp:2432
bool p_groundRangeComputed
Flag showing if ground range was computed successfully.
Definition: Camera.h:538
Define shapes and provide utilities for Isis3 targets.
Definition: ShapeModel.h:78
double ComputeAzimuth(const double lat, const double lon)
Computes the image azimuth value from your current position (origin) to a point of interest specified...
Definition: Camera.cpp:2059
double CelestialNorthClockAngle()
Computes the celestial north clock angle at the current line/sample or ra/dec.
Definition: Camera.cpp:3049
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:512
Defines an angle and provides unit conversions.
Definition: Angle.h:62
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double p_maxra
The maxumum right ascension.
Definition: Camera.h:554
double LowestObliqueImageResolution()
Returns the lowest/worst oblique resolution in the entire image.
Definition: Camera.cpp:740
double BetaSample(double alphaSample)
Returns a beta sample given an alpha sample.
Definition: AlphaCube.h:161
QString name() const
Gets the shape name.
Definition: ShapeModel.cpp:537
QString m_spacecraftNameLong
Full spacecraft name.
Definition: Camera.h:509
int p_samples
The number of samples in the image.
Definition: Camera.h:542
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
virtual bool IsBandIndependent()
Virtual method that checks if the band is independent.
Definition: Camera.cpp:2661
bool SetImageMapProjection(const double sample, const double line, ShapeModel *shape)
Sets the sample/line values of the image to get the lat/lon values for a Map Projected image...
Definition: Camera.cpp:310
double ParentLine() const
Return parent line.
Base class for Map Projections of plane shapes.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
double p_maxlon
The maximum longitude.
Definition: Camera.h:530
void SetDistortionMap(CameraDistortionMap *map, bool deleteExisting=true)
Sets the Distortion Map.
Definition: Camera.cpp:2354
double FocalPlaneX() const
Definition: CameraSkyMap.h:63
double LowestImageResolution()
Returns the lowest/worst resolution in the entire image.
Definition: Camera.cpp:718
CameraGroundMap * p_groundMap
A pointer to the GroundMap.
Definition: Camera.h:576
double p_maxRingLongitude180
The maximum ring longitude in the 180 domain.
Definition: Camera.h:565
int Bands() const
Returns the number of bands in the image.
Definition: Camera.cpp:2808
QString spacecraftNameShort() const
This method returns the shortened spacecraft name.
Definition: Camera.cpp:2928
double Line()
Returns the current line number.
Definition: Camera.cpp:2722
int lineCount() const
Definition: Cube.cpp:1379
int Lines() const
Returns the number of lines in the image.
Definition: Camera.cpp:2798
int Samples() const
Returns the number of samples in the image.
Definition: Camera.cpp:2788
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Definition: NaifStatus.cpp:43
double RaDecResolution()
Returns the RaDec resolution.
Definition: Camera.cpp:1868
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
double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition: Camera.cpp:689
Isis exception class.
Definition: IException.h:107
SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Definition: Sensor.cpp:270
double p_minres
The minimum resolution.
Definition: Camera.h:531
double p_minlon180
The minimum longitude in the 180 domain.
Definition: Camera.h:535
Adds specific functionality to C++ strings.
Definition: IString.h:181
SpiceInt naifBodyCode() const
This returns the NAIF body code of the target indicated in the labels.
Definition: Spice.cpp:866
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
virtual bool SetDetector(const double sample, const double line)
Compute parent position from a detector coordinate.
double p_minra
The minimum right ascension.
Definition: Camera.h:553
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition: Cube.cpp:1125
bool p_ringRangeComputed
Flag showing if ring range was computed successfully.
Definition: Camera.h:567
double LineResolution()
Returns the line resolution at the current position in meters.
Definition: Camera.cpp:667
virtual int SpkCenterId() const
Provides the center of motion body for SPK NAIF kernel.
Definition: Camera.cpp:3017
virtual double LineScaleFactor() const
Return scaling factor for computing line resolution.
Convert between undistorted focal plane and ra/dec coordinates.
Definition: CameraSkyMap.h:48
double DetectorLine() const
Return detector line.
QString m_spacecraftNameShort
Shortened spacecraft name.
Definition: Camera.h:510
The distance is being specified in meters.
Definition: Distance.h:56
void IgnoreProjection(bool ignore)
Set whether or not the camera should ignore the Projection.
Definition: Camera.cpp:2937
double p_maxRingRadius
The maximum ring radius.
Definition: Camera.h:561
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
virtual QList< QPointF > PixelIfovOffsets()
Returns the pixel ifov offsets from center of pixel, which defaults to the (pixel pitch * summing mod...
Definition: Camera.cpp:2767
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition: Angle.h:80
double kilometers() const
Get the displacement in kilometers.
virtual double exposureDuration() const
Return the exposure duration for the pixel that the camera is set to.
Definition: Camera.cpp:3075
Projection * p_projection
A pointer to the Projection.
Definition: Camera.h:548
SpiceInt naifSpkCode() const
This returns the NAIF SPK code to use when reading from SPK kernels.
Definition: Spice.cpp:875
void SetGeometricTilingHint(int startSize=128, int endSize=8)
This method sets the best geometric tiling size for projecting from this camera model.
Definition: Camera.cpp:2566
double p_minRingRadius
The minimum ring radius.
Definition: Camera.h:560
double p_maxdec
The maximum declination.
Definition: Camera.h:552
bool SetImageSkyMapProjection(const double sample, const double line, ShapeModel *shape)
Sets the sample/line values of the image to get the lat/lon values for a Skymap Projected image...
Definition: Camera.cpp:371
int ReferenceBand() const
Returns the reference band.
Definition: Camera.cpp:2671
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition: Spice.h:377
double UndistortedFocalPlaneY() const
Gets the y-value in the undistorted focal plane coordinate system.
int p_geometricTilingStartSize
The ideal geometric tile size to start with when projecting.
Definition: Camera.h:580
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition: Spice.cpp:855
CameraSkyMap * p_skyMap
A pointer to the SkyMap.
Definition: Camera.h:577
double UndistortedFocalPlaneX() const
Gets the x-value in the undistorted focal plane coordinate system.
double SampleResolution()
Returns the sample resolution at the current position in meters.
Definition: Camera.cpp:645
double Et() const
Returns the ephemeris time (TDB) representation of the time as a double.
Definition: iTime.h:139
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition: Camera.cpp:2692
bool hasNormal() const
Returns surface point normal status.
Definition: ShapeModel.cpp:372
double UniversalRingLongitude()
This returns a universal ring longitude (clockwise in 0 to 360 domain).
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:559
bool p_pointComputed
Flag showing if Sample/Line has been computed.
Definition: Camera.h:540
double p_childLine
Line value for child.
Definition: Camera.h:571
bool p_raDecRangeComputed
Flag showing if the raDec range has been computed successfully.
Definition: Camera.h:558
void GetGeometricTilingHint(int &startSize, int &endSize)
This will get the geometric tiling hint; these values are typically used for ProcessRubberSheet::SetT...
Definition: Camera.cpp:2617
double DetectorResolution()
Returns the detector resolution at the current position in meters.
Definition: Camera.cpp:624
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition: Sensor.cpp:201
SpiceDouble getDouble(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition: Spice.cpp:963
std::vector< Distance > radii() const
Returns the radii of the body in km.
Definition: Target.cpp:522
void GroundRangeResolution()
Computes the ground range and min/max resolution.
Definition: Camera.cpp:760
int p_geometricTilingEndSize
The ideal geometric tile size to end with when projecting.
Definition: Camera.h:582
double ObliqueDetectorResolution()
This method returns the Oblique Detector Resolution if the Look Vector intersects the target and if t...
Definition: Camera.cpp:598
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double Declination()
Returns the declination angle (sky latitude).
Definition: Sensor.cpp:587
These projections are used to map triaxial and irregular-shaped bodies.
Definition: Projection.h:182
double FocalPlaneX() const
Gets the x-value in the focal plane coordinate system.
IO Handler for Isis Cubes.
Definition: Cube.h:170
iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions...
Definition: Spice.cpp:809
void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east...
Definition: Spice.cpp:1202