Isis 3 Programmer Reference
Spice.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Spice.h"
8
9#include <cfloat>
10#include <iomanip>
11
12#include <QDebug>
13#include <QVector>
14
15#include <getSpkAbCorrState.hpp>
16
17#include <ale/Load.h>
18
19#include <nlohmann/json.hpp>
20using json = nlohmann::json;
21
22
23#include "Constants.h"
24#include "Distance.h"
25#include "EllipsoidShape.h"
26#include "EndianSwapper.h"
27#include "FileName.h"
28#include "IException.h"
29#include "IString.h"
30#include "iTime.h"
31#include "Longitude.h"
32#include "LightTimeCorrectionState.h"
33#include "NaifStatus.h"
34#include "ShapeModel.h"
35#include "SpacecraftPosition.h"
36#include "Target.h"
37#include "Blob.h"
38
39using namespace std;
40
41namespace Isis {
63 // TODO: DOCUMENT EVERYTHING
65 Pvl &lab = *cube.label();
66 if (cube.hasBlob("CSMState", "String")) {
67 csmInit(cube, lab);
68 }
69 else {
70 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
71 bool hasTables = (kernels["TargetPosition"][0] == "Table");
72 // BONUS TODO: update to pull out separate init methods
73 init(lab, !hasTables);
74 }
75 }
76
77
84 Spice::Spice(Pvl &lab, json isd) {
85 init(lab, true, isd);
86 }
87
88
97 void Spice::csmInit(Cube &cube, Pvl label) {
99 m_target = new Target;
101 }
102
103
109
110 m_et = nullptr;
111 m_kernels = new QVector<QString>;
112
113 m_startTime = new iTime;
114 m_endTime = new iTime;
115 m_cacheSize = new SpiceDouble;
116 *m_cacheSize = 0;
117
118 m_startTimePadding = new SpiceDouble;
120 m_endTimePadding = new SpiceDouble;
121 *m_endTimePadding = 0;
122
123 m_instrumentPosition = nullptr;
124 m_instrumentRotation = nullptr;
125
126 m_sunPosition = nullptr;
127 m_bodyRotation = nullptr;
128
129 m_allowDownsizing = false;
130
131 m_spkCode = nullptr;
132 m_ckCode = nullptr;
133 m_ikCode = nullptr;
134 m_sclkCode = nullptr;
135 m_spkBodyCode = nullptr;
136 m_bodyFrameCode = nullptr;
137 m_target = nullptr;
138 }
139
140
154 void Spice::init(Pvl &lab, bool noTables, json isd) {
156 // Initialize members
157 defaultInit();
158
159 m_spkCode = new SpiceInt;
160 m_ckCode = new SpiceInt;
161 m_ikCode = new SpiceInt;
162 m_sclkCode = new SpiceInt;
163 m_spkBodyCode = new SpiceInt;
164 m_bodyFrameCode = new SpiceInt;
165
166 m_naifKeywords = new PvlObject("NaifKeywords");
167 // m_sky = false;
168
169 // Get the kernel group and load main kernels
170 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
171
172 // Get the time padding first
173 if (kernels.hasKeyword("StartPadding")) {
174 *m_startTimePadding = toDouble(kernels["StartPadding"][0]);
175 }
176 else {
177 *m_startTimePadding = 0.0;
178 }
179
180 if (kernels.hasKeyword("EndPadding")) {
181 *m_endTimePadding = toDouble(kernels["EndPadding"][0]);
182 }
183 else {
184 *m_endTimePadding = 0.0;
185 }
186
187 // We should remove this completely in the near future
188 m_usingNaif = !lab.hasObject("NaifKeywords") || noTables;
189 m_usingAle = false;
190
191
192 // Modified to load planetary ephemeris SPKs before s/c SPKs since some
193 // missions (e.g., MESSENGER) may augment the s/c SPK with new planet
194 // ephemerides. (2008-02-27 (KJB))
195 if (m_usingNaif) {
196 try {
197 if (isd == NULL) {
198 // try using ALE
199 std::ostringstream kernel_pvl;
200 kernel_pvl << kernels;
201
202 json props;
203 if (kernels["InstrumentPointing"][0].toUpper() == "NADIR") {
204 props["nadir"] = true;
205 }
206
207 props["kernels"] = kernel_pvl.str();
208
209 isd = ale::load(lab.fileName().toStdString(), props.dump(), "ale", false, false, true);
210 }
211
212 json aleNaifKeywords = isd["naif_keywords"];
213 m_naifKeywords = new PvlObject("NaifKeywords", aleNaifKeywords);
214
215 // Still need to load clock kernels for now
216 load(kernels["LeapSecond"], noTables);
217 if ( kernels.hasKeyword("SpacecraftClock")) {
218 load(kernels["SpacecraftClock"], noTables);
219 }
220 m_usingAle = true;
221 }
222 catch(...) {
223 // Backup to standard ISIS implementation
224 if (noTables) {
225 load(kernels["TargetPosition"], noTables);
226 load(kernels["InstrumentPosition"], noTables);
227 load(kernels["InstrumentPointing"], noTables);
228 }
229
230 if (kernels.hasKeyword("Frame")) {
231 load(kernels["Frame"], noTables);
232 }
233
234 load(kernels["TargetAttitudeShape"], noTables);
235 if (kernels.hasKeyword("Instrument")) {
236 load(kernels["Instrument"], noTables);
237 }
238 // Always load after instrument
239 if (kernels.hasKeyword("InstrumentAddendum")) {
240 load(kernels["InstrumentAddendum"], noTables);
241 }
242
243 // Still need to load clock kernels for now
244 load(kernels["LeapSecond"], noTables);
245 if ( kernels.hasKeyword("SpacecraftClock")) {
246 load(kernels["SpacecraftClock"], noTables);
247 }
248
249 // Modified to load extra kernels last to allow overriding default values
250 // (2010-04-07) (DAC)
251 if (kernels.hasKeyword("Extra")) {
252 load(kernels["Extra"], noTables);
253 }
254 }
255
256 // Moved the construction of the Target after the NAIF kenels have been loaded or the
257 // NAIF keywords have been pulled from the cube labels, so we can find target body codes
258 // that are defined in kernels and not just body codes build into spicelib
259 // TODO: Move this below the else once the rings code below has been refactored
260 m_target = new Target(this, lab);
261
262 // This should not be here. Consider having spiceinit add the necessary rings kernels to the
263 // Extra parameter if the user has set the shape model to RingPlane.
264 // If Target is Saturn and ShapeModel is RingPlane, load the extra rings pck file
265 // which changes the prime meridian values to report longitudes with respect to
266 // the ascending node of the ringplane.
267 if (m_target->name().toUpper() == "SATURN" && m_target->shape()->name().toUpper() == "PLANE") {
268 PvlKeyword ringPck = PvlKeyword("RingPCK","$cassini/kernels/pck/saturnRings_v001.tpc");
269 load(ringPck, noTables);
270 }
271 }
272 else {
273 *m_naifKeywords = lab.findObject("NaifKeywords");
274
275 // Moved the construction of the Target after the NAIF kenels have been loaded or the
276 // NAIF keywords have been pulled from the cube labels, so we can find target body codes
277 // that are defined in kernels and not just body codes build into spicelib
278 // TODO: Move this below the else once the rings code above has been refactored
279
280 m_target = new Target(this, lab);
281 }
282
283 // Get NAIF ik, spk, sclk, and ck codes
284 //
285 // Use ikcode to get parameters from instrument kernel such as focal
286 // length, distortions, focal plane maps, etc
287 //
288 // Use spkcode to get spacecraft position from spk file
289 //
290 // Use sclkcode to transform times from et to tics
291 //
292 // Use ckcode to transform between frames
293 //
294 // Use bodycode to obtain radii and attitude (pole position/omega0)
295 //
296 // Use spkbodycode to read body position from spk
297
298 QString trykey = "NaifIkCode";
299 if (kernels.hasKeyword("NaifFrameCode")) trykey = "NaifFrameCode";
300 *m_ikCode = toInt(kernels[trykey][0]);
301
302 *m_spkCode = *m_ikCode / 1000;
304 *m_ckCode = *m_ikCode;
305
306 if (!m_target->isSky()) {
307 // Get target body code and radii and store them in the Naif group
308 // DAC modified to look for and store body code so that the radii keyword name
309 // will be able to be constructed even for new bodies not in the standard PCK yet.
310 QString radiiKey = "BODY" + Isis::toString(m_target->naifBodyCode()) + "_RADII";
311 QVariant result = m_target->naifBodyCode();
312 storeValue("BODY_CODE", 0, SpiceIntType, result);
313 std::vector<Distance> radii(3,Distance());
314 radii[0] = Distance(getDouble(radiiKey, 0), Distance::Kilometers);
315 radii[1] = Distance(getDouble(radiiKey, 1), Distance::Kilometers);
316 radii[2] = Distance(getDouble(radiiKey, 2), Distance::Kilometers);
317 // m_target doesn't have the getDouble method so Spice gets the radii for it
319 }
320
322
323 // Override them if they exist in the labels
324 if (kernels.hasKeyword("NaifSpkCode")) {
325 *m_spkCode = (int) kernels["NaifSpkCode"];
326 }
327
328 if (kernels.hasKeyword("NaifCkCode")) {
329 *m_ckCode = (int) kernels["NaifCkCode"];
330 }
331
332 if (kernels.hasKeyword("NaifSclkCode")) {
333 *m_sclkCode = (int) kernels["NaifSclkCode"];
334 }
335
336 if (!m_target->isSky()) {
337 if (kernels.hasKeyword("NaifSpkBodyCode")) {
338 *m_spkBodyCode = (int) kernels["NaifSpkBodyCode"];
339 }
340 }
341
342 if (m_target->isSky()) {
343 // Create the identity rotation for sky targets
344 // Everything in bodyfixed will really be J2000
346 }
347 else {
348 // JAA - Modified to store and look for the frame body code in the cube labels
349 SpiceInt frameCode;
350 if (((m_usingNaif) || (!m_naifKeywords->hasKeyword("BODY_FRAME_CODE"))) && !isUsingAle()) {
351 char frameName[32];
352 SpiceBoolean found;
353 cidfrm_c(*m_spkBodyCode, sizeof(frameName), &frameCode, frameName, &found);
354
355 if (!found) {
356 QString naifTarget = "IAU_" + m_target->name().toUpper();
357 namfrm_c(naifTarget.toLatin1().data(), &frameCode);
358 if (frameCode == 0) {
359 QString msg = "Can not find NAIF BODY_FRAME_CODE for target ["
360 + m_target->name() + "]";
361 throw IException(IException::Io, msg, _FILEINFO_);
362 }
363 }
364
365 QVariant result = (int)frameCode;
366 storeValue("BODY_FRAME_CODE", 0, SpiceIntType, result);
367 }
368 else {
369 try {
370 frameCode = getInteger("BODY_FRAME_CODE", 0);
371 }
372 catch(IException &e) {
373 QString msg = "Unable to read BODY_FRAME_CODE from naifkeywords group";
374 throw IException(IException::Io, msg, _FILEINFO_);
375 }
376 }
377
378 m_bodyRotation = new SpiceRotation(frameCode);
379 *m_bodyFrameCode = frameCode;
380 }
381
383
384 // Set up for observer/target and light time correction to between s/c
385 // and target body.
386 LightTimeCorrectionState ltState(*m_ikCode, this);
387 ltState.checkSpkKernelsForAberrationCorrection();
388
389 vector<Distance> radius = m_target->radii();
390 Distance targetRadius((radius[0] + radius[2])/2.0);
392 ltState, targetRadius);
393
395
396
397 // Check to see if we have nadir pointing that needs to be computed &
398 // See if we have table blobs to load
399 if (m_usingAle) {
400 m_sunPosition->LoadCache(isd["sun_position"]);
401 if (m_sunPosition->cacheSize() > 3) {
403 }
404 m_bodyRotation->LoadCache(isd["body_rotation"]);
406 if (m_bodyRotation->cacheSize() > 5) {
408 }
410 }
411 else if (kernels["TargetPosition"][0].toUpper() == "TABLE") {
412 Table t("SunPosition", lab.fileName(), lab);
414
415 Table t2("BodyRotation", lab.fileName(), lab);
417 if (t2.Label().hasKeyword("SolarLongitude")) {
418 *m_solarLongitude = Longitude(t2.Label()["SolarLongitude"],
420 }
421 else {
423 }
424 }
425
426 // We can't assume InstrumentPointing & InstrumentPosition exist, old
427 // files may be around with the old keywords, SpacecraftPointing &
428 // SpacecraftPosition. The old keywords were in existance before the
429 // Table option, so we don't need to check for Table under the old
430 // keywords.
431
432 if (kernels["InstrumentPointing"].size() == 0) {
434 "No camera pointing available",
435 _FILEINFO_);
436 }
437
438 // 2009-03-18 Tracie Sucharski - Removed test for old keywords, any files
439 // with the old keywords should be re-run through spiceinit.
440 if (kernels["InstrumentPointing"][0].toUpper() == "NADIR" && !isUsingAle()) {
444 }
445
447 }
448 else if (m_usingAle) {
449 m_instrumentRotation->LoadCache(isd["instrument_pointing"]);
451 if (m_instrumentRotation->cacheSize() > 5) {
453 }
454 }
455 else if (kernels["InstrumentPointing"][0].toUpper() == "TABLE") {
456 Table t("InstrumentPointing", lab.fileName(), lab);
458 }
459
460
461 if (kernels["InstrumentPosition"].size() == 0) {
463 "No instrument position available",
464 _FILEINFO_);
465 }
466
467 if (m_usingAle) {
468 m_instrumentPosition->LoadCache(isd["instrument_position"]);
469 }
470 else if (kernels["InstrumentPosition"][0].toUpper() == "TABLE") {
471 Table t("InstrumentPosition", lab.fileName(), lab);
473 }
475 }
476
477
486 void Spice::load(PvlKeyword &key, bool noTables) {
488
489 for (int i = 0; i < key.size(); i++) {
490 if (key[i] == "") continue;
491 if (key[i].toUpper() == "NULL") break;
492 if (key[i].toUpper() == "NADIR") break;
493 if (key[i].toUpper() == "TABLE" && !noTables) break;
494 if (key[i].toUpper() == "TABLE" && noTables) continue;
495 FileName file(key[i]);
496 if (!file.fileExists()) {
497 QString msg = "Spice file does not exist [" + file.expanded() + "]";
498 throw IException(IException::Io, msg, _FILEINFO_);
499 }
500 QString fileName = file.expanded();
501 furnsh_c(fileName.toLatin1().data());
502 m_kernels->push_back(key[i]);
503 }
504
506 }
507
513
514 if (m_solarLongitude != NULL) {
515 delete m_solarLongitude;
516 m_solarLongitude = NULL;
517 }
518
519 if (m_et != NULL) {
520 delete m_et;
521 m_et = NULL;
522 }
523
524 if (m_startTime != NULL) {
525 delete m_startTime;
526 m_startTime = NULL;
527 }
528
529 if (m_endTime != NULL) {
530 delete m_endTime;
531 m_endTime = NULL;
532 }
533
534 if (m_cacheSize != NULL) {
535 delete m_cacheSize;
536 m_cacheSize = NULL;
537 }
538
539 if (m_startTimePadding != NULL) {
540 delete m_startTimePadding;
541 m_startTimePadding = NULL;
542 }
543
544 if (m_endTimePadding != NULL) {
545 delete m_endTimePadding;
546 m_endTimePadding = NULL;
547 }
548
549 if (m_instrumentPosition != NULL) {
552 }
553
554 if (m_instrumentRotation != NULL) {
557 }
558
559 if (m_sunPosition != NULL) {
560 delete m_sunPosition;
561 m_sunPosition = NULL;
562 }
563
564 if (m_bodyRotation != NULL) {
565 delete m_bodyRotation;
566 m_bodyRotation = NULL;
567 }
568
569 if (m_spkCode != NULL) {
570 delete m_spkCode;
571 m_spkCode = NULL;
572 }
573
574 if (m_ckCode != NULL) {
575 delete m_ckCode;
576 m_ckCode = NULL;
577 }
578
579 if (m_ikCode != NULL) {
580 delete m_ikCode;
581 m_ikCode = NULL;
582 }
583
584 if (m_sclkCode != NULL) {
585 delete m_sclkCode;
586 m_sclkCode = NULL;
587 }
588
589 if (m_spkBodyCode != NULL) {
590 delete m_spkBodyCode;
591 m_spkBodyCode = NULL;
592 }
593
594 if (m_bodyFrameCode != NULL) {
595 delete m_bodyFrameCode;
596 m_bodyFrameCode = NULL;
597 }
598
599 if (m_target != NULL) {
600 delete m_target;
601 m_target = NULL;
602 }
603
604 // Unload the kernels (TODO: Can this be done faster)
605 for (int i = 0; m_kernels && i < m_kernels->size(); i++) {
606 FileName file(m_kernels->at(i));
607 QString fileName = file.expanded();
608 unload_c(fileName.toLatin1().data());
609 }
610
611 if (m_kernels != NULL) {
612 delete m_kernels;
613 m_kernels = NULL;
614 }
616 }
617
649 void Spice::createCache(iTime startTime, iTime endTime,
650 int cacheSize, double tol) {
652
653 // Check for errors
654 if (cacheSize <= 0) {
655 QString msg = "Argument cacheSize must be greater than zero";
656 throw IException(IException::Programmer, msg, _FILEINFO_);
657 }
658
659 if (startTime > endTime) {
660 QString msg = "Argument startTime must be less than or equal to endTime";
661 throw IException(IException::Programmer, msg, _FILEINFO_);
662 }
663
664 if (*m_cacheSize > 0) {
665 QString msg = "A cache has already been created";
666 throw IException(IException::Programmer, msg, _FILEINFO_);
667 }
668
669 if (cacheSize == 1 && (*m_startTimePadding != 0 || *m_endTimePadding != 0)) {
670 QString msg = "This instrument does not support time padding";
671 throw IException(IException::User, msg, _FILEINFO_);
672 }
673
674 string abcorr;
675 if (getSpkAbCorrState(abcorr)) {
676 instrumentPosition()->SetAberrationCorrection("NONE");
677 }
678
679 iTime avgTime((startTime.Et() + endTime.Et()) / 2.0);
680 computeSolarLongitude(avgTime);
681
682 // Cache everything
683 if (!m_bodyRotation->IsCached()) {
684 int bodyRotationCacheSize = cacheSize;
685 if (cacheSize > 2) bodyRotationCacheSize = 2;
687 startTime.Et() - *m_startTimePadding,
688 endTime.Et() + *m_endTimePadding,
689 bodyRotationCacheSize);
690 }
691
695 startTime.Et() - *m_startTimePadding,
696 endTime.Et() + *m_endTimePadding,
697 cacheSize);
698 }
699
702 startTime.Et() - *m_startTimePadding,
703 endTime.Et() + *m_endTimePadding,
704 cacheSize);
705 if (cacheSize > 3) m_instrumentPosition->Memcache2HermiteCache(tol);
706 }
708 int aleCacheSize = m_instrumentPosition->cacheSize();
709 if (aleCacheSize > 3) {
711 }
712 }
713
714
715 if (!m_sunPosition->IsCached()) {
716 int sunPositionCacheSize = cacheSize;
717 if (cacheSize > 2) sunPositionCacheSize = 2;
719 startTime.Et() - *m_startTimePadding,
720 endTime.Et() + *m_endTimePadding,
721 sunPositionCacheSize);
722 }
723
724 // Save the time and cache size
725 *m_startTime = startTime;
726 *m_endTime = endTime;
727 *m_cacheSize = cacheSize;
728 m_et = NULL;
729
730 // Unload the kernels (TODO: Can this be done faster)
731 for (int i = 0; i < m_kernels->size(); i++) {
732 FileName file(m_kernels->at(i));
733 QString fileName = file.expanded();
734 unload_c(fileName.toLatin1().data());
735 }
736
737 m_kernels->clear();
738
740 }
741
742
751 if (m_startTime) {
752 return *m_startTime;
753 }
754
755 return iTime();
756 }
757
766 if (m_endTime) {
767 return *m_endTime;
768 }
769
770 return iTime();
771 }
772
787 void Spice::setTime(const iTime &et) {
788
789 if (m_et == NULL) {
790 m_et = new iTime();
791
792 // Before the Spice is cached, but after the camera aberration correction
793 // is set, check to see if the instrument position kernel was created
794 // by spkwriter. If so turn off aberration corrections because the camera
795 // set aberration corrections are included in the spk already.
796 string abcorr;
797 if (*m_cacheSize == 0) {
798 if (m_startTime->Et() == 0.0 && m_endTime->Et() == 0.0
799 && getSpkAbCorrState(abcorr)) {
800 instrumentPosition()->SetAberrationCorrection("NONE");
801 }
802 }
803 }
804
805 *m_et = et;
806
811
812 std::vector<double> uB = m_bodyRotation->ReferenceVector(m_sunPosition->Coordinate());
813 m_uB[0] = uB[0];
814 m_uB[1] = uB[1];
815 m_uB[2] = uB[2];
816
818 }
819
829 void Spice::instrumentPosition(double p[3]) const {
831 }
832
842 void Spice::instrumentBodyFixedPosition(double p[3]) const {
843 if (m_et == NULL) {
844 QString msg = "Unable to retrieve instrument's body fixed position."
845 " Spice::SetTime must be called first.";
846 throw IException(IException::Programmer, msg, _FILEINFO_);
847 }
848
850 p[0] = sB[0];
851 p[1] = sB[1];
852 p[2] = sB[2];
853 }
854
860 void Spice::instrumentBodyFixedVelocity(double v[3]) const {
861 if (m_et == NULL) {
862 QString msg = "Unable to retrieve instrument's body fixed velocity."
863 " Spice::SetTime must be called first.";
864 throw IException(IException::Programmer, msg, _FILEINFO_);
865 }
866
867 std::vector<double> state;
868 state.push_back(m_instrumentPosition->Coordinate()[0]);
869 state.push_back(m_instrumentPosition->Coordinate()[1]);
870 state.push_back(m_instrumentPosition->Coordinate()[2]);
871 state.push_back(m_instrumentPosition->Velocity()[0]);
872 state.push_back(m_instrumentPosition->Velocity()[1]);
873 state.push_back(m_instrumentPosition->Velocity()[2]);
874
875 std::vector<double> vB = m_bodyRotation->ReferenceVector(state);
876 v[0] = vB[3];
877 v[1] = vB[4];
878 v[2] = vB[5];
879 }
880
881
892 if (m_et == NULL) {
893 QString msg = "Unable to retrieve the time."
894 " Spice::SetTime must be called first.";
895 throw IException(IException::Programmer, msg, _FILEINFO_);
896 }
897 return *m_et;
898 }
899
900
909 void Spice::sunPosition(double p[3]) const {
910 if (m_et == NULL) {
911 QString msg = "Unable to retrieve sun's position."
912 " Spice::SetTime must be called first.";
913 throw IException(IException::Programmer, msg, _FILEINFO_);
914 }
915 p[0] = m_uB[0];
916 p[1] = m_uB[1];
917 p[2] = m_uB[2];
918 }
919
927 return sqrt(pow(sB[0], 2) + pow(sB[1], 2) + pow(sB[2], 2));
928 }
929
937 void Spice::radii(Distance r[3]) const {
938 for (int i = 0; i < 3; i++)
939 r[i] =m_target->radii()[i];
940 }
941
948 SpiceInt Spice::naifBodyCode() const {
949 return (int) m_target->naifBodyCode();
950 }
951
957 SpiceInt Spice::naifSpkCode() const {
958 return *m_spkCode;
959 }
960
966 SpiceInt Spice::naifCkCode() const {
967 return *m_ckCode;
968 }
969
975 SpiceInt Spice::naifIkCode() const {
976 return *m_ikCode;
977 }
978
985 SpiceInt Spice::naifSclkCode() const {
986 return *m_sclkCode;
987 }
988
996 SpiceInt Spice::naifBodyFrameCode() const {
997 return *m_bodyFrameCode;
998 }
999
1000
1008
1009
1017 return 1.0;
1018 };
1019
1020
1032 SpiceInt Spice::getInteger(const QString &key, int index) {
1033 return readValue(key, SpiceIntType, index).toInt();
1034 }
1035
1046 SpiceDouble Spice::getDouble(const QString &key, int index) {
1047 return readValue(key, SpiceDoubleType, index).toDouble();
1048 }
1049
1050
1060 iTime Spice::getClockTime(QString clockValue, int sclkCode, bool clockTicks) {
1061 if (sclkCode == -1) {
1062 sclkCode = naifSclkCode();
1063 }
1064
1065 iTime result;
1066
1067 QString key = "CLOCK_ET_" + Isis::toString(sclkCode) + "_" + clockValue;
1068 QVariant storedClockTime = getStoredResult(key, SpiceDoubleType);
1069
1070 if (storedClockTime.isNull()) {
1071 SpiceDouble timeOutput;
1073 if (clockTicks) {
1074 sct2e_c(sclkCode, (SpiceDouble) clockValue.toDouble(), &timeOutput);
1075 }
1076 else {
1077 scs2e_c(sclkCode, clockValue.toLatin1().data(), &timeOutput);
1078 }
1080 storedClockTime = timeOutput;
1081 storeResult(key, SpiceDoubleType, timeOutput);
1082 }
1083
1084 result = storedClockTime.toDouble();
1085
1086 return result;
1087 }
1088
1089
1100 QVariant Spice::readValue(QString key, SpiceValueType type, int index) {
1101 QVariant result;
1102
1103 if (m_usingNaif && !m_usingAle) {
1105
1106 // This is the success status of the naif call
1107 SpiceBoolean found = false;
1108
1109 // Naif tells us how many values were read, but we always just read one.
1110 // Use this variable to make naif happy.
1111 SpiceInt numValuesRead;
1112
1113 if (type == SpiceDoubleType) {
1114 SpiceDouble kernelValue;
1115 gdpool_c(key.toLatin1().data(), (SpiceInt)index, 1,
1116 &numValuesRead, &kernelValue, &found);
1117
1118 if (found && numValuesRead > 0)
1119 result = kernelValue;
1120 }
1121 else if (type == SpiceStringType) {
1122 char kernelValue[512];
1123 gcpool_c(key.toLatin1().data(), (SpiceInt)index, 1, sizeof(kernelValue),
1124 &numValuesRead, kernelValue, &found);
1125
1126 if (found && numValuesRead > 0)
1127 result = kernelValue;
1128 }
1129 else if (type == SpiceIntType) {
1130 SpiceInt kernelValue;
1131 gipool_c(key.toLatin1().data(), (SpiceInt)index, 1, &numValuesRead,
1132 &kernelValue, &found);
1133
1134 if (found && numValuesRead > 0)
1135 result = (int)kernelValue;
1136 }
1137
1138 if (!found) {
1139 QString msg = "Can not find [" + key + "] in text kernels";
1140 throw IException(IException::Io, msg, _FILEINFO_);
1141 }
1142 else if (numValuesRead == 0){
1143 QString msg = "Found " + key + "] in text kernels, but no values were identified and read.";
1144 throw IException(IException::Io, msg, _FILEINFO_);
1145 }
1146
1147 storeValue(key, index, type, result);
1149 }
1150 else {
1151 // Read from PvlObject that is our naif keywords
1152 result = readStoredValue(key, type, index);
1153
1154 if (result.isNull()) {
1155 QString msg = "The camera is requesting spice data [" + key + "] that "
1156 "was not attached, please re-run spiceinit";
1157 throw IException(IException::Unknown, msg, _FILEINFO_);
1158 }
1159 }
1160
1161 return result;
1162 }
1163
1164
1165 void Spice::storeResult(QString name, SpiceValueType type, QVariant value) {
1166 if (type == SpiceDoubleType) {
1167 EndianSwapper swapper("LSB");
1168
1169 double doubleVal = value.toDouble();
1170 doubleVal = swapper.Double(&doubleVal);
1171 QByteArray byteCode((char *) &doubleVal, sizeof(double));
1172 value = byteCode;
1173 type = SpiceByteCodeType;
1174 }
1175
1176 storeValue(name + "_COMPUTED", 0, type, value);
1177 }
1178
1179
1180 QVariant Spice::getStoredResult(QString name, SpiceValueType type) {
1181 bool wasDouble = false;
1182
1183 if (type == SpiceDoubleType) {
1184 wasDouble = true;
1185 type = SpiceByteCodeType;
1186 }
1187
1188 QVariant stored = readStoredValue(name + "_COMPUTED", type, 0);
1189
1190 if (wasDouble && !stored.isNull()) {
1191 EndianSwapper swapper("LSB");
1192 double doubleVal = swapper.Double((void *)QByteArray::fromHex(
1193 stored.toByteArray()).data());
1194 stored = doubleVal;
1195 }
1196
1197 return stored;
1198 }
1199
1200
1201 void Spice::storeValue(QString key, int index, SpiceValueType type,
1202 QVariant value) {
1203 if (!m_naifKeywords->hasKeyword(key)) {
1204 m_naifKeywords->addKeyword(PvlKeyword(key));
1205 }
1206
1207 PvlKeyword &storedKey = m_naifKeywords->findKeyword(key);
1208
1209 while(index >= storedKey.size()) {
1210 storedKey.addValue("");
1211 }
1212
1213 if (type == SpiceByteCodeType) {
1214 storedKey[index] = QString(value.toByteArray().toHex().data());
1215 }
1216 else if (type == SpiceStringType) {
1217 storedKey[index] = value.toString();
1218 }
1219 else if (type == SpiceDoubleType) {
1220 storedKey[index] = toString(value.toDouble());
1221 }
1222 else if (type == SpiceIntType) {
1223 storedKey[index] = toString(value.toInt());
1224 }
1225 else {
1226 QString msg = "Unable to store variant in labels for key [" + key + "]";
1227 throw IException(IException::Unknown, msg, _FILEINFO_);
1228 }
1229 }
1230
1231
1232 QVariant Spice::readStoredValue(QString key, SpiceValueType type,
1233 int index) {
1234 // Read from PvlObject that is our naif keywords
1235 QVariant result;
1236
1237 if (m_naifKeywords->hasKeyword(key) && (!m_usingNaif || m_usingAle)) {
1238 PvlKeyword &storedKeyword = m_naifKeywords->findKeyword(key);
1239
1240 try {
1241 if (type == SpiceDoubleType) {
1242 result = toDouble(storedKeyword[index]);
1243 }
1244 else if (type == SpiceStringType) {
1245 result = storedKeyword[index];
1246 }
1247 else if (type == SpiceByteCodeType || SpiceStringType) {
1248 result = storedKeyword[index].toLatin1();
1249 }
1250 else if (type == SpiceIntType) {
1251 result = toInt(storedKeyword[index]);
1252 }
1253 }
1254 catch(IException &e) {
1255 e.print();
1256 }
1257 }
1258
1259 return result;
1260 }
1261
1273 QString Spice::getString(const QString &key, int index) {
1274 return readValue(key, SpiceStringType, index).toString();
1275 }
1276
1277
1290 void Spice::subSpacecraftPoint(double &lat, double &lon) {
1292
1293 if (m_et == NULL) {
1294 QString msg = "Unable to retrieve subspacecraft position."
1295 " Spice::SetTime must be called first.";
1296 throw IException(IException::Programmer, msg, _FILEINFO_);
1297 }
1298
1299 SpiceDouble usB[3], dist;
1300 std::vector<double> vsB = m_bodyRotation->ReferenceVector(m_instrumentPosition->Coordinate());
1301 SpiceDouble sB[3];
1302 sB[0] = vsB[0];
1303 sB[1] = vsB[1];
1304 sB[2] = vsB[2];
1305 unorm_c(sB, usB, &dist);
1306
1307 std::vector<Distance> radii = target()->radii();
1308 SpiceDouble a = radii[0].kilometers();
1309 SpiceDouble b = radii[1].kilometers();
1310 SpiceDouble c = radii[2].kilometers();
1311
1312 SpiceDouble originB[3];
1313 originB[0] = originB[1] = originB[2] = 0.0;
1314
1315 SpiceBoolean found;
1316 SpiceDouble subB[3];
1317
1318 surfpt_c(originB, usB, a, b, c, subB, &found);
1319
1320 SpiceDouble mylon, mylat;
1321 reclat_c(subB, &a, &mylon, &mylat);
1322 lat = mylat * 180.0 / PI;
1323 lon = mylon * 180.0 / PI;
1324 if (lon < 0.0) lon += 360.0;
1325
1327 }
1328
1329
1341 void Spice::subSolarPoint(double &lat, double &lon) {
1343
1344 if (m_et == NULL) {
1345 QString msg = "Unable to retrieve subsolar point."
1346 " Spice::SetTime must be called first.";
1347 throw IException(IException::Programmer, msg, _FILEINFO_);
1348 }
1349
1350 SpiceDouble uuB[3], dist;
1351 unorm_c(m_uB, uuB, &dist);
1352 std::vector<Distance> radii = target()->radii();
1353
1354 SpiceDouble a = radii[0].kilometers();
1355 SpiceDouble b = radii[1].kilometers();
1356 SpiceDouble c = radii[2].kilometers();
1357
1358 SpiceDouble originB[3];
1359 originB[0] = originB[1] = originB[2] = 0.0;
1360
1361 SpiceBoolean found;
1362 SpiceDouble subB[3];
1363 surfpt_c(originB, uuB, a, b, c, subB, &found);
1364
1365 SpiceDouble mylon, mylat;
1366 reclat_c(subB, &a, &mylon, &mylat);
1367
1368 lat = mylat * 180.0 / PI;
1369 lon = mylon * 180.0 / PI;
1370 if (lon < 0.0) lon += 360.0;
1372 }
1373
1374
1381 return m_target;
1382 }
1383
1384
1390 QString Spice::targetName() const {
1391 return m_target->name();
1392 }
1393
1394
1395 double Spice::sunToBodyDist() const {
1396 std::vector<double> sunPosition = m_sunPosition->Coordinate();
1397 std::vector<double> bodyRotation = m_bodyRotation->Matrix();
1398
1399 double sunPosFromTarget[3];
1400 mxv_c(&bodyRotation[0], &sunPosition[0], sunPosFromTarget);
1401
1402 return vnorm_c(sunPosFromTarget);
1403 }
1404
1405
1414
1415 if (m_target->isSky()) {
1417 return;
1418 }
1419
1420 if (m_usingAle || !m_usingNaif) {
1421 double og_time = m_bodyRotation->EphemerisTime();
1424
1425 std::vector<double> bodyRotMat = m_bodyRotation->Matrix();
1426 std::vector<double> sunPos = m_sunPosition->Coordinate();
1427 std::vector<double> sunVel = m_sunPosition->Velocity();
1428 double sunAv[3];
1429
1430 ucrss_c(&sunPos[0], &sunVel[0], sunAv);
1431
1432 double npole[3];
1433 for (int i = 0; i < 3; i++) {
1434 npole[i] = bodyRotMat[6+i];
1435 }
1436
1437 double x[3], y[3], z[3];
1438 vequ_c(sunAv, z);
1439 ucrss_c(npole, z, x);
1440 ucrss_c(z, x, y);
1441
1442 double trans[3][3];
1443 for (int i = 0; i < 3; i++) {
1444 trans[0][i] = x[i];
1445 trans[1][i] = y[i];
1446 trans[2][i] = z[i];
1447 }
1448
1449 double pos[3];
1450 mxv_c(trans, &sunPos[0], pos);
1451
1452 double radius, ls, lat;
1453 reclat_c(pos, &radius, &ls, &lat);
1454
1456
1460 return;
1461 }
1462
1463 if (m_bodyRotation->IsCached()) return;
1464
1465 double tipm[3][3], npole[3];
1466 char frameName[32];
1467 SpiceInt frameCode;
1468 SpiceBoolean found;
1469
1470 cidfrm_c(*m_spkBodyCode, sizeof(frameName), &frameCode, frameName, &found);
1471
1472 if (found) {
1473 pxform_c("J2000", frameName, et.Et(), tipm);
1474 }
1475 else {
1476 tipbod_c("J2000", *m_spkBodyCode, et.Et(), tipm);
1477 }
1478
1479 for (int i = 0; i < 3; i++) {
1480 npole[i] = tipm[2][i];
1481 }
1482
1483 double state[6], lt;
1484 spkez_c(*m_spkBodyCode, et.Et(), "J2000", "NONE", 10, state, &lt);
1485
1486 double uavel[3];
1487 ucrss_c(state, &state[3], uavel);
1488
1489 double x[3], y[3], z[3];
1490 vequ_c(uavel, z);
1491 ucrss_c(npole, z, x);
1492 ucrss_c(z, x, y);
1493
1494 double trans[3][3];
1495 for (int i = 0; i < 3; i++) {
1496 trans[0][i] = x[i];
1497 trans[1][i] = y[i];
1498 trans[2][i] = z[i];
1499 }
1500
1501 spkez_c(10, et.Et(), "J2000", "LT+S", *m_spkBodyCode, state, &lt);
1502
1503 double pos[3];
1504 mxv_c(trans, state, pos);
1505
1506 double radius, ls, lat;
1507 reclat_c(pos, &radius, &ls, &lat);
1508
1510
1512
1513 }
1514
1515
1522 if (m_et) {
1524 return *m_solarLongitude;
1525 }
1526
1527 return Longitude();
1528 }
1529
1530
1539
1540 // Get the kernel group and check main kernels
1541 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
1542 std::vector<string> keywords;
1543 keywords.push_back("TargetPosition");
1544
1545 if (kernels.hasKeyword("SpacecraftPosition")) {
1546 keywords.push_back("SpacecraftPosition");
1547 }
1548 else {
1549 keywords.push_back("InstrumentPosition");
1550 }
1551
1552 if (kernels.hasKeyword("SpacecraftPointing")) {
1553 keywords.push_back("SpacecraftPointing");
1554 }
1555 else {
1556 keywords.push_back("InstrumentPointing");
1557 }
1558
1559 if (kernels.hasKeyword("Frame")) {
1560 keywords.push_back("Frame");
1561 }
1562
1563 if (kernels.hasKeyword("Extra")) {
1564 keywords.push_back("Extra");
1565 }
1566
1567 PvlKeyword key;
1568 for (int ikey = 0; ikey < (int) keywords.size(); ikey++) {
1569 key = kernels[ikey];
1570
1571 for (int i = 0; i < key.size(); i++) {
1572 if (key[i] == "") return false;
1573 if (key[i].toUpper() == "NULL") return false;
1574 if (key[i].toUpper() == "NADIR") return false;
1575 if (key[i].toUpper() == "TABLE") return false;
1576 }
1577 }
1578 return true;
1579 }
1580
1581
1590 return !(m_et == NULL);
1591 }
1592
1593
1602 return m_sunPosition;
1603 }
1604
1615
1624 return m_bodyRotation;
1625 }
1626
1637
1638 bool Spice::isUsingAle(){
1639 return m_usingAle;
1640 }
1641}
@ 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
IO Handler for Isis Cubes.
Definition Cube.h:168
bool hasBlob(const QString &name, const QString &type)
Check to see if the cube contains a BLOB.
Definition Cube.cpp:2025
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
Distance measurement, usually in meters.
Definition Distance.h:34
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
File name manipulation and expansion.
Definition FileName.h:100
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
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Provides interface to user configurable Light Time correction feature.
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
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
int size() const
Returns the number of values stored in this keyword.
Definition PvlKeyword.h:133
void addValue(QString value, QString unit="")
Adds a value with units.
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:276
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
QString name() const
Gets the shape name.
Provides swap observer/target and improved light time correction.
virtual void setTime(const iTime &time)
Sets the ephemeris time and reads the spacecraft and sun position from the kernels at that instant in...
Definition Spice.cpp:787
QString getString(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1273
virtual iTime getClockTime(QString clockValue, int sclkCode=-1, bool clockTicks=false)
This converts the spacecraft clock ticks value (clockValue) to an iTime.
Definition Spice.cpp:1060
SpiceDouble * m_startTimePadding
Kernels pvl group StartPadding keyword value.
Definition Spice.h:403
Target * m_target
Target of the observation.
Definition Spice.h:381
bool m_usingNaif
Indicates whether we are reading values from the NaifKeywords PvlObject in cube.
Definition Spice.h:429
QVariant readValue(QString key, SpiceValueType type, int index=0)
This should be used for reading ALL text naif kernel values.
Definition Spice.cpp:1100
Longitude * m_solarLongitude
Body rotation solar longitude value.
Definition Spice.h:383
bool m_usingAle
Indicate whether we are reading values from an ISD returned from ALE.
Definition Spice.h:432
virtual Longitude solarLongitude()
Returns the solar longitude.
Definition Spice.cpp:1521
Spice(Cube &cube)
Constructs a Spice object and loads SPICE kernels using information from the label object.
Definition Spice.cpp:64
SpiceInt * m_ikCode
Instrument kernel (IK) code.
Definition Spice.h:420
virtual void instrumentBodyFixedVelocity(double v[3]) const
Returns the spacecraft velocity in body-fixed frame km/sec units.
Definition Spice.cpp:860
SpiceRotation * m_instrumentRotation
Instrument spice rotation.
Definition Spice.h:407
SpiceInt * m_sclkCode
Spacecraft clock correlation kernel (SCLK) code.
Definition Spice.h:421
void csmInit(Cube &cube, Pvl label)
Initialize the Spice object for a CSMCamera.
Definition Spice.cpp:97
virtual void computeSolarLongitude(iTime et)
Computes the solar longitude for the given ephemeris time.
Definition Spice.cpp:1412
SpicePosition * m_instrumentPosition
Instrument spice position.
Definition Spice.h:406
bool m_allowDownsizing
Indicates whether to allow downsizing.
Definition Spice.h:411
SpiceDouble * m_endTimePadding
Kernels pvl group EndPadding keyword value.
Definition Spice.h:404
SpicePosition * m_sunPosition
Sun spice position.
Definition Spice.h:408
SpiceInt * m_bodyFrameCode
Naif's BODY_FRAME_CODE value.
Definition Spice.h:423
virtual SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition Spice.cpp:1623
virtual double targetCenterDistance() const
Calculates and returns the distance from the spacecraft to the target center.
Definition Spice.cpp:925
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
virtual iTime cacheEndTime() const
Accessor method for the cache end time.
Definition Spice.cpp:765
virtual ~Spice()
Destroys the Spice object.
Definition Spice.cpp:511
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition Spice.cpp:937
SpiceValueType
NAIF value primitive type.
Definition Spice.h:348
@ SpiceByteCodeType
SpiceByteCode type.
Definition Spice.h:352
@ SpiceIntType
SpiceInt type.
Definition Spice.h:351
@ SpiceStringType
SpiceString type.
Definition Spice.h:350
@ SpiceDoubleType
SpiceDouble type.
Definition Spice.h:349
PvlObject * m_naifKeywords
NaifKeywords PvlObject from cube.
Definition Spice.h:427
void init(Pvl &pvl, bool noTables, nlohmann::json isd=NULL)
Initialization of Spice object.
Definition Spice.cpp:154
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
PvlObject getStoredNaifKeywords() const
This returns the PvlObject that stores all of the requested Naif data and can be a replacement for fu...
Definition Spice.cpp:1005
SpiceInt naifCkCode() const
This returns the NAIF CK code to use when reading from CK kernels.
Definition Spice.cpp:966
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
SpiceInt * m_spkBodyCode
Spacecraft and planet ephemeris kernel (SPK) body code.
Definition Spice.h:422
virtual iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions.
Definition Spice.cpp:891
SpiceInt * m_ckCode
Camera kernel (CK) code.
Definition Spice.h:419
SpiceInt * m_spkCode
Spacecraft and planet ephemeris kernel (SPK) code.
Definition Spice.h:418
bool hasKernels(Pvl &lab)
Returns true if the kernel group has kernel files.
Definition Spice.cpp:1538
virtual SpiceRotation * instrumentRotation() const
Accessor method for the instrument rotation.
Definition Spice.cpp:1634
SpiceDouble * m_cacheSize
Cache size. Note: This value is 1 for Framing cameras.
Definition Spice.h:401
void defaultInit()
Default initialize the members of the SPICE object.
Definition Spice.cpp:107
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
SpiceInt naifSclkCode() const
This returns the NAIF SCLK code to use when reading from instrument kernels.
Definition Spice.cpp:985
QString targetName() const
Returns the QString name of the target.
Definition Spice.cpp:1390
SpiceInt naifBodyFrameCode() const
This returns the NAIF body frame code.
Definition Spice.cpp:996
void load(PvlKeyword &key, bool notab)
Loads/furnishes NAIF kernel(s)
Definition Spice.cpp:486
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition Spice.h:369
virtual iTime cacheStartTime() const
Accessor method for the cache start time.
Definition Spice.cpp:750
iTime * m_endTime
Corrected end (shutter close) time of the observation.
Definition Spice.h:400
iTime * m_et
Ephemeris time (read NAIF documentation for a detailed description)
Definition Spice.h:382
bool isTimeSet()
Returns true if time has been initialized.
Definition Spice.cpp:1589
QVector< QString > * m_kernels
Vector containing kernels filenames.
Definition Spice.h:396
SpiceRotation * m_bodyRotation
Body spice rotation.
Definition Spice.h:409
iTime * m_startTime
Corrected start (shutter open) time of the observation.
Definition Spice.h:399
virtual SpicePosition * sunPosition() const
Accessor method for the sun position.
Definition Spice.cpp:1601
SpiceDouble getDouble(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1046
SpiceInt getInteger(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1032
virtual void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1290
virtual double resolution()
Virtual method that returns the pixel resolution of the sensor in meters/pix.
Definition Spice.cpp:1016
Obtain SPICE position information for a body.
int cacheSize() const
Get the size of the current cached positions.
void Memcache2HermiteCache(double tolerance)
This method reduces the cache for position, time and velocity to the minimum number of values needed ...
bool HasVelocity()
Return the flag indicating whether the velocity exists.
const std::vector< double > & Velocity()
Return the current J2000 velocity.
@ Memcache
Object is reading from cached table.
void LoadCache(double startTime, double endTime, int size)
Cache J2000 position over a time range.
bool IsCached() const
Is this position cached.
virtual const std::vector< double > & SetEphemerisTime(double et)
Return J2000 coordinate at given time.
Source GetSource()
Return the source of the position.
virtual const std::vector< double > & Coordinate()
Return the current J2000 position.
Obtain SPICE rotation information for a body.
std::vector< double > Matrix()
Return the full rotation TJ as a matrix.
double EphemerisTime() const
Accessor method to get current ephemeris time.
Source GetSource()
Accessor method to get the rotation source.
void LoadTimeCache()
Load the time cache.
void LoadCache(double startTime, double endTime, int size)
Cache J2000 rotation quaternion over a time range.
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
void SetEphemerisTime(double et)
Return the J2000 to reference frame quaternion at given time.
@ Yes
Downsize the cache.
@ Memcache
From cached table.
void MinimizeCache(DownsizeStatus status)
Set the downsize status to minimize cache.
bool IsCached() const
Checks if the cache is empty.
Class for storing Table blobs information.
Definition Table.h:61
This class is used to create and store valid Isis targets.
Definition Target.h:63
SpiceInt naifBodyCode() const
This returns the NAIF body code of the target.
Definition Target.cpp:522
void setRadii(std::vector< Distance > radii)
Sets the radii of the body.
Definition Target.cpp:640
std::vector< Distance > radii() const
Returns the radii of the body in km.
Definition Target.cpp:557
ShapeModel * shape() const
Return the shape.
Definition Target.cpp:680
bool isSky() const
Return if our target is the sky.
Definition Target.cpp:215
QString name() const
Return target name.
Definition Target.cpp:541
Parse and return pieces of a time string.
Definition iTime.h:65
double Et() const
Returns the ephemeris time (TDB) representation of the time as a double.
Definition iTime.h:126
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
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
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.