Isis 3 Programmer Reference
Camera.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Camera.h"
8
9
10#include <algorithm>
11#include <cfloat>
12#include <cmath>
13#include <iomanip>
14#include <stdint.h>
15
16#include <QDebug>
17#include <QList>
18#include <QPair>
19#include <QString>
20#include <QTime>
21#include <QVector>
22
23#include "MathUtils.h"
24
25#include "Angle.h"
26#include "Constants.h"
27#include "CameraDetectorMap.h"
28#include "CameraFocalPlaneMap.h"
29#include "CameraDistortionMap.h"
30#include "CameraGroundMap.h"
31#include "CameraSkyMap.h"
32#include "DemShape.h"
33#include "IException.h"
34#include "IString.h"
35#include "iTime.h"
36#include "Latitude.h"
37#include "Longitude.h"
38#include "NaifStatus.h"
39#include "Projection.h"
40#include "ProjectionFactory.h"
41#include "RingPlaneProjection.h"
42#include "ShapeModel.h"
43#include "SpecialPixel.h"
44#include "SurfacePoint.h"
45#include "Target.h"
46#include "TProjection.h"
47
48using namespace std;
49
50namespace Isis {
51
56 Camera::Camera(Cube &cube) : Sensor(cube) {
57
58 m_instrumentId = cube.label()->findGroup("Instrument",
59 PvlObject::FindOptions::Traverse).findKeyword("InstrumentId")[0];
60
61 m_instrumentNameLong = "Unknown";
62 m_instrumentNameShort = "Unknown";
63 m_spacecraftNameLong = "Unknown";
64 m_spacecraftNameShort = "Unknown";
65 // Get the image size which can be different than the alpha cube size
66 p_lines = cube.lineCount();
67 p_samples = cube.sampleCount();
68 p_bands = cube.bandCount();
69
71
72 // Get the AlphaCube information
73 p_alphaCube = new AlphaCube(cube);
74
75 // Get the projection group if it exists
76 Pvl &lab = *cube.label();
77 if (lab.findObject("IsisCube").hasGroup("Mapping")) {
79 }
80 else {
81 p_projection = NULL;
82 }
83 p_ignoreProjection = false;
84
85 // Initialize stuff
86 p_focalLength = 0.0;
87 p_pixelPitch = 1.0;
89 p_childBand = 1;
90
91 p_distortionMap = NULL;
92 p_focalPlaneMap = NULL;
93 p_detectorMap = NULL;
94 p_groundMap = NULL;
95 p_skyMap = NULL;
96
97 // See if we have a reference band
98 PvlGroup &inst = lab.findObject("IsisCube").findGroup("Instrument");
99 if (inst.hasKeyword("ReferenceBand")) {
100 p_referenceBand = inst["ReferenceBand"];
101 }
102
103 p_groundRangeComputed = false;
104 p_raDecRangeComputed = false;
105 p_ringRangeComputed = false;
106 p_pointComputed = false;
107 }
108
111 if (p_projection) {
112 delete p_projection;
113 p_projection = NULL;
114 }
115
116 if (p_alphaCube) {
117 delete p_alphaCube;
118 p_alphaCube = NULL;
119 }
120
121 if (p_distortionMap) {
122 delete p_distortionMap;
123 p_distortionMap = NULL;
124 }
125
126 if (p_focalPlaneMap) {
127 delete p_focalPlaneMap;
128 p_focalPlaneMap = NULL;
129 }
130
131 if (p_detectorMap) {
132 delete p_detectorMap;
133 p_detectorMap = NULL;
134 }
135
136 if (p_groundMap) {
137 delete p_groundMap;
138 p_groundMap = NULL;
139 }
140
141 if (p_skyMap) {
142 delete p_skyMap;
143 p_skyMap = NULL;
144 }
145 }
146
147
156 bool Camera::SetImage(const double sample, const double line) {
157 p_childSample = sample;
158 p_childLine = line;
159 p_pointComputed = true;
160
161 // get shape
162 // TODO: we need to validate this pointer (somewhere)
163 ShapeModel *shape = target()->shape();
164 shape->clearSurfacePoint(); // Set initial condition for ShapeModel
165
166 // Case of no map projection
167 if (p_projection == NULL || p_ignoreProjection) {
168 // Convert to parent coordinate (remove crop, pad, shrink, enlarge)
169 double parentSample = p_alphaCube->AlphaSample(sample);
170 double parentLine = p_alphaCube->AlphaLine(line);
171 bool success = false;
172 success = p_detectorMap->SetParent(parentSample, parentLine);
173 // Convert from parent to detector
174 if (success) {
175 double detectorSample = p_detectorMap->DetectorSample();
176 double detectorLine = p_detectorMap->DetectorLine();
177 success = p_focalPlaneMap->SetDetector(detectorSample, detectorLine);
178 // Now Convert from detector to distorted focal plane
179 if (success) {
180 double focalPlaneX = p_focalPlaneMap->FocalPlaneX();
181 double focalPlaneY = p_focalPlaneMap->FocalPlaneY();
182 success = p_distortionMap->SetFocalPlane(focalPlaneX, focalPlaneY);
183 // Remove optical distortion
184 if (success) {
185 // Map to the ground
189 return p_groundMap->SetFocalPlane(x, y, z);
190 }
191 }
192 }
193 }
194
195 // The projection is a sky map
196 else if (p_projection->IsSky()) {
197 return SetImageSkyMapProjection(sample, line, shape);
198 }
199
200 // We have map projected camera model
201 else {
202 return SetImageMapProjection(sample, line, shape);
203 }
204
205 // failure
206 shape->clearSurfacePoint();
207 return false;
208 }
209
210
230 bool Camera::SetImage(const double sample, const double line, const double deltaT) {
231 p_childSample = sample;
232 p_childLine = line;
233 p_pointComputed = true;
234
235 // get shape
236 // TODO: we need to validate this pointer (somewhere)
237 ShapeModel *shape = target()->shape();
238 shape->clearSurfacePoint(); // Set initial condition for ShapeModel
239
240 // Case of no map projection
241 if (p_projection == NULL || p_ignoreProjection) {
242 // Convert to parent coordinate (remove crop, pad, shrink, enlarge)
243 double parentSample = p_alphaCube->AlphaSample(sample);
244 double parentLine = p_alphaCube->AlphaLine(line);
245 bool success = false;
246 success = p_detectorMap->SetParent(parentSample, parentLine, deltaT);
247 // Convert from parent to detector
248 if (success) {
249 double detectorSample = p_detectorMap->DetectorSample();
250 double detectorLine = p_detectorMap->DetectorLine();
251 success = p_focalPlaneMap->SetDetector(detectorSample, detectorLine);
252 // Now Convert from detector to distorted focal plane
253 if (success) {
254 double focalPlaneX = p_focalPlaneMap->FocalPlaneX();
255 double focalPlaneY = p_focalPlaneMap->FocalPlaneY();
256 success = p_distortionMap->SetFocalPlane(focalPlaneX, focalPlaneY);
257 // Remove optical distortion
258 if (success) {
259 // Map to the ground
263 return p_groundMap->SetFocalPlane(x, y, z);
264 }
265 }
266 }
267 }
268
269 // The projection is a sky map
270 else if (p_projection->IsSky()) {
271 return SetImageSkyMapProjection(sample, line, shape);
272 }
273
274 // We have map projected camera model
275 else {
276 return SetImageMapProjection(sample, line, shape);
277 }
278
279 // failure
280 shape->clearSurfacePoint();
281 return false;
282 }
283
284
296 bool Camera::SetImageMapProjection(const double sample, const double line, ShapeModel *shape) {
297 Latitude lat;
298 Longitude lon;
299 Distance rad;
300 if (shape->name() != "Plane") { // this is the normal behavior
301 if (p_projection->SetWorld(sample, line)) {
303 lat = Latitude(tproj->UniversalLatitude(), Angle::Degrees);
304 lon = Longitude(tproj->UniversalLongitude(), Angle::Degrees);
305 rad = Distance(LocalRadius(lat, lon));
306 if (!rad.isValid()) {
307 shape->setHasIntersection(false);
308 return false;
309 }
310 SurfacePoint surfPt(lat, lon, rad);
311 if (SetGround(surfPt)) {
312 p_childSample = sample;
313 p_childLine = line;
314
315 shape->setHasIntersection(true);
316 return true;
317 }
318 }
319 }
320 else { // shape is ring plane
321 if (p_projection->SetWorld(sample, line)) {
323 lat = Latitude(0.0, Angle::Degrees);
324 lon = Longitude(rproj->UniversalRingLongitude(), Angle::Degrees);
325 rad = Distance(rproj->UniversalRingRadius(),Distance::Meters);
326
327 if (!rad.isValid()) {
328 shape->setHasIntersection(false);
329 return false;
330 }
331 SurfacePoint surfPt(lat, lon, rad);
332 if (SetGround(surfPt)) {
333 p_childSample = sample;
334 p_childLine = line;
335
336 shape->setHasIntersection(true);
337 return true;
338 }
339 }
340 }
341 shape->clearSurfacePoint();
342 return false;
343 }
344
345
357 bool Camera::SetImageSkyMapProjection(const double sample, const double line, ShapeModel *shape) {
359 if (tproj->SetWorld(sample, line)) {
360 if (SetRightAscensionDeclination(tproj->Longitude(),
361 tproj->UniversalLatitude())) {
362 p_childSample = sample;
363 p_childLine = line;
364
365 return HasSurfaceIntersection();
366 }
367 }
368 shape->clearSurfacePoint();
369 return false;
370 }
371
372
382 bool Camera::SetUniversalGround(const double latitude, const double longitude) {
383 // Convert lat/lon or rad/az (i.e. ring rad / ring lon) to undistorted focal plane x/y
385 Longitude(longitude, Angle::Degrees))) {
386 return RawFocalPlanetoImage();
387 }
388
389 target()->shape()->clearSurfacePoint();
390 return false;
391 }
392
393
403 bool Camera::SetGround(Latitude latitude, Longitude longitude) {
404 ShapeModel *shape = target()->shape();
405 Distance localRadius;
406
407 if (shape->name() != "Plane") { // this is the normal behavior
408 localRadius = LocalRadius(latitude, longitude);
409 }
410 else {
411 localRadius = Distance(latitude.degrees(),Distance::Kilometers);
412 latitude = Latitude(0.,Angle::Degrees);
413 }
414
415 if (!localRadius.isValid()) {
416 target()->shape()->clearSurfacePoint();
417 return false;
418 }
419
420 return SetGround(SurfacePoint(latitude, longitude, localRadius));
421 }
422
423
424
433 bool Camera::SetGround(const SurfacePoint & surfacePt) {
434 ShapeModel *shape = target()->shape();
435 if (!surfacePt.Valid()) {
436 shape->clearSurfacePoint();
437 return false;
438 }
439
440 // Convert lat/lon to undistorted focal plane x/y
441 if (p_groundMap->SetGround(surfacePt)) {
442 return RawFocalPlanetoImage();
443 }
444
445 shape->clearSurfacePoint();
446 return false;
447 }
448
449
458 double ux = p_groundMap->FocalPlaneX();
459 double uy = p_groundMap->FocalPlaneY();
460
461 // get shape
462 // TODO: we need to validate this pointer (somewhere)
463 ShapeModel *shape = target()->shape();
464
465 // Convert undistorted x/y to distorted x/y
466 bool success = p_distortionMap->SetUndistortedFocalPlane(ux, uy);
467 if (success) {
468 double focalPlaneX = p_distortionMap->FocalPlaneX();
469 double focalPlaneY = p_distortionMap->FocalPlaneY();
470 // Convert distorted x/y to detector position
471 success = p_focalPlaneMap->SetFocalPlane(focalPlaneX, focalPlaneY);
472 if (success) {
473 double detectorSample = p_focalPlaneMap->DetectorSample();
474 double detectorLine = p_focalPlaneMap->DetectorLine();
475 // Convert detector to parent position
476 success = p_detectorMap->SetDetector(detectorSample, detectorLine);
477 if (success) {
478 double parentSample = p_detectorMap->ParentSample();
479 double parentLine = p_detectorMap->ParentLine();
480 if (p_projection == NULL || p_ignoreProjection) {
481 p_childSample = p_alphaCube->BetaSample(parentSample);
482 p_childLine = p_alphaCube->BetaLine(parentLine);
483 p_pointComputed = true;
484 shape->setHasIntersection(true);
485 return true;
486 }
487 else if (p_projection->IsSky()) {
488 if (p_projection->SetGround(Declination(), RightAscension())) {
491 p_pointComputed = true;
492 shape->setHasIntersection(true);
493 return true;
494 }
495 }
500 p_pointComputed = true;
501 shape->setHasIntersection(true);
502 return true;
503 }
504 }
505 else { // ring plane
506 // UniversalLongitude should return azimuth (ring longitude) in this case
507 // TODO:
508 // when we make the change to real azimuths this value may need to be adjusted or
509 // code changed in the shapemodel or surfacepoint class.
513 p_pointComputed = true;
514 shape->setHasIntersection(true);
515 return true;
516 }
517 }
518 }
519 }
520 }
521
522 shape->clearSurfacePoint();
523 return false;
524 }
525
526
527
538 bool Camera::SetUniversalGround(const double latitude, const double longitude,
539 const double radius) {
540 // Convert lat/lon to undistorted focal plane x/y
542 Longitude(longitude, Angle::Degrees),
543 Distance(radius, Distance::Meters)))) {
544 return RawFocalPlanetoImage(); // sets p_hasIntersection
545 }
546
547 target()->shape()->clearSurfacePoint();
548 return false;
549 }
550
551
552
583 double Camera::ObliqueDetectorResolution(bool useLocal) {
584
585
587 return Isis::Null;
588 }
589
590 double thetaRad;
591 double emissionDeg;
592
593 if(useLocal) {
594 Angle phase, emission, incidence;
595 bool success;
596
597 LocalPhotometricAngles(phase, incidence, emission, success);
598 emissionDeg = (success) ? emission.degrees() : Isis::Null;
599 }
600 else {
601 emissionDeg = EmissionAngle();
602 }
603
604 thetaRad = emissionDeg*DEG2RAD;
605
606 if (thetaRad < HALFPI) {
607 return DetectorResolution()/cos(thetaRad);
608
609 }
610
611 return Isis::Null;
612
613
614 }
615
616
624 double sB[3];
626 double pB[3];
627 Coordinate(pB);
628 double dist = SensorUtilities::distance(sB, pB) * 1000.0;
629 return dist / (p_focalLength / p_pixelPitch);
630 }
631 return Isis::Null;
632 }
633
634
643
650 double Camera::ObliqueSampleResolution(bool useLocal) {
652 }
653
654
663
664
672 double Camera::ObliqueLineResolution(bool useLocal) {
674 }
675
676
682 double lineRes = LineResolution();
683 double sampRes = SampleResolution();
684 if (lineRes < 0.0) return Isis::Null;
685 if (sampRes < 0.0) return Isis::Null;
686 return (lineRes + sampRes) / 2.0;
687 }
688
689
696 double Camera::ObliquePixelResolution(bool useLocal) {
697 double lineRes = ObliqueLineResolution(useLocal);
698 double sampRes = ObliqueSampleResolution(useLocal);
699 if (lineRes < 0.0) return Isis::Null;
700 if (sampRes < 0.0) return Isis::Null;
701 return (lineRes + sampRes) / 2.0;
702 }
703
704
714
715
725
726
736
737
747
748
753 // Software adjustment is needed if we get here -- call RingRangeResolution instead
754 if (target()->shape()->name() == "Plane") {
755 IString msg = "Images with plane targets should use Camera method RingRangeResolution ";
756 msg += "instead of GroundRangeResolution";
757 throw IException(IException::Programmer, msg, _FILEINFO_);
758 }
759
760 // Have we already done this
761 if (p_groundRangeComputed) return;
763
764 bool computed = p_pointComputed;
765 double originalSample = Sample();
766 double originalLine = Line();
767 int originalBand = Band();
768
769 // Initializations
770 p_minlat = DBL_MAX;
771 p_minlon = DBL_MAX;
772 p_minlon180 = DBL_MAX;
773 p_maxlat = -DBL_MAX;
774 p_maxlon = -DBL_MAX;
775 p_maxlon180 = -DBL_MAX;
776 p_minres = DBL_MAX;
777 p_maxres = -DBL_MAX;
778 p_minobliqueres = DBL_MAX;
779 p_maxobliqueres = -DBL_MAX;
780
781 // See if we have band dependence and loop for the appropriate number of bands
782 int eband = p_bands;
783 if (IsBandIndependent()) eband = 1;
784 for (int band = 1; band <= eband; band++) {
785 SetBand(band);
786
787 // Loop for each line testing the left and right sides of the image
788 for (int line = 1; line <= p_lines + 1; line++) {
789 // Look for the first good lat/lon on the left edge of the image
790 // If it is the first or last line then test the whole line
791 int samp;
792 for (samp = 1; samp <= p_samples + 1; samp++) {
793
794 if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
795 double lat = UniversalLatitude();
796 double lon = UniversalLongitude();
797 if (lat < p_minlat) p_minlat = lat;
798 if (lat > p_maxlat) p_maxlat = lat;
799 if (lon < p_minlon) p_minlon = lon;
800 if (lon > p_maxlon) p_maxlon = lon;
801
802 if (lon > 180.0) lon -= 360.0;
803 if (lon < p_minlon180) p_minlon180 = lon;
804 if (lon > p_maxlon180) p_maxlon180 = lon;
805
806 double res = PixelResolution();
807 if (res > 0.0) {
808 if (res < p_minres) p_minres = res;
809 if (res > p_maxres) p_maxres = res;
810 }
811 // Determine min/max oblique resolution
812 double obliqueres = ObliquePixelResolution();
813 if (obliqueres > 0.0) {
814 if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
815 if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
816
817 }
818 if ((line != 1) && (line != p_lines + 1)) break;
819 }
820 } // end loop through samples
821
822 //We've already checked the first and last lines.
823 if (line == 1) continue;
824 if (line == p_lines + 1) continue;
825
826 // Look for the first good lat/lon on the right edge of the image
827 if (samp < p_samples + 1) {
828 for (samp = p_samples + 1; samp >= 1; samp--) {
829 if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
830 double lat = UniversalLatitude();
831 double lon = UniversalLongitude();
832 if (lat < p_minlat) p_minlat = lat;
833 if (lat > p_maxlat) p_maxlat = lat;
834 if (lon < p_minlon) p_minlon = lon;
835 if (lon > p_maxlon) p_maxlon = lon;
836
837 if (lon > 180.0) lon -= 360.0;
838 if (lon < p_minlon180) p_minlon180 = lon;
839 if (lon > p_maxlon180) p_maxlon180 = lon;
840
841 double res = PixelResolution();
842 if (res > 0.0) {
843 if (res < p_minres) p_minres = res;
844 if (res > p_maxres) p_maxres = res;
845 }
846
847 // Determine min/max oblique resolution
848 double obliqueres = ObliquePixelResolution();
849 if (obliqueres > 0.0) {
850 if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
851 if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
852
853 }
854 break;
855 }
856 }
857 }
858 } // end loop through lines
859
860 // Test at the sub-spacecraft point to see if we have a
861 // better resolution
862 double lat, lon;
863
864 subSpacecraftPoint(lat, lon);
865 Latitude latitude(lat, Angle::Degrees);
866 Longitude longitude(lon, Angle::Degrees);
867 // get the local radius for the subspacecraft point
868 Distance radius(LocalRadius(latitude, longitude));
869 SurfacePoint testPoint;
870
871 if (radius.isValid()) {
872
873 testPoint = SurfacePoint(latitude, longitude, radius);
874
875 if (SetGround(testPoint)) {
876 if (Sample() >= 0.5 && Line() >= 0.5 &&
877 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
878 double res = PixelResolution();
879 if (res > 0.0) {
880 if (res < p_minres) p_minres = res;
881 if (res > p_maxres) p_maxres = res;
882 }
883
884 double obliqueres = ObliquePixelResolution();
885 if (obliqueres > 0.0) {
886 if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres;
887 if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres;
888
889 }
890 }
891 }
892 } // end valid local (subspacecraft) radius
893
894 // Special test for ground range to see if either pole is in the image
895 latitude = Latitude(90, Angle::Degrees);
896 longitude = Longitude(0.0, Angle::Degrees);
897 // get radius for north pole
898 radius = LocalRadius(latitude, longitude);
899
900 if (radius.isValid()) {
901
902 testPoint = SurfacePoint(latitude, longitude, radius);
903
904 if (SetGround(testPoint)) {
905 if (Sample() >= 0.5 && Line() >= 0.5 &&
906 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
907 p_maxlat = 90.0;
908 p_minlon = 0.0;
909 p_maxlon = 360.0;
910 p_minlon180 = -180.0;
911 p_maxlon180 = 180.0;
912 }
913 }
914 } // end valid north polar radius
915
916 latitude = Latitude(-90, Angle::Degrees);
917 // get radius for south pole
918 radius = LocalRadius(latitude, longitude);
919
920 if (radius.isValid()) {
921
922 testPoint = SurfacePoint(latitude, longitude, radius);
923 if (SetGround(testPoint)) {
924 if (Sample() >= 0.5 && Line() >= 0.5 &&
925 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
926 p_minlat = -90.0;
927 p_minlon = 0.0;
928 p_maxlon = 360.0;
929 p_minlon180 = -180.0;
930 p_maxlon180 = 180.0;
931 }
932 }
933 } // end valid south polar radius
934
935 // Another special test for ground range as we could have the
936 // 0-360 seam running right through the image so
937 // test it as well (the increment may not be fine enough !!!)
940 lat += Angle((p_maxlat - p_minlat) / 10.0, Angle::Degrees)) {
941 if (SetGround(lat, Longitude(0.0, Angle::Degrees))) {
942 if (Sample() >= 0.5 && Line() >= 0.5 &&
943 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
944 p_minlon = 0.0;
945 p_maxlon = 360.0;
946 break;
947 }
948 } // end if set ground (lat, 0)
949
950 // Another special test for ground range as we could have the
951 // -180-180 seam running right through the image so
952 // test it as well (the increment may not be fine enough !!!)
953 if (SetGround(lat, Longitude(180.0, Angle::Degrees))) {
954 if (Sample() >= 0.5 && Line() >= 0.5 &&
955 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
956 p_minlon180 = -180.0;
957 p_maxlon180 = 180.0;
958 break;
959 }
960 } // end if set ground (lat, 180)
961 } // end for loop (latitudes from min to max)
962 } // end for loop through bands
963
964 SetBand(originalBand);
965
966 if(computed) {
967 SetImage(originalSample, originalLine);
968 }
969 else {
970 p_pointComputed = false;
971 }
972
973 if (p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX || p_maxlat == -DBL_MAX) {
974 string message = "Camera missed planet or SPICE data off.";
975 throw IException(IException::Unknown, message, _FILEINFO_);
976 }
977
978
979 // Checks for invalid lat/lon ranges
980// if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX
981// || p_maxlat == -DBL_MAX)
982// {
983// string message = "Camera missed planet or SPICE data off.";
984// throw IException(IException::Unknown, message, _FILEINFO_);
985// }
986 }
987
988
994 // TODO Add test to make sure we have a ring plane image **
995
996 // Have we already done this
997 if (p_ringRangeComputed) return;
998
999 p_ringRangeComputed = true;
1000
1001 bool computed = p_pointComputed;
1002 double originalSample = Sample();
1003 double originalLine = Line();
1004 int originalBand = Band();
1005
1006 // Initializations
1007 p_minRingRadius = DBL_MAX;
1008 p_minRingLongitude = DBL_MAX;
1009 p_minRingLongitude180 = DBL_MAX;
1010 p_maxRingRadius = -DBL_MAX;
1011 p_maxRingLongitude = -DBL_MAX;
1012 p_maxRingLongitude180 = -DBL_MAX;
1013 p_minres = DBL_MAX;
1014 p_maxres = -DBL_MAX;
1015
1016 // See if we have band dependence and loop for the appropriate number of bands
1017 int eband = p_bands;
1018 if (IsBandIndependent())
1019 eband = 1;
1020
1021 for (int band = 1; band <= eband; band++) {
1022 SetBand(band);
1023
1024 // Loop for each line testing the left and right sides of the image
1025 for (int line = 1; line <= p_lines + 1; line++) {
1026
1027 // Look for the first good radius/azimuth on the left edge of the image
1028 // If it is the first or last line then test the whole line
1029 int samp;
1030 for (samp = 1; samp <= p_samples + 1; samp++) {
1031
1032 if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
1033 double radius = LocalRadius().meters();
1034 double azimuth = UniversalLongitude();
1035 if (radius < p_minRingRadius) p_minRingRadius = radius;
1036 if (radius > p_maxRingRadius) p_maxRingRadius = radius;
1037 if (azimuth < p_minRingLongitude) p_minRingLongitude = azimuth;
1038 if (azimuth > p_maxRingLongitude) p_maxRingLongitude = azimuth;
1039
1040 if (azimuth > 180.0) azimuth -= 360.0;
1041 if (azimuth < p_minRingLongitude180) p_minRingLongitude180 = azimuth;
1042 if (azimuth > p_maxRingLongitude180) p_maxRingLongitude180 = azimuth;
1043
1044 double res = PixelResolution();
1045 if (res > 0.0) {
1046 if (res < p_minres) p_minres = res;
1047 if (res > p_maxres) p_maxres = res;
1048 }
1049 if ((line != 1) && (line != p_lines + 1)) break;
1050 }
1051 }
1052 //We've already checked the first and last lines.
1053 if (line == 1) continue;
1054 if (line == p_lines + 1) continue;
1055
1056 // Look for the first good rad/azimuth on the right edge of the image
1057 if (samp < p_samples + 1) {
1058 for(samp = p_samples + 1; samp >= 1; samp--) {
1059 if (SetImage((double)samp - 0.5, (double)line - 0.5)) {
1060 double radius = LocalRadius().meters();
1061 double azimuth = UniversalLongitude();
1062 if (radius < p_minRingRadius) p_minRingRadius = radius;
1063 if (radius > p_maxRingRadius) p_maxRingRadius = radius;
1064 if (azimuth < p_minRingLongitude) p_minRingLongitude = azimuth;
1065 if (azimuth > p_maxRingLongitude) p_maxRingLongitude = azimuth;
1066
1067 if (azimuth > 180.0) azimuth -= 360.0;
1068 if (azimuth < p_minRingLongitude180) p_minRingLongitude180 = azimuth;
1069 if (azimuth > p_maxRingLongitude180) p_maxRingLongitude180 = azimuth;
1070
1071 double res = PixelResolution();
1072 if (res > 0.0) {
1073 if (res < p_minres) p_minres = res;
1074 if (res > p_maxres) p_maxres = res;
1075 }
1076 break;
1077 }
1078 }
1079 }
1080 }
1081
1082 // Test at the sub-spacecraft point to see if we have a
1083 // better resolution
1084 // TODO: is there something to this analogous for ring images?
1085// double rad, lon;
1086
1087// subSpacecraftPoint(lat, lon);
1088// Latitude latitude(lat, Angle::Degrees);
1089// Longitude longitude(lon, Angle::Degrees);
1090// Distance radius(LocalRadius(latitude, longitude));
1091// SurfacePoint testPoint;
1092
1093// if (radius.isValid()) {
1094
1095// testPoint = SurfacePoint(latitude, longitude, radius);
1096
1097// if(SetGround(testPoint)) {
1098// if(Sample() >= 0.5 && Line() >= 0.5 &&
1099// Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1100// double res = PixelResolution();
1101// if(res > 0.0) {
1102// if(res < p_minres) p_minres = res;
1103// if(res > p_maxres) p_maxres = res;
1104// }
1105// }
1106// }
1107// }
1108
1109 // Another special test for ring range as we could have the
1110 // 0-360 seam running right through the image so
1111 // test it as well (the increment may not be fine enough !!!)
1116 if (Sample() >= 0.5 && Line() >= 0.5 &&
1117 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1118 p_minRingLongitude = 0.0;
1119 p_maxRingLongitude = 360.0;
1120 break;
1121 }
1122 }
1123
1124 // for (Latitude lat = Latitude(p_minlat, Angle::Degrees);
1125 // lat <= Latitude(p_maxlat, Angle::Degrees);
1126 // lat += Angle((p_maxlat - p_minlat) / 10.0, Angle::Degrees)) {
1127 // if (SetGround(lat, Longitude(0.0, Angle::Degrees))) {
1128 // if (Sample() >= 0.5 && Line() >= 0.5 &&
1129 // Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1130 // p_minlon = 0.0;
1131 // p_maxlon = 360.0;
1132 // break;
1133 // }
1134 // }
1135
1136 // Another special test for ring range as we could have the
1137 // -180-180 seam running right through the image so
1138 // test it as well (the increment may not be fine enough !!!)
1140 if (Sample() >= 0.5 && Line() >= 0.5 &&
1141 Sample() <= p_samples + 0.5 && Line() <= p_lines + 0.5) {
1142 p_minRingLongitude180 = -180.0;
1143 p_maxRingLongitude180 = 180.0;
1144 break;
1145 }
1146 }
1147 }
1148 } // end loop over bands
1149
1150 SetBand(originalBand);
1151
1152 if (computed) {
1153 SetImage(originalSample, originalLine);
1154 }
1155 else {
1156 p_pointComputed = false;
1157 }
1158
1159 // Checks for invalid radius/lon ranges
1160 if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX
1161 || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) {
1162 string message = "RingPlane ShapeModel - Camera missed plane or SPICE data off.";
1163 throw IException(IException::Unknown, message, _FILEINFO_);
1164 }
1165 }
1166
1167
1177 double minlat, minlon, maxlat, maxlon;
1178 return GroundRange(minlat, maxlat, minlon, maxlon, pvl);
1179 }
1180
1193 bool Camera::GroundRange(double &minlat, double &maxlat,
1194 double &minlon, double &maxlon,
1195 Pvl &pvl) {
1196 // Compute the ground range and resolution
1198
1199 // Get the default radii
1200 Distance localRadii[3];
1201 radii(localRadii);
1202 Distance &a = localRadii[0];
1203 Distance &b = localRadii[2];
1204
1205 // See if the PVL overrides the radii
1206 PvlGroup map = pvl.findGroup("Mapping", Pvl::Traverse);
1207
1208 if(map.hasKeyword("EquatorialRadius"))
1209 a = Distance(toDouble(map["EquatorialRadius"][0]), Distance::Meters);
1210
1211 if(map.hasKeyword("PolarRadius"))
1212 b = Distance(toDouble(map["PolarRadius"][0]), Distance::Meters);
1213
1214 // Convert to planetographic if necessary
1215 minlat = p_minlat;
1216 maxlat = p_maxlat;
1217 if(map.hasKeyword("LatitudeType")) {
1218 QString latType = (QString) map["LatitudeType"];
1219 if (latType.toUpper() == "PLANETOGRAPHIC") {
1220 if (abs(minlat) < 90.0) { // So tan doesn't fail
1221 minlat *= PI / 180.0;
1222 minlat = atan(tan(minlat) * (a / b) * (a / b));
1223 minlat *= 180.0 / PI;
1224 }
1225
1226 if(abs(maxlat) < 90.0) { // So tan doesn't fail
1227 maxlat *= PI / 180.0;
1228 maxlat = atan(tan(maxlat) * (a / b) * (a / b));
1229 maxlat *= 180.0 / PI;
1230 }
1231 }
1232 }
1233
1234 // Assume 0 to 360 domain but change it if necessary
1235 minlon = p_minlon;
1236 maxlon = p_maxlon;
1237 bool domain360 = true;
1238 if(map.hasKeyword("LongitudeDomain")) {
1239 QString lonDomain = (QString) map["LongitudeDomain"];
1240 if(lonDomain.toUpper() == "180") {
1241 minlon = p_minlon180;
1242 maxlon = p_maxlon180;
1243 domain360 = false;
1244 }
1245 }
1246
1247 // Convert to the proper longitude direction
1248 if(map.hasKeyword("LongitudeDirection")) {
1249 QString lonDirection = (QString) map["LongitudeDirection"];
1250 if(lonDirection.toUpper() == "POSITIVEWEST") {
1251 double swap = minlon;
1252 minlon = -maxlon;
1253 maxlon = -swap;
1254 }
1255 }
1256
1257 // Convert to the proper longitude domain
1258 if(domain360) {
1259 while(minlon < 0.0) {
1260 minlon += 360.0;
1261 maxlon += 360.0;
1262 }
1263 while(minlon > 360.0) {
1264 minlon -= 360.0;
1265 maxlon -= 360.0;
1266 }
1267 }
1268 else {
1269 while(minlon < -180.0) {
1270 minlon += 360.0;
1271 maxlon += 360.0;
1272 }
1273 while(minlon > 180.0) {
1274 minlon -= 360.0;
1275 maxlon -= 360.0;
1276 }
1277 }
1278
1279 // Now return if it crosses the longitude domain boundary
1280 if((maxlon - minlon) > 359.0) return true;
1281 return false;
1282 }
1283
1297 bool Camera::ringRange(double &minRingRadius, double &maxRingRadius,
1298 double &minRingLongitude, double &maxRingLongitude, Pvl &pvl) {
1299 // Compute the ring range and resolution
1301
1302 // Get the mapping group
1303 PvlGroup map = pvl.findGroup("Mapping", Pvl::Traverse);
1304
1305 // Get the ring radius range
1306 minRingRadius = p_minRingRadius;
1307 maxRingRadius = p_maxRingRadius;
1308
1309 // Assume 0 to 360 domain but change it if necessary
1310 minRingLongitude = p_minRingLongitude;
1311 maxRingLongitude = p_maxRingLongitude;
1312 bool domain360 = true;
1313 if (map.hasKeyword("RingLongitudeDomain")) {
1314 QString ringLongitudeDomain = (QString) map["RingLongitudeDomain"];
1315 if (ringLongitudeDomain == "180") {
1316 minRingLongitude = p_minRingLongitude180;
1317 maxRingLongitude = p_maxRingLongitude180;
1318 domain360 = false;
1319 }
1320 }
1321
1322 // Convert to the proper azimuth direction
1323 if (map.hasKeyword("RingLongitudeDirection")) {
1324 QString ringLongitudeDirection = (QString) map["RingLongitudeDirection"];
1325 if (ringLongitudeDirection.toUpper() == "Clockwise") {
1326 double swap = minRingLongitude;
1327 minRingLongitude = -maxRingLongitude;
1328 maxRingLongitude = -swap;
1329 }
1330 }
1331
1332 // Convert to the proper azimuth domain
1333 if (domain360) {
1334 while (minRingLongitude < 0.0) {
1335 minRingLongitude += 360.0;
1336 maxRingLongitude += 360.0;
1337 }
1338 while (minRingLongitude > 360.0) {
1339 minRingLongitude -= 360.0;
1340 maxRingLongitude -= 360.0;
1341 }
1342 }
1343 else {
1344 while (minRingLongitude < -180.0) {
1345 minRingLongitude += 360.0;
1346 maxRingLongitude += 360.0;
1347 }
1348 while (minRingLongitude > 180.0) {
1349 minRingLongitude -= 360.0;
1350 maxRingLongitude -= 360.0;
1351 }
1352 }
1353
1354 // Now return if it crosses the azimuth domain boundary
1355 if ((maxRingLongitude - minRingLongitude) > 359.0) {
1356 return true;
1357 }
1358 return false;
1359 }
1360
1361
1368 PvlGroup map("Mapping");
1369 map += PvlKeyword("TargetName", target()->name());
1370
1371 std::vector<Distance> radii = target()->radii();
1372 map += PvlKeyword("EquatorialRadius", toString(radii[0].meters()), "meters");
1373 map += PvlKeyword("PolarRadius", toString(radii[2].meters()), "meters");
1374
1375 map += PvlKeyword("LatitudeType", "Planetocentric");
1376 map += PvlKeyword("LongitudeDirection", "PositiveEast");
1377 map += PvlKeyword("LongitudeDomain", "360");
1378
1380 map += PvlKeyword("MinimumLatitude", toString(p_minlat));
1381 map += PvlKeyword("MaximumLatitude", toString(p_maxlat));
1382 map += PvlKeyword("MinimumLongitude", toString(p_minlon));
1383 map += PvlKeyword("MaximumLongitude", toString(p_maxlon));
1384 map += PvlKeyword("PixelResolution", toString(p_minres));
1385
1386 map += PvlKeyword("ProjectionName", "Sinusoidal");
1387 pvl.addGroup(map);
1388 }
1389
1390
1397 if (target()->shape()->name() != "Plane") {
1398 // If we get here and we don't have a plane, throw an error
1399 IString msg = "A ring plane projection has been requested on an image whose shape is not a ring plane. ";
1400 msg += "Rerun spiceinit with shape=RINGPLANE. ";
1401 throw IException(IException::User, msg, _FILEINFO_);
1402 }
1403
1404 PvlGroup map("Mapping");
1405 map += PvlKeyword("TargetName", target()->name());
1406
1407 map += PvlKeyword("RingLongitudeDirection", "CounterClockwise");
1408 map += PvlKeyword("RingLongitudeDomain", "360");
1409
1411 map += PvlKeyword("MinimumRingRadius", toString(p_minRingRadius));
1412 map += PvlKeyword("MaximumRingRadius", toString(p_maxRingRadius));
1413 map += PvlKeyword("MinimumRingLongitude", toString(p_minRingLongitude));
1414 map += PvlKeyword("MaximumRingLongitude", toString(p_maxRingLongitude));
1415 map += PvlKeyword("PixelResolution", toString(p_minres));
1416
1417 map += PvlKeyword("ProjectionName", "Planar");
1418 pvl.addGroup(map);
1419 }
1420
1423 int code = naifIkCode();
1424 QString key = "INS" + toString(code) + "_FOCAL_LENGTH";
1426 }
1427
1430 int code = naifIkCode();
1431 QString key = "INS" + toString(code) + "_PIXEL_PITCH";
1433 }
1434
1435
1436
1446 bool Camera::SetRightAscensionDeclination(const double ra, const double dec) {
1447 if (p_skyMap->SetSky(ra, dec)) {
1448 double ux = p_skyMap->FocalPlaneX();
1449 double uy = p_skyMap->FocalPlaneY();
1451 double dx = p_distortionMap->FocalPlaneX();
1452 double dy = p_distortionMap->FocalPlaneY();
1453 if (p_focalPlaneMap->SetFocalPlane(dx, dy)) {
1454 double detectorSamp = p_focalPlaneMap->DetectorSample();
1455 double detectorLine = p_focalPlaneMap->DetectorLine();
1456 if (p_detectorMap->SetDetector(detectorSamp, detectorLine)) {
1457 double parentSample = p_detectorMap->ParentSample();
1458 double parentLine = p_detectorMap->ParentLine();
1459
1460 if (p_projection == NULL || p_ignoreProjection) {
1461 p_childSample = p_alphaCube->BetaSample(parentSample);
1462 p_childLine = p_alphaCube->BetaLine(parentLine);
1463 p_pointComputed = true;
1464 return true;
1465 }
1466 else if (p_projection->IsSky()) {
1467 if (p_projection->SetGround(dec, ra)) {
1470 p_pointComputed = true;
1471 return true;
1472 }
1473 }
1474 else if (target()->shape()->hasIntersection()) {
1476 UniversalLongitude())) {
1479 p_pointComputed = true;
1480 return true;
1481 }
1482 }
1483 }
1484 }
1485 }
1486 }
1487
1488 return false;
1489 }
1490
1491
1499 void Camera::GetLocalNormal(double normal[3]) {
1500
1501 ShapeModel *shapeModel = target()->shape();
1502 if ( !shapeModel->hasIntersection()) {
1503 // if the shape is not intersected, then clearly there is no normal
1504 normal[0] = normal[1] = normal[2] = 0.0;
1505 return;
1506 }
1507
1508 // The DEM shape model (and it's child classes) will use 4 surrounding neighbor
1509 // points to find the local normal. The SetImage() calls used to find the
1510 // neighbors is potentially expensive, so we will not calculate the neighbors
1511 // for shape models whose calculateLocalNormal() method won't use them.
1512 bool computed = p_pointComputed;
1513 if (!shapeModel->isDEM()) {
1514 // Non-DEM case: Ellipsoid, NAIF DSK, or Plane --
1515 // Pass in a vector where all of the "neighbors" are the origin (shape model center).
1516 // We do this so that if the implementation of the calculateLocalNormal() method in
1517 // any of the non-DEM shape model classes is modified to use this vector, then an error
1518 // should be thrown instead of a segmentation fault.
1519 QVector<double *> unusedNeighborPoints(4);
1520 double origin[3] = {0, 0, 0};
1521 unusedNeighborPoints.fill(origin);
1522 shapeModel->calculateLocalNormal(unusedNeighborPoints);
1523 }
1524 else { // attempt to find local normal for DEM shapes using 4 surrounding points on the image
1525 QVector<double *> cornerNeighborPoints(4);
1526
1527 // As documented in the doxygen above, the goal of this method is to
1528 // calculate a normal vector to the surface using the 4 corner surrounding points.
1529 double samp = Sample();
1530 double line = Line();
1531
1532 // order of points in vector is top, bottom, left, right
1533 QList< QPair< double, double > > surroundingPoints;
1534 surroundingPoints.append(qMakePair(samp, std::nexttoward(line - 0.5, line)));
1535 surroundingPoints.append(qMakePair(samp, std::nexttoward(line + 0.5, line)));
1536 surroundingPoints.append(qMakePair(std::nexttoward(samp - 0.5, samp), line));
1537 surroundingPoints.append(qMakePair(std::nexttoward(samp + 0.5, samp), line));
1538
1539 // save input state to be restored on return
1540 double originalSample = samp;
1541 double originalLine = line;
1542
1543 // now we have all four points in the image, so find the same points on the surface
1544 for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1545 cornerNeighborPoints[i] = new double[3];
1546 }
1547
1548 Latitude lat;
1549 Longitude lon;
1550 Distance radius;
1551
1552 // if this is a dsk, we only need to use the existing intercept point (plate) normal then return
1553 for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1554 // If a surrounding point fails, set it to the original point
1555 if (!(SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1556 surroundingPoints[i].first = samp;
1557 surroundingPoints[i].second = line;
1558
1559 // If the original point fails too, we can't get a normal. Clean up and return.
1560 if (!(SetImage(surroundingPoints[i].first, surroundingPoints[i].second))) {
1561
1562 normal[0] = normal[1] = normal[2] = 0.0;
1563
1564 // restore input state
1565 if (computed) {
1566 SetImage(originalSample, originalLine);
1567 }
1568 else {
1569 p_pointComputed = false;
1570 }
1571
1572 // free memory
1573 for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1574 delete [] cornerNeighborPoints[i];
1575 }
1576
1577 return;
1578 }
1579 }
1580
1581 SurfacePoint surfacePoint = GetSurfacePoint();
1582 lat = surfacePoint.GetLatitude();
1583 lon = surfacePoint.GetLongitude();
1584 radius = LocalRadius(lat, lon);
1585
1586 latrec_c(radius.kilometers(), lon.radians(), lat.radians(), cornerNeighborPoints[i]);
1587 }
1588
1589 // if the first 2 surrounding points match or the last 2 surrounding points match,
1590 // we can't get a normal. Clean up and return.
1591 if ((surroundingPoints[0].first == surroundingPoints[1].first &&
1592 surroundingPoints[0].second == surroundingPoints[1].second) ||
1593 (surroundingPoints[2].first == surroundingPoints[3].first &&
1594 surroundingPoints[2].second == surroundingPoints[3].second)) {
1595
1596 normal[0] = normal[1] = normal[2] = 0.0;
1597
1598 // restore input state
1599 if (!computed) {
1600 SetImage(originalSample, originalLine);
1601 }
1602 else {
1603 p_pointComputed = false;
1604 }
1605
1606 // free memory
1607 for (int i = 0; i < cornerNeighborPoints.size(); i++)
1608 delete [] cornerNeighborPoints[i];
1609
1610 return;
1611 }
1612
1613 // Restore input state to original point before calculating normal
1614 SetImage(originalSample, originalLine);
1615 shapeModel->calculateLocalNormal(cornerNeighborPoints);
1616
1617 // free memory
1618 for (int i = 0; i < cornerNeighborPoints.size(); i++) {
1619 delete [] cornerNeighborPoints[i];
1620 }
1621
1622 }
1623
1624 // restore input state if calculation failed and clean up.
1625 if (!shapeModel->hasLocalNormal()) {
1626 p_pointComputed = false;
1627 return;
1628 }
1629
1630 // restore failed computed state
1631 if (!computed) {
1632 p_pointComputed = false;
1633 }
1634
1635 // Set the method normal values
1636 std::vector<double> localNormal(3);
1637 localNormal = shapeModel->localNormal();
1638 memcpy(normal, (double *) &localNormal[0], sizeof(double) * 3);
1639 }
1640
1641
1653 void Camera::LocalPhotometricAngles(Angle & phase, Angle & incidence,
1654 Angle & emission, bool &success) {
1655
1656 // get local normal vector
1657 double normal[3];
1658 GetLocalNormal(normal);
1659 success = true;
1660
1661 // Check to make sure normal is valid
1662 if (SensorUtilities::magnitude(normal) == 0.) {
1663 success = false;
1664 return;
1665 }
1666
1667 // get the vector from the surface to the sensor
1668 double sensorPosBf[3];
1669 instrumentBodyFixedPosition(sensorPosBf);
1670 SensorUtilities::Vec sensorPos(sensorPosBf);
1671
1672 SurfacePoint surfacePoint = GetSurfacePoint();
1673 SensorUtilities::Vec groundPt = {
1674 surfacePoint.GetX().kilometers(),
1675 surfacePoint.GetY().kilometers(),
1676 surfacePoint.GetZ().kilometers()};
1677
1678 SensorUtilities::Vec groundToSensor = sensorPos - groundPt;
1679
1680 // get the vector from the surface to the sun
1681 SensorUtilities::Vec sunPos(m_uB);
1682 SensorUtilities::Vec groundToSun = sunPos - groundPt;
1683
1684 phase = Angle(SensorUtilities::sepAngle(groundToSensor, groundToSun),
1686
1687 emission = Angle(SensorUtilities::sepAngle(groundToSensor, normal),
1689
1690 incidence = Angle(SensorUtilities::sepAngle(groundToSun, normal),
1692
1693 }
1694
1695
1706 void Camera::Slope(double &slope, bool &success) {
1707 ShapeModel *shapeModel = target()->shape();
1708 if ( !shapeModel->hasIntersection()) {
1709 success = false;
1710 return;
1711 }
1712 shapeModel->calculateSurfaceNormal();
1713 if (!shapeModel->hasNormal()) {
1714 success = false;
1715 return;
1716 }
1717 std::vector<double> ellipsoidNormal = shapeModel->normal();
1718
1719 double localNormal[3];
1720 GetLocalNormal(localNormal);
1721 if (localNormal[0] == 0.0 && localNormal[1] == 0.0 && localNormal[2] == 0.0) {
1722 success = false;
1723 return;
1724 }
1725
1726 slope = SensorUtilities::sepAngle(localNormal, &ellipsoidNormal[0]) * RAD2DEG;
1727 success = true;
1728 }
1729
1730
1741 bool Camera::RaDecRange(double &minra, double &maxra,
1742 double &mindec, double &maxdec) {
1743
1744
1745 bool computed = p_pointComputed;
1746 double originalSample = Sample();
1747 double originalLine = Line();
1748 int originalBand = Band();
1749
1750 // Have we already done this
1751 if (!p_raDecRangeComputed) {
1752 p_raDecRangeComputed = true;
1753
1754 // Initializations
1755 p_mindec = DBL_MAX;
1756 p_minra = DBL_MAX;
1757 p_minra180 = DBL_MAX;
1758 p_maxdec = -DBL_MAX;
1759 p_maxra = -DBL_MAX;
1760 p_maxra180 = -DBL_MAX;
1761
1762 // See if we have band dependence and loop for the appropriate number of bands
1763 int eband = p_bands;
1764 if (IsBandIndependent()) eband = 1;
1765 for (int band = 1; band <= eband; band++) {
1766 this->SetBand(band);
1767
1768 for (int line = 1; line <= p_lines; line++) {
1769 // Test left, top, and bottom sides
1770 int samp;
1771 for (samp = 1; samp <= p_samples; samp++) {
1772 SetImage((double)samp, (double)line);
1773 double ra = RightAscension();
1774 double dec = Declination();
1775 if (ra < p_minra) p_minra = ra;
1776 if (ra > p_maxra) p_maxra = ra;
1777 if (dec < p_mindec) p_mindec = dec;
1778 if (dec > p_maxdec) p_maxdec = dec;
1779
1780 if (ra > 180.0) ra -= 360.0;
1781 if (ra < p_minra180) p_minra180 = ra;
1782 if (ra > p_maxra180) p_maxra180 = ra;
1783
1784 if ((line != 1) && (line != p_lines)) break;
1785 }
1786
1787 // Test right side
1788 if (samp < p_samples) {
1789 for (samp = p_samples; samp >= 1; samp--) {
1790 SetImage((double)samp, (double)line);
1791 double ra = RightAscension();
1792 double dec = Declination();
1793 if (ra < p_minra) p_minra = ra;
1794 if (ra > p_maxra) p_maxra = ra;
1795 if (dec < p_mindec) p_mindec = dec;
1796 if (dec > p_maxdec) p_maxdec = dec;
1797
1798 if (ra > 180.0) ra -= 360.0;
1799 if (ra < p_minra180) p_minra180 = ra;
1800 if (ra > p_maxra180) p_maxra180 = ra;
1801
1802 break;
1803 }
1804 }
1805 }
1806
1807 // Special test for ground range to see if either pole is in the image
1808 if (SetRightAscensionDeclination(0.0, 90.0)) {
1809 if ((Line() >= 0.5) && (Line() <= p_lines) &&
1810 (Sample() >= 0.5) && (Sample() <= p_samples)) {
1811 p_maxdec = 90.0;
1812 p_minra = 0.0;
1813 p_maxra = 360.0;
1814 p_minra180 = -180.0;
1815 p_maxra180 = 180.0;
1816 }
1817 }
1818
1819 if (SetRightAscensionDeclination(0.0, -90.0)) {
1820 if ((Line() >= 0.5) && (Line() <= p_lines) &&
1821 (Sample() >= 0.5) && (Sample() <= p_samples)) {
1822 p_mindec = -90.0;
1823 p_minra = 0.0;
1824 p_maxra = 360.0;
1825 p_minra180 = -180.0;
1826 p_maxra180 = 180.0;
1827 }
1828 }
1829
1830 // Another special test for ground range as we could have the
1831 // 0-360 seam running right through the image so
1832 // test it as well (the increment may not be fine enough !!!)
1833 for (double dec = p_mindec; dec <= p_maxdec; dec += (p_maxdec - p_mindec) / 10.0) {
1834 if (SetRightAscensionDeclination(0.0, dec)) {
1835 if ((Line() >= 0.5) && (Line() <= p_lines) &&
1836 (Sample() >= 0.5) && (Sample() <= p_samples)) {
1837 p_minra = 0.0;
1838 p_maxra = 360.0;
1839 break;
1840 }
1841 }
1842 }
1843
1844 // Another special test for ground range as we could have the
1845 // 0-360 seam running right through the image so
1846 // test it as well (the increment may not be fine enough !!!)
1847 for (double dec = p_mindec; dec <= p_maxdec; dec += (p_maxdec - p_mindec) / 10.0) {
1848 if (SetRightAscensionDeclination(180.0, dec)) {
1849 if ((Line() >= 0.5) && (Line() <= p_lines) &&
1850 (Sample() >= 0.5) && (Sample() <= p_samples)) {
1851 p_minra180 = -180.0;
1852 p_maxra180 = 180.0;
1853 break;
1854 }
1855 }
1856 }
1857 }
1858 }
1859
1860 minra = p_minra;
1861 maxra = p_maxra;
1862 mindec = p_mindec;
1863 maxdec = p_maxdec;
1864
1865 SetBand(originalBand);
1866
1867 if (computed) {
1868 SetImage(originalSample, originalLine);
1869 }
1870 else {
1871 p_pointComputed = false;
1872 }
1873
1874 return true;
1875 }
1876
1877
1884
1885 bool computed = p_pointComputed;
1886 double originalSample = Sample();
1887 double originalLine = Line();
1888 int originalBand = Band();
1889
1890 SetImage(1.0, 1.0);
1891 double ra1 = RightAscension();
1892 double dec1 = Declination();
1893
1894 SetImage(1.0, (double)p_lines);
1895 double ra2 = RightAscension();
1896 double dec2 = Declination();
1897
1898 double dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1899 dist = sqrt(dist);
1900 double lineRes = dist / (p_lines - 1);
1901
1902 SetImage((double)p_samples, 1.0);
1903 ra2 = RightAscension();
1904 dec2 = Declination();
1905
1906 dist = (ra1 - ra2) * (ra1 - ra2) + (dec1 - dec2) * (dec1 - dec2);
1907 dist = sqrt(dist);
1908 double sampRes = dist / (p_samples - 1);
1909
1910 SetBand(originalBand);
1911
1912 if (computed) {
1913 SetImage(originalSample, originalLine);
1914 }
1915 else {
1916 p_pointComputed = false;
1917 }
1918
1919 return (sampRes < lineRes) ? sampRes : lineRes;
1920 }
1921
1928 if (target()->shape()->name() == "Plane") {
1929 QString msg = "North Azimuth is not available for plane target shapes.";
1930 throw IException(IException::Programmer, msg, _FILEINFO_);
1931 }
1932 // Get the latitude of your current location using the shape model
1933 // specified in the image Kernels
1934 double lat = UniversalLatitude();
1935 // We are in northern hemisphere
1936 if (lat >= 0.0) {
1937 return ComputeAzimuth(90.0, 0.0);
1938 }
1939 // We are in southern hemisphere
1940 else {
1941 double azimuth = ComputeAzimuth(-90.0, 0.0) + 180.0;
1942 if (azimuth > 360.0) azimuth = azimuth - 360.0;
1943 return azimuth;
1944 }
1945 }
1946
1955 double lat, lon;
1956 subSolarPoint(lat, lon);
1957 return ComputeAzimuth(lat, lon);
1958 }
1959
1960
1969 double lat, lon;
1970 subSpacecraftPoint(lat, lon);
1971 return ComputeAzimuth(lat, lon);
1972 }
1973
1974
2074 double Camera::ComputeAzimuth(const double lat, const double lon) {
2075 // Make sure we are on the planet, if not, north azimuth is meaningless
2076 if (!HasSurfaceIntersection()) return Isis::Null;
2077
2078 // Need to save the "state" of the camera so we can restore it when the
2079 // method is done
2080 bool computed = p_pointComputed;
2081
2083
2084 // Get the azimuth's origin point (the current position) and its radius
2085 SpiceDouble azimuthOrigin[3];
2086 Coordinate(azimuthOrigin);
2087 Distance originRadius = LocalRadius();
2088 if (!originRadius.isValid()) {
2089 return Isis::Null;
2090 }
2091
2092 // Convert the point of interest to rectangular coordinates (x,y,z) in the
2093 // body-fixed coordinate system and use the azimuth's origin radius to avoid the
2094 // situation where the DEM does not cover the entire planet
2095 SpiceDouble pointOfInterestFromBodyCenter[3];
2096 latrec_c(originRadius.kilometers(), lon * PI / 180.0,
2097 lat * PI / 180.0, pointOfInterestFromBodyCenter);
2098
2099 // Get the difference vector with its tail at the azimuth origin and its
2100 // head at the point of interest by subtracting vectors the vectors that
2101 // originate at the body center
2102 //
2103 // pointOfInterest = pointOfInterestFromBodyCenter - azimuthOriginFromBodyCenter
2104 //
2105 SpiceDouble pointOfInterest[3];
2106 vsub_c(pointOfInterestFromBodyCenter, azimuthOrigin, pointOfInterest);
2107
2108 // Get the component of the difference vector pointOfInterestFromAzimuthOrigin that is
2109 // perpendicular to the origin point (i.e. project perpendicularly onto the reference plane).
2110 // This will result in a point of interest vector that is in the plane tangent to the surface at
2111 // the origin point
2112 SpiceDouble pointOfInterestProj[3];
2113 vperp_c(pointOfInterest, azimuthOrigin, pointOfInterestProj);
2114
2115 // Unitize the tangent vector to a 1 km length vector
2116 SpiceDouble pointOfInterestProjUnit[3];
2117 vhat_c(pointOfInterestProj, pointOfInterestProjUnit);
2118
2119 // Scale the vector to within a pixel of the azimuth's origin point.
2120 // Get pixel scale in km/pixel and divide by 2 to insure that we stay within
2121 // a pixel of the origin point
2122 double scale = (PixelResolution() / 1000.0) / 2.0;
2123 SpiceDouble pointOfInterestProjUnitScaled[3];
2124 vscl_c(scale, pointOfInterestProjUnit, pointOfInterestProjUnitScaled);
2125
2126 // Compute the adjusted point of interest vector from the body center. This point
2127 // will be within a pixel of the origin and in the same direction as the requested
2128 // raw point of interest vector
2129 SpiceDouble adjustedPointOfInterestFromBodyCenter[3];
2130 vadd_c(azimuthOrigin, pointOfInterestProjUnitScaled, adjustedPointOfInterestFromBodyCenter);
2131
2132 // Get the origin image coordinate
2133 double azimuthOriginSample = Sample();
2134 double azimuthOriginLine = Line();
2135
2136 // Convert the point to a lat/lon and find out its image coordinate
2137 double adjustedPointOfInterestRad, adjustedPointOfInterestLon, adjustedPointOfInterestLat;
2138 reclat_c(adjustedPointOfInterestFromBodyCenter,
2139 &adjustedPointOfInterestRad,
2140 &adjustedPointOfInterestLon,
2141 &adjustedPointOfInterestLat);
2142 adjustedPointOfInterestLat = adjustedPointOfInterestLat * 180.0 / PI;
2143 adjustedPointOfInterestLon = adjustedPointOfInterestLon * 180.0 / PI;
2144 if (adjustedPointOfInterestLon < 0) adjustedPointOfInterestLon += 360.0;
2145
2146 // Use the radius of the azimuth's origin point
2147 // (rather than that of the adjusted point of interest location)
2148 // to avoid the effects of topography on the calculation
2149 bool success = SetUniversalGround(adjustedPointOfInterestLat,
2150 adjustedPointOfInterestLon,
2151 originRadius.meters());
2152 if (!success) {
2153 // if the adjusted lat/lon values for the point of origin fail to be set, we can not compute
2154 // an azimuth. reset to the original sample/line and return null.
2155 SetImage(azimuthOriginSample, azimuthOriginLine);
2156 return Isis::Null;
2157 }
2158
2159 double adjustedPointOfInterestSample = Sample();
2160 double adjustedPointOfInterestLine = Line();
2161
2162 // TODO: Write PushState and PopState method to ensure the
2163 // internals of the class are set based on SetImage or SetGround
2164
2165 // We now have the information needed to calculate an arctangent
2166 //
2167 //
2168 // point of interest
2169 // |\ |
2170 // | \ |
2171 // | \ | tan(A) = (delta line) / (delta sample)
2172 // delta line | \ | A = arctan( (delta line) / (delta sample) )
2173 // | \ |
2174 // | \ |
2175 // | \ |
2176 // ___________|_____A_\|_______________
2177 // delta sample |origin point
2178 // |
2179 // |
2180 // |
2181 // |
2182 // |
2183 //
2184 // in this example, the azimuth is the angle indicated by the A plus 180 degrees, since we begin
2185 // the angle rotation at the positive x-axis
2186 // This quadrant issue (i.e.need to add 180 degrees) is handled by the atan2 program
2187 //
2188 double deltaSample = adjustedPointOfInterestSample - azimuthOriginSample;
2189 double deltaLine = adjustedPointOfInterestLine - azimuthOriginLine;
2190
2191 // Compute the angle; the azimuth is the arctangent of the line difference divided by the
2192 // sample difference; the atan2 function is used because it determines which quadrant we
2193 // are in based on the sign of the 2 arguments; the arctangent is measured in a positive
2194 // clockwise direction because the lines in the image increase downward; the arctangent
2195 // uses the 3 o'clock axis (positive sample direction) as its reference line (line of
2196 // zero degrees); a good place to read about the atan2 function is at
2197 // http://en.wikipedia.org/wiki/Atan2
2198 double azimuth = 0.0;
2199 if (deltaSample != 0.0 || deltaLine != 0.0) {
2200 azimuth = atan2(deltaLine, deltaSample);
2201 azimuth *= 180.0 / PI;
2202 }
2203
2204 // Azimuth is limited to the range of 0 to 360
2205 if (azimuth < 0.0) azimuth += 360.0;
2206 if (azimuth > 360.0) azimuth -= 360.0;
2207
2209
2210 // computed is true if the sample/line or lat/lon were reset in this method
2211 // to find the location of the point of interest
2212 // If so, reset "state" of camera to the original sample/line
2213 if (computed) {
2214 SetImage(azimuthOriginSample, azimuthOriginLine);
2215 }
2216 else {
2217 p_pointComputed = false;
2218 }
2219
2220 return azimuth;
2221 }
2222
2223
2230 // Get the xyz coordinates for the spacecraft and point we are interested in
2231 double coord[3], spCoord[3];
2232 Coordinate(coord);
2233 instrumentPosition(spCoord);
2234
2235 // Get the angle between the 2 points and convert to degrees
2236 double a = SensorUtilities::sepAngle(coord, spCoord) * RAD2DEG;
2237 double b = 180.0 - EmissionAngle();
2238
2239 // The three angles in a triangle must add up to 180 degrees
2240 double c = 180.0 - (a + b);
2241
2242 return c;
2243 }
2244
2245
2267 double Camera::GroundAzimuth(double glat, double glon,
2268 double slat, double slon) {
2269 double a;
2270 double b;
2271 if (glat >= 0.0) {
2272 a = (90.0 - slat) * PI / 180.0;
2273 b = (90.0 - glat) * PI / 180.0;
2274 }
2275 else {
2276 a = (90.0 + slat) * PI / 180.0;
2277 b = (90.0 + glat) * PI / 180.0;
2278 }
2279
2280 double cslon = slon;
2281 double cglon = glon;
2282 if (cslon > cglon) {
2283 if ((cslon-cglon) > 180.0) {
2284 while ((cslon-cglon) > 180.0) cslon = cslon - 360.0;
2285 }
2286 }
2287 if (cglon > cslon) {
2288 if ((cglon-cslon) > 180.0) {
2289 while ((cglon-cslon) > 180.0) cglon = cglon - 360.0;
2290 }
2291 }
2292
2293 // Which quadrant are we in?
2294 int quad;
2295 if (slat > glat) {
2296 if (cslon > cglon) {
2297 quad = 1;
2298 }
2299 else if (cslon < cglon) {
2300 quad = 2;
2301 }
2302 else {
2303 quad = 1;
2304 }
2305 }
2306 else if (slat < glat) {
2307 if (cslon > cglon) {
2308 quad = 4;
2309 }
2310 else if (cslon < cglon) {
2311 quad = 3;
2312 }
2313 else {
2314 quad = 4;
2315 }
2316 }
2317 else {
2318 if (cslon > cglon) {
2319 quad = 1;
2320 }
2321 else if (cslon < cglon) {
2322 quad = 2;
2323 }
2324 else {
2325 return 0.0;
2326 }
2327 }
2328
2329 double C = (cglon - cslon) * PI / 180.0;
2330 if (C < 0) C = -C;
2331 double c = acos(cos(a)*cos(b) + sin(a)*sin(b)*cos(C));
2332 double azimuth = 0.0;
2333 if (sin(b) == 0.0 || sin(c) == 0.0) {
2334 return azimuth;
2335 }
2336 double intermediate = (cos(a) - cos(b)*cos(c))/(sin(b)*sin(c));
2337 if (intermediate < -1.0) {
2338 intermediate = -1.0;
2339 }
2340 else if (intermediate > 1.0) {
2341 intermediate = 1.0;
2342 }
2343 double A = acos(intermediate) * 180.0 / PI;
2344 //double B = acos((cos(b) - cos(c)*cos(a))/(sin(c)*sin(a))) * 180.0 / PI;
2345 if (glat >= 0.0) {
2346 if (quad == 1 || quad == 4) {
2347 azimuth = A;
2348 }
2349 else if (quad == 2 || quad == 3) {
2350 azimuth = 360.0 - A;
2351 }
2352 }
2353 else {
2354 if (quad == 1 || quad == 4) {
2355 azimuth = 180.0 - A;
2356 }
2357 else if (quad == 2 || quad == 3) {
2358 azimuth = 180.0 + A;
2359 }
2360 }
2361
2362 return azimuth;
2363 }
2364
2365
2372 void Camera::SetDistortionMap(CameraDistortionMap *map, bool deleteExisting) {
2373 if (deleteExisting && p_distortionMap) {
2374 delete p_distortionMap;
2375 }
2376
2377 p_distortionMap = map;
2378 }
2379
2380
2388 if (p_focalPlaneMap) {
2389 delete p_focalPlaneMap;
2390 }
2391
2392 p_focalPlaneMap = map;
2393 }
2394
2395
2403 if (p_detectorMap) {
2404 delete p_detectorMap;
2405 }
2406
2407 p_detectorMap = map;
2408 }
2409
2410
2418 if (p_groundMap) {
2419 delete p_groundMap;
2420 }
2421
2422 p_groundMap = map;
2423 }
2424
2425
2432 if (p_skyMap) {
2433 delete p_skyMap;
2434 }
2435
2436 p_skyMap = map;
2437 }
2438
2439
2451 // We want to stay in unprojected space for this process
2452 bool projIgnored = p_ignoreProjection;
2453 p_ignoreProjection = true;
2454
2455 // get the cache variables
2456 pair<double,double> ephemerisTimes = StartEndEphemerisTimes();
2457 int cacheSize = CacheSize(ephemerisTimes.first, ephemerisTimes.second);
2458
2459 // Set a position in the image so that the PixelResolution can be calculated
2461 double tol = PixelResolution() / 100.; //meters/pix/100.
2462
2463 if (tol < 0.0) {
2464 // Alternative calculation of ground resolution of a pixel/100
2465 double altitudeMeters;
2466 if (target()->isSky()) { // Use the unit sphere as the target
2467 altitudeMeters = 1.0;
2468 }
2469 else {
2470 altitudeMeters = SpacecraftAltitude() * 1000.;
2471 }
2472 tol = PixelPitch() * altitudeMeters / FocalLength() / 100.;
2473 }
2474
2475 p_ignoreProjection = projIgnored;
2476
2477 Spice::createCache(ephemerisTimes.first, ephemerisTimes.second,
2478 cacheSize, tol);
2479
2480 setTime(ephemerisTimes.first);
2481
2482 // Reset to band 1
2483 SetBand(1);
2484
2485 return;
2486 }
2487
2488
2509 pair<double, double> Camera::StartEndEphemerisTimes() {
2510 pair<double,double> ephemerisTimes;
2511 double startTime = -DBL_MAX;
2512 double endTime = -DBL_MAX;
2513
2514 for (int band = 1; band <= Bands(); band++) {
2515 SetBand(band);
2516 SetImage(0.5, 0.5);
2517 double etStart = time().Et();
2519 p_alphaCube->BetaLines() + 0.5); // need to do something if SetImage returns false???
2520 double etEnd = time().Et();
2521 if (band == 1) {
2522 startTime = min(etStart, etEnd);
2523 endTime = max(etStart, etEnd);
2524 }
2525 startTime = min(startTime, min(etStart, etEnd));
2526 endTime = max(endTime, max(etStart, etEnd));
2527 }
2528 if (startTime == -DBL_MAX || endTime == -DBL_MAX) {
2529 string msg = "Unable to find time range for the spice kernels";
2530 throw IException(IException::Programmer, msg, _FILEINFO_);
2531 }
2532 ephemerisTimes.first = startTime;
2533 ephemerisTimes.second = endTime;
2534 return ephemerisTimes;
2535 }
2536
2537
2557 int Camera::CacheSize(double startTime, double endTime) {
2558 int cacheSize;
2559 // BetaLines() + 1 so we get at least 2 points for interpolation
2560 cacheSize = p_alphaCube->BetaLines() + 1;
2561 if (startTime == endTime) {
2562 cacheSize = 1;
2563 }
2564 return cacheSize;
2565 }
2566
2567
2584 void Camera::SetGeometricTilingHint(int startSize, int endSize) {
2585 // verify the start size is a multiple of 2 greater than 2
2586 int powerOf2 = 2;
2587
2588 // No hint if 2's are passed in
2589 if (startSize == 2 && endSize == 2) {
2592 return;
2593 }
2594
2595 if (endSize > startSize) {
2596 IString message = "Camera::SetGeometricTilingHint End size must be smaller than the start size";
2597 throw IException(IException::Programmer, message, _FILEINFO_);
2598 }
2599
2600 if (startSize < 4) {
2601 IString message = "Camera::SetGeometricTilingHint Start size must be at least 4";
2602 throw IException(IException::Programmer, message, _FILEINFO_);
2603 }
2604
2605 bool foundEnd = false;
2606 while (powerOf2 > 0 && startSize != powerOf2) {
2607 if (powerOf2 == endSize) foundEnd = true;
2608 powerOf2 *= 2;
2609 }
2610
2611 // Didnt find a solution, the integer became negative first, must not be
2612 // a power of 2
2613 if (powerOf2 < 0) {
2614 IString message = "Camera::SetGeometricTilingHint Start size must be a power of 2";
2615 throw IException(IException::Programmer, message, _FILEINFO_);
2616 }
2617
2618 if (!foundEnd) {
2619 IString message = "Camera::SetGeometricTilingHint End size must be a power of 2 less than the start size, but greater than 2";
2620 throw IException(IException::Programmer, message, _FILEINFO_);
2621 }
2622
2623 p_geometricTilingStartSize = startSize;
2624 p_geometricTilingEndSize = endSize;
2625 }
2626
2627
2635 void Camera::GetGeometricTilingHint(int &startSize, int &endSize) {
2636 startSize = p_geometricTilingStartSize;
2637 endSize = p_geometricTilingEndSize;
2638 }
2639
2640
2650 if (Sample() < 0.5 || Line() < 0.5) {
2651 return false;
2652 }
2653
2654 if (Sample() > Samples() + 0.5 || Line() > Lines() + 0.5) {
2655 return false;
2656 }
2657
2658 return true;
2659 }
2660
2661
2669 return p_projection != 0;
2670 }
2671
2672
2680 return true;
2681 }
2682
2683
2690 return p_referenceBand;
2691 }
2692
2693
2701 return p_referenceBand != 0;
2702 }
2703
2704
2710 void Camera::SetBand(const int band) {
2711 p_childBand = band;
2712 }
2713
2714
2720 double Camera::Sample() const {
2721 return p_childSample;
2722 }
2723
2724
2730 int Camera::Band() const {
2731 return p_childBand;
2732 }
2733
2734
2740 double Camera::Line() const {
2741 return p_childLine;
2742 }
2743
2744
2751 return PixelResolution();
2752 }
2753
2754
2755
2756
2762 double Camera::FocalLength() const {
2763 return p_focalLength;
2764 }
2765
2766
2772 double Camera::PixelPitch() const {
2773 return p_pixelPitch;
2774 }
2775
2776
2785 QList<QPointF> Camera::PixelIfovOffsets() {
2786
2787 QList<QPointF> offsets;
2788 offsets.append(QPointF(-PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2789 -PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2790 offsets.append(QPointF(PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2791 -PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2792 offsets.append(QPointF(PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2793 PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2794 offsets.append(QPointF(-PixelPitch() * DetectorMap()->SampleScaleFactor() / 2.0,
2795 PixelPitch() * DetectorMap()->LineScaleFactor() / 2.0));
2796
2797 return offsets;
2798 }
2799
2800
2806 int Camera::Samples() const {
2807 return p_samples;
2808 }
2809
2810
2816 int Camera::Lines() const {
2817 return p_lines;
2818 }
2819
2820
2826 int Camera::Bands() const {
2827 return p_bands;
2828 }
2829
2830
2837 return p_alphaCube->AlphaLines();
2838 }
2839
2840
2847 return p_alphaCube->AlphaSamples();
2848 }
2849
2850
2859
2860
2869
2870
2879
2880
2889
2890
2897 return p_skyMap;
2898 }
2899
2900
2907 return m_instrumentId;
2908 }
2909
2910
2917 return m_instrumentNameLong;
2918 }
2919
2920
2927 return m_instrumentNameShort;
2928 }
2929
2930
2937 return m_spacecraftNameLong;
2938 }
2939
2940
2947 return m_spacecraftNameShort;
2948 }
2949
2955 void Camera::IgnoreProjection(bool ignore) {
2956 p_ignoreProjection = ignore;
2957 }
2994 return (naifSpkCode());
2995 }
2996
3036 return (naifBodyCode());
3037 }
3038
3044 void Camera::SetFocalLength(double v) {
3045 p_focalLength = v;
3046 }
3047
3053 void Camera::SetPixelPitch(double v) {
3054 p_pixelPitch = v;
3055 }
3056
3068 double orgLine = Line();
3069 double orgSample = Sample();
3070 double orgDec = Declination();
3071 double orgRa = RightAscension();
3072
3073 SetRightAscensionDeclination(orgRa, orgDec + (2 * RaDecResolution()));
3074 double y = Line() - orgLine;
3075 double x = Sample() - orgSample;
3076 double celestialNorthClockAngle = atan2(-y, x) * 180.0 / Isis::PI;
3077 celestialNorthClockAngle = 90.0 - celestialNorthClockAngle;
3078
3079 if (celestialNorthClockAngle < 0.0) {
3080 celestialNorthClockAngle += 360.0;
3081 }
3082
3083 SetImage(orgSample, orgLine);
3084 return celestialNorthClockAngle;
3085 }
3086
3087
3096
3097
3107 double Camera::exposureDuration(const double sample, const double line, const int band) const {
3108
3109 //If band defaults to -1, use the camera's stored band.
3110 if (band < 0) {
3111 return p_detectorMap->exposureDuration(sample, line, p_childBand);
3112 }
3113 return p_detectorMap->exposureDuration(sample, line, band);
3114 }
3115
3116// end namespace isis
3117}
This class is used to rewrite the "alpha" keywords out of the AlphaCube group or Instrument group.
Definition AlphaCube.h:46
double AlphaSample(double betaSample)
Returns an alpha sample given a beta sample.
Definition AlphaCube.h:121
int AlphaSamples() const
Returns the number of samples in the alpha cube.
Definition AlphaCube.h:77
double BetaLine(double alphaLine)
Returns a beta line given an alpha line.
Definition AlphaCube.h:133
int BetaLines() const
Returns the number of lines in the beta cube.
Definition AlphaCube.h:87
int AlphaLines() const
Returns the number of lines in the alpha cube.
Definition AlphaCube.h:67
double AlphaLine(double betaLine)
Returns an alpha line given a beta line.
Definition AlphaCube.h:109
int BetaSamples() const
Returns the number of samples in the beta cube.
Definition AlphaCube.h:97
double BetaSample(double alphaSample)
Returns a beta sample given an alpha sample.
Definition AlphaCube.h:145
Defines an angle and provides unit conversions.
Definition Angle.h:45
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition Angle.h:63
Convert between parent image coordinates and detector coordinates.
double ParentSample() const
Return parent sample.
double ParentLine() const
Return parent line.
double DetectorLine() const
Return detector line.
virtual double LineScaleFactor() const
Return scaling factor for computing line resolution.
virtual bool SetParent(const double sample, const double line)
Compute detector position from a parent image coordinate.
double DetectorSample() const
Return detector sample.
virtual double SampleScaleFactor() const
Return scaling factor for computing sample resolution.
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.
virtual bool SetDetector(const double sample, const double line)
Compute parent position from a detector coordinate.
Distort/undistort focal plane coordinates.
virtual bool SetUndistortedFocalPlane(double ux, double uy)
Compute distorted focal plane x/y.
virtual bool SetFocalPlane(double dx, double dy)
Compute undistorted focal plane x/y.
double UndistortedFocalPlaneX() const
Gets the x-value in the undistorted focal plane coordinate system.
double FocalPlaneX() const
Gets the x-value in the focal plane coordinate system.
double UndistortedFocalPlaneZ() const
Gets the z-value in the undistorted focal plane coordinate system.
double UndistortedFocalPlaneY() const
Gets the y-value in the undistorted focal plane coordinate system.
double FocalPlaneY() const
Gets the y-value in the focal plane coordinate system.
Convert between distorted focal plane and detector coordinates.
virtual bool SetDetector(const double sample, const double line)
Compute distorted focal plane coordinate from detector position (sampel,line)
virtual bool SetFocalPlane(const double dx, const double dy)
Compute detector position (sample,line) from focal plane coordinates.
Convert between undistorted focal plane and ground coordinates.
virtual bool SetGround(const Latitude &lat, const Longitude &lon)
Compute undistorted focal plane coordinate from ground position.
virtual bool SetFocalPlane(const double ux, const double uy, const double uz)
Compute ground position from focal plane coordinate.
double FocalPlaneX() const
double FocalPlaneY() const
double NorthAzimuth()
Returns the North Azimuth.
Definition Camera.cpp:1927
std::pair< double, double > StartEndEphemerisTimes()
Calculates the start and end ephemeris times.
Definition Camera.cpp:2509
virtual double SampleResolution()
Returns the sample resolution at the current position in meters.
Definition Camera.cpp:640
QString m_spacecraftNameLong
Full spacecraft name.
Definition Camera.h:499
double p_maxRingLongitude180
The maximum ring longitude in the 180 domain.
Definition Camera.h:559
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:2267
AlphaCube * p_alphaCube
A pointer to the AlphaCube.
Definition Camera.h:504
double p_mindec
The minimum declination.
Definition Camera.h:545
Projection * p_projection
A pointer to the Projection.
Definition Camera.h:542
void GroundRangeResolution()
Computes the ground range and min/max resolution.
Definition Camera.cpp:752
double p_maxres
The maximum resolution.
Definition Camera.h:527
virtual double exposureDuration() const
Return the exposure duration for the pixel that the camera is set to.
Definition Camera.cpp:3093
double p_maxobliqueres
The maximum oblique resolution.
Definition Camera.h:529
double p_focalLength
The focal length, in units of millimeters.
Definition Camera.h:519
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:357
double p_minra
The minimum right ascension.
Definition Camera.h:547
bool p_raDecRangeComputed
Flag showing if the raDec range has been computed successfully.
Definition Camera.h:552
virtual ~Camera()
Destroys the Camera Object.
Definition Camera.cpp:110
int ParentLines() const
Returns the number of lines in the parent alphacube.
Definition Camera.cpp:2836
void SetSkyMap(CameraSkyMap *map)
Sets the Sky Map.
Definition Camera.cpp:2431
virtual double DetectorResolution()
Returns the detector resolution at the current position in meters.
Definition Camera.cpp:622
double LowestObliqueImageResolution()
Returns the lowest/worst oblique resolution in the entire image.
Definition Camera.cpp:732
double SpacecraftAzimuth()
Return the Spacecraft Azimuth.
Definition Camera.cpp:1968
CameraSkyMap * p_skyMap
A pointer to the SkyMap.
Definition Camera.h:569
CameraDetectorMap * DetectorMap()
Returns a pointer to the CameraDetectorMap object.
Definition Camera.cpp:2876
double CelestialNorthClockAngle()
Computes the celestial north clock angle at the current line/sample or ra/dec.
Definition Camera.cpp:3067
double p_maxra
The maxumum right ascension.
Definition Camera.h:548
virtual double Line() const
Returns the current line number.
Definition Camera.cpp:2740
void GetGeometricTilingHint(int &startSize, int &endSize)
This will get the geometric tiling hint; these values are typically used for ProcessRubberSheet::SetT...
Definition Camera.cpp:2635
double RaDecResolution()
Returns the RaDec resolution.
Definition Camera.cpp:1883
void IgnoreProjection(bool ignore)
Set whether or not the camera should ignore the Projection.
Definition Camera.cpp:2955
CameraDetectorMap * p_detectorMap
A pointer to the DetectorMap.
Definition Camera.h:567
Camera(Cube &cube)
Constructs the Camera object.
Definition Camera.cpp:56
bool IntersectsLongitudeDomain(Pvl &pvl)
Checks whether the ground range intersects the longitude domain or not.
Definition Camera.cpp:1176
double SunAzimuth()
Returns the Sun Azimuth.
Definition Camera.cpp:1954
double PixelPitch() const
Returns the pixel pitch.
Definition Camera.cpp:2772
double p_minobliqueres
The minimum oblique resolution.
Definition Camera.h:528
double p_minres
The minimum resolution.
Definition Camera.h:526
int ReferenceBand() const
Returns the reference band.
Definition Camera.cpp:2689
double p_maxlon180
The maximum longitude in the 180 domain.
Definition Camera.h:531
double p_maxRingRadius
The maximum ring radius.
Definition Camera.h:555
CameraSkyMap * SkyMap()
Returns a pointer to the CameraSkyMap object.
Definition Camera.cpp:2896
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:296
int p_referenceBand
The reference band.
Definition Camera.h:540
QString m_instrumentId
The InstrumentId as it appears on the cube.
Definition Camera.h:495
double p_minRingLongitude180
The minimum ring longitude in the 180 domain.
Definition Camera.h:558
int ParentSamples() const
Returns the number of samples in the parent alphacube.
Definition Camera.cpp:2846
virtual double ObliquePixelResolution(bool useLocal=true)
Returns the oblique pixel resolution at the current position in meters/pixel.
Definition Camera.cpp:696
void BasicMapping(Pvl &map)
Writes the basic mapping group to the specified Pvl.
Definition Camera.cpp:1367
int Lines() const
Returns the number of lines in the image.
Definition Camera.cpp:2816
int p_geometricTilingEndSize
The ideal geometric tile size to end with when projecting.
Definition Camera.h:574
virtual double Sample() const
Returns the current sample number.
Definition Camera.cpp:2720
void ringRangeResolution()
Analogous to above GroundRangeResolution method.
Definition Camera.cpp:993
QString spacecraftNameLong() const
This method returns the full spacecraft name.
Definition Camera.cpp:2936
bool p_groundRangeComputed
Flag showing if ground range was computed successfully.
Definition Camera.h:533
virtual double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
Definition Camera.cpp:681
bool ringRange(double &minRingRadius, double &maxRingRadius, double &minRingLongitude, double &maxRingLongitude, Pvl &pvl)
Analogous to the above Ground Range method.
Definition Camera.cpp:1297
double OffNadirAngle()
Return the off nadir angle in degrees.
Definition Camera.cpp:2229
virtual 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:156
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:2584
virtual double LineResolution()
Returns the line resolution at the current position in meters.
Definition Camera.cpp:660
void SetFocalLength()
Reads the focal length from the instrument kernel.
Definition Camera.cpp:1422
QString instrumentNameLong() const
This method returns the full instrument name.
Definition Camera.cpp:2916
void SetPixelPitch()
Reads the Pixel Pitch from the instrument kernel.
Definition Camera.cpp:1429
double FocalLength() const
Returns the focal length.
Definition Camera.cpp:2762
virtual int Band() const
Returns the current band.
Definition Camera.cpp:2730
void SetDetectorMap(CameraDetectorMap *map)
Sets the Detector Map.
Definition Camera.cpp:2402
double p_maxlat
The maximum latitude.
Definition Camera.h:523
int p_samples
The number of samples in the image.
Definition Camera.h:536
bool HasProjection()
Checks to see if the camera object has a projection.
Definition Camera.cpp:2668
int p_lines
The number of lines in the image.
Definition Camera.h:537
bool InCube()
This returns true if the current Sample() or Line() value is outside of the cube (meaning the point m...
Definition Camera.cpp:2649
double p_minlat
The minimum latitude.
Definition Camera.h:522
double p_childSample
Sample value for child.
Definition Camera.h:502
void LoadCache()
This loads the spice cache big enough for this image.
Definition Camera.cpp:2450
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition Camera.cpp:382
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:2074
QString instrumentNameShort() const
This method returns the shortened instrument name.
Definition Camera.cpp:2926
bool p_pointComputed
Flag showing if Sample/Line has been computed.
Definition Camera.h:506
void SetFocalPlaneMap(CameraFocalPlaneMap *map)
Sets the Focal Plane Map.
Definition Camera.cpp:2387
virtual double ObliqueLineResolution(bool useLocal=true)
Returns the oblique line resolution at the current position in meters.
Definition Camera.cpp:672
double p_minra180
The minimum right ascension in the 180 domain.
Definition Camera.h:549
bool p_ignoreProjection
Whether or no to ignore the Projection.
Definition Camera.h:543
QString m_instrumentNameShort
Shortened instrument name.
Definition Camera.h:498
CameraFocalPlaneMap * p_focalPlaneMap
A pointer to the FocalPlaneMap.
Definition Camera.h:566
void LocalPhotometricAngles(Angle &phase, Angle &incidence, Angle &emission, bool &success)
Calculates LOCAL photometric angles using the DEM (not ellipsoid).
Definition Camera.cpp:1653
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:1499
QString instrumentId()
This method returns the InstrumentId as it appears in the cube.
Definition Camera.cpp:2906
CameraGroundMap * p_groundMap
A pointer to the GroundMap.
Definition Camera.h:568
CameraDistortionMap * DistortionMap()
Returns a pointer to the CameraDistortionMap object.
Definition Camera.cpp:2856
double HighestImageResolution()
Returns the highest/best resolution in the entire image.
Definition Camera.cpp:721
virtual bool SetGround(Latitude latitude, Longitude longitude)
Sets the lat/lon values to get the sample/line values.
Definition Camera.cpp:403
QString spacecraftNameShort() const
This method returns the shortened spacecraft name.
Definition Camera.cpp:2946
double HighestObliqueImageResolution()
Returns the highest/best oblique resolution in the entire image.
Definition Camera.cpp:743
virtual int SpkTargetId() const
Provides target code for instruments SPK NAIF kernel.
Definition Camera.cpp:2993
QString m_spacecraftNameShort
Shortened spacecraft name.
Definition Camera.h:500
bool p_ringRangeComputed
Flag showing if ring range was computed successfully.
Definition Camera.h:561
double p_minlon
The minimum longitude.
Definition Camera.h:524
virtual bool IsBandIndependent()
Virtual method that checks if the band is independent.
Definition Camera.cpp:2679
virtual double ObliqueSampleResolution(bool useLocal=true)
Returns the oblique sample resolution at the current position in m.
Definition Camera.cpp:650
bool GroundRange(double &minlat, double &maxlat, double &minlon, double &maxlon, Pvl &pvl)
Computes the Ground Range.
Definition Camera.cpp:1193
double p_maxRingLongitude
The maximum ring longitude (azimuth)
Definition Camera.h:557
int p_bands
The number of bands in the image.
Definition Camera.h:538
virtual double ObliqueDetectorResolution(bool useLocal=true)
This method returns the Oblique Detector Resolution if the Look Vector intersects the target and if t...
Definition Camera.cpp:583
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition Camera.cpp:2417
bool RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec)
Computes the RaDec range.
Definition Camera.cpp:1741
double p_minRingLongitude
The minimum ring longitude (azimuth)
Definition Camera.h:556
CameraDistortionMap * p_distortionMap
A pointer to the DistortionMap.
Definition Camera.h:565
double p_maxdec
The maximum declination.
Definition Camera.h:546
double p_minRingRadius
The minimum ring radius.
Definition Camera.h:554
void basicRingMapping(Pvl &map)
Writes the basic mapping group for ring plane to the specified Pvl.
Definition Camera.cpp:1396
int CacheSize(double startTime, double endTime)
This method calculates the spice cache size.
Definition Camera.cpp:2557
void Slope(double &slope, bool &success)
Calculates the slope at the current point by computing the angle between the local surface normal and...
Definition Camera.cpp:1706
double p_maxra180
The maximum right ascension in the 180 domain.
Definition Camera.h:550
bool HasReferenceBand() const
Checks to see if the Camera object has a reference band.
Definition Camera.cpp:2700
bool RawFocalPlanetoImage()
Computes the image coordinate for the current universal ground point.
Definition Camera.cpp:457
double p_pixelPitch
The pixel pitch, in millimeters per pixel.
Definition Camera.h:520
double LowestImageResolution()
Returns the lowest/worst resolution in the entire image.
Definition Camera.cpp:710
int Samples() const
Returns the number of samples in the image.
Definition Camera.cpp:2806
virtual QList< QPointF > PixelIfovOffsets()
Returns the pixel ifov offsets from center of pixel, which defaults to the (pixel pitch * summing mod...
Definition Camera.cpp:2785
CameraFocalPlaneMap * FocalPlaneMap()
Returns a pointer to the CameraFocalPlaneMap object.
Definition Camera.cpp:2866
virtual bool SetRightAscensionDeclination(const double ra, const double dec)
Sets the right ascension declination.
Definition Camera.cpp:1446
double p_minlon180
The minimum longitude in the 180 domain.
Definition Camera.h:530
void SetDistortionMap(CameraDistortionMap *map, bool deleteExisting=true)
Sets the Distortion Map.
Definition Camera.cpp:2372
int p_childBand
Band value for child.
Definition Camera.h:564
double p_childLine
Line value for child.
Definition Camera.h:503
virtual double resolution()
Returns the resolution of the camera.
Definition Camera.cpp:2750
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition Camera.cpp:2710
CameraGroundMap * GroundMap()
Returns a pointer to the CameraGroundMap object.
Definition Camera.cpp:2886
virtual int SpkCenterId() const
Provides the center of motion body for SPK NAIF kernel.
Definition Camera.cpp:3035
QString m_instrumentNameLong
Full instrument name.
Definition Camera.h:497
double p_maxlon
The maximum longitude.
Definition Camera.h:525
int p_geometricTilingStartSize
The ideal geometric tile size to start with when projecting.
Definition Camera.h:572
int Bands() const
Returns the number of bands in the image.
Definition Camera.cpp:2826
Convert between undistorted focal plane and ra/dec coordinates.
virtual bool SetSky(const double ra, const double dec)
Compute undistorted focal plane coordinate from ra/dec.
double FocalPlaneY() const
double FocalPlaneX() const
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
int sampleCount() const
Definition Cube.cpp:1813
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition Cube.cpp:1416
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
double kilometers() const
Get the displacement in kilometers.
Distance measurement, usually in meters.
Definition Distance.h:34
bool isValid() const
Test if this distance has been initialized or not.
Definition Distance.cpp:192
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
Definition Projection.h:166
virtual bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
bool IsSky() const
Returns true if projection is sky and false if it is land.
virtual double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
virtual double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
ProjectionType projectionType() const
Returns an enum value for the projection type.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
Base class for Map Projections of plane shapes.
Class for computing sensor ground coordinates.
Definition Sensor.h:170
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:99
virtual SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Definition Sensor.cpp:257
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition Sensor.cpp:212
virtual double RightAscension()
Returns the right ascension angle (sky longitude).
Definition Sensor.cpp:565
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition Sensor.cpp:188
double SpacecraftAltitude()
Returns the distance from the spacecraft to the subspacecraft point in km.
Definition Sensor.cpp:703
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition Sensor.cpp:235
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Definition Sensor.cpp:198
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition Sensor.cpp:269
virtual double Declination()
Returns the declination angle (sky latitude).
Definition Sensor.cpp:578
virtual double EmissionAngle() const
Returns the emission angle in degrees.
Definition Sensor.cpp:328
Define shapes and provide utilities for Isis targets.
Definition ShapeModel.h:66
virtual void clearSurfacePoint()
Clears or resets the current surface point.
void setHasIntersection(bool b)
Sets the flag to indicate whether this ShapeModel has an intersection.
QString name() const
Gets the shape name.
virtual void subSolarPoint(double &lat, double &lon)
Returns the sub-solar latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1341
virtual 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:649
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition Spice.cpp:937
SpiceInt naifBodyCode() const
This returns the NAIF body code of the target indicated in the labels.
Definition Spice.cpp:948
SpiceInt naifSpkCode() const
This returns the NAIF SPK code to use when reading from SPK kernels.
Definition Spice.cpp:957
virtual void instrumentBodyFixedPosition(double p[3]) const
Returns the spacecraft position in body-fixed frame km units.
Definition Spice.cpp:842
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
virtual iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions.
Definition Spice.cpp:891
virtual SpicePosition * instrumentPosition() const
Accessor method for the instrument position.
Definition Spice.cpp:1612
SpiceInt naifIkCode() const
This returns the NAIF IK code to use when reading from instrument kernels.
Definition Spice.cpp:975
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition Spice.h:369
SpiceDouble getDouble(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1046
virtual void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1290
This class defines a body-fixed surface point.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Base class for Map TProjections.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition Constants.h:43
const double Null
Value for an Isis Null pixel.
const double HALFPI
The mathematical constant PI/2.
Definition Constants.h:41
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.