File failed to load: https://isis.astrogeology.usgs.gov/6.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
Target.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "Target.h"
8 
9 #include "Angle.h"
10 #include "Distance.h"
11 #include "EllipsoidShape.h"
12 #include "FileName.h"
13 #include "IException.h"
14 #include "NaifStatus.h"
15 #include "Pvl.h"
16 #include "PvlGroup.h"
17 #include "ShapeModelFactory.h"
18 #include "SpecialPixel.h"
19 #include "Spice.h"
20 
21 
22 using namespace std;
23 
24 namespace Isis {
25 
37  // TODO: what is needed to initialize?
38  Target::Target(Spice *spice, Pvl &lab) {
39 
40  // Initialize members
41  init();
42  m_bodyCode = new SpiceInt;
43  m_systemCode = new SpiceInt;
44  m_radii.resize(3, Distance());
45 
46  m_spice = spice;
47 
48  // If we get this far, we know we have a kernels group. Spice requires it.
49  PvlGroup &kernels = lab.findGroup("Kernels", Pvl::Traverse);
50 
51  PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
52  m_name = new QString;
53  *m_name = inst["TargetName"][0];
54  QString trykey = "NaifIkCode";
55 
56  m_systemName = new QString;
57 
58  if (kernels.hasKeyword("NaifFrameCode")) {
59  trykey = "NaifFrameCode";
60  }
61 
62  if (name().toUpper() == "SKY") {
63  m_radii[0] = m_radii[1] = m_radii[2] = Distance(1000.0, Distance::Meters);
64  m_sky = true;
65  int ikCode = toInt(kernels[trykey][0]);
66  *m_bodyCode = ikCode / 1000;
67  // Check for override in kernel group
68  if (kernels.hasKeyword("NaifSpkCode")) {
69  *m_bodyCode = (int) kernels["NaifSpkCode"];
70  }
71 
72  *m_systemCode = -1;
73  (*m_systemName).append("THE COSMOS");
74 
75  }
76  else {
77  *m_bodyCode = lookupNaifBodyCode(lab);
78  m_sky = false;
79 
80  *m_systemCode = (*m_bodyCode/100)*100 + 99;
81 
82  SpiceChar naifBuf[40];
83  SpiceBoolean found;
84  bodc2n_c((SpiceInt) *m_systemCode, sizeof(naifBuf), naifBuf, &found);
85  NaifStatus::CheckErrors();
86  string s(naifBuf);
87  (*m_systemName).append(s.c_str());
88 
89  // QString radiiKey = "BODY" + QString((BigInt) naifBodyCode()) + "_RADII";
90  // m_radii[0] = Distance(getDouble(radiiKey, 0), Distance::Kilometers);
91  // m_radii[1] = Distance(getDouble(radiiKey, 1), Distance::Kilometers);
92  // m_radii[2] = Distance(getDouble(radiiKey, 2), Distance::Kilometers);
93  }
94  // Override it if it exists in the labels
95  if (kernels.hasKeyword("NaifBodyCode")) {
96  *m_bodyCode = (int) kernels["NaifBodyCode"];
97  }
98  m_shape = ShapeModelFactory::create(this, lab);
99  }
100 
101 
109  Target::Target(Pvl &label) {
110  // Initialize everything to null
111  m_bodyCode = NULL;
112  m_systemCode = NULL;
113  m_name = NULL;
114  m_systemName = NULL;
115  m_spice = NULL;
116  init();
117 
118  PvlGroup &inst = label.findGroup("Instrument", Pvl::Traverse);
119  QString targetName = inst["TargetName"][0];
120  setName(targetName);
121 
122  m_shape = ShapeModelFactory::create(this, label);
123  }
124 
125 
134  Target::Target() {
135  m_bodyCode = NULL;
136  m_systemCode = NULL;
137  m_name = NULL;
138  m_systemName = NULL;
139  m_spice = NULL;
140  init();
141  }
142 
143 
152  void Target::init() {
153  m_shape = NULL;
154  m_originalShape = NULL;
155  m_sky = false;
156  }
157 
158 
162  Target::~Target() {
163  NaifStatus::CheckErrors();
164 
165  delete m_bodyCode;
166  m_bodyCode = NULL;
167 
168  delete m_systemCode;
169  m_systemCode = NULL;
170 
171  delete m_name;
172  m_name = NULL;
173 
174  delete m_systemName;
175  m_systemName = NULL;
176 
177  if (m_radii.size() != 0) {
178  m_radii.clear();
179  }
180 
181  delete m_originalShape;
182  m_originalShape = NULL;
183 
184  delete m_shape;
185  m_shape = NULL;
186  }
187 
188 
190  bool Target::isSky() const {
191  return m_sky;
192  }
193 
194 
201  SpiceInt Target::lookupNaifBodyCode(Pvl &lab) const {
202  SpiceInt code;
203  try {
204  code = lookupNaifBodyCode(*m_name);
205  return code;
206  }
207  catch (IException &e) {
208  try {
209  // Get body code from Isis Naif object if it exists or Naif data pool
210  if (m_spice) {
211  code = m_spice->getInteger("BODY_CODE", 0);
212  return code;
213  }
214  // getInteger automatically calls Spice::readValue which looks in the NaifKeywords
215  else if (lab.hasObject("NaifKeywords")
216  && lab.findObject("NaifKeywords").hasKeyword("BODY_CODE") ) {
217  code = int(lab.findObject("NaifKeywords").findKeyword("BODY_CODE"));
218  return code;
219  }
220  else {
221  throw IException(e,
222  IException::Unknown,
223  "BODY_CODE not found for this Target.",
224  _FILEINFO_);
225  }
226  }
227  catch (IException &e2) {
228  e.append(e2);
229  throw IException(e,
230  IException::Unknown,
231  "Unable to look up NAIF body code for this Target.",
232  _FILEINFO_);
233  }
234  }
235  }
236 
237 
244  SpiceInt Target::lookupNaifBodyCode(QString name) {
245 
246  NaifStatus::CheckErrors();
247  SpiceInt code;
248  SpiceBoolean found;
249  bodn2c_c(name.toLatin1().data(), &code, &found);
250  if (!found) {
251  QString msg = "Could not convert Target [" + name +
252  "] to NAIF body code";
253  throw IException(IException::Io, msg, _FILEINFO_);
254  }
255  NaifStatus::CheckErrors();
256  return code;
257 
258  }
259 
260 
275  PvlGroup Target::radiiGroup(Pvl &cubeLab, const PvlGroup &mapGroup) {
276  PvlGroup mapping = mapGroup;
277 
278  // Check to see if the mapGroup already has the target radii.
279  // If BOTH radii are already in the mapGroup then just return the given
280  // mapping group as is.
281  if (mapping.hasKeyword("EquatorialRadius")
282  && mapping.hasKeyword("PolarRadius")) {
283  return mapping;
284  }
285 
286  // If radii values are not in the given mapping group, we will get the target from the mapping
287  // group or cube label and attempt to use NAIF routines to find the radii.
288  QString target = "";
289  try {
290  if (mapping.hasKeyword("TargetName")) {
291  target = mapping["TargetName"][0];
292  }
293 
294  // if target name not found in mapping group or value was empty string, try instrument group
295  if (target.isEmpty()) {
296  bool hasInstrumentGroup = cubeLab.findObject("IsisCube").hasGroup("Instrument");
297  if (hasInstrumentGroup) {
298  PvlGroup inst = cubeLab.findGroup("Instrument", Pvl::Traverse);
299  if (inst.hasKeyword("TargetName")) {
300  target = inst["TargetName"][0];
301  mapping.addKeyword( PvlKeyword("TargetName", target), PvlContainer::Replace );
302  }
303  }
304  }
305 
306  // target name still not found, throw error
307  if (target.isEmpty()) {
308  throw IException(IException::Unknown,
309  "Unable to find a TargetName keyword in the given PVL.",
310  _FILEINFO_);
311  }
312 
313  // first, attempt to use cached values or run NAIF routine on the target name to get the
314  // radii values. if this fails, the exception will be caught and we will try to find
315  // radii in the NaifKeywords object of the labels
316  PvlGroup radii = Target::radiiGroup(target);
317 
318  // Successfully found radii using target name.
319  // Copy the EquatorialRadius and PolorRadius and we are done.
320  mapping.addKeyword( radii.findKeyword("EquatorialRadius"), PvlContainer::Replace );
321  mapping.addKeyword( radii.findKeyword("PolarRadius"), PvlContainer::Replace );
322  return mapping;
323  }
324  catch (IException &e) {
325  // If all previous attempts fail, look for the radii using the body frame
326  // code in the NaifKeywords object.
327  // Note: We will only look in the given label for the values after SPICELIB
328  // routines have failed, to preserve backwards compatibility (since this
329  // label check is new).
330  if (cubeLab.hasObject("NaifKeywords")) {
331 
332  PvlObject naifKeywords = cubeLab.findObject("NaifKeywords");
333 
334  // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object
335 
336  try {
337 
338  SpiceInt bodyCode = 0;
339  try {
340  // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object
341  bodyCode = lookupNaifBodyCode(target);
342  }
343  catch (IException &e2) {
344  throw IException(e, IException::Unknown, e2.what(), _FILEINFO_);
345  }
346  QString radiiKeyword = "BODY" + toString(int(bodyCode)) + "_RADII";
347 
348  if (naifKeywords.hasKeyword(radiiKeyword)) {
349  PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword);
350  mapping.addKeyword( PvlKeyword("EquatorialRadius",
351  toString(toDouble(radii[0]) * 1000.0), "meters"),
352  PvlContainer::Replace);
353  mapping.addKeyword( PvlKeyword("PolarRadius",
354  toString(toDouble(radii[2]) * 1000.0), "meters"),
355  PvlContainer::Replace);
356  return mapping;
357  }
358  }
359  catch (IException &e) {
360  // Try using the value of the BODY_FRAME_CODE keyword in the NaifKeywords PVL object
361  if (naifKeywords.hasKeyword("BODY_FRAME_CODE")) {
362 
363  PvlKeyword bodyFrame = naifKeywords.findKeyword("BODY_FRAME_CODE");
364  QString radiiKeyword = "BODY" + bodyFrame[0] + "_RADII";
365 
366  if (naifKeywords.hasKeyword(radiiKeyword)) {
367  PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword);
368  mapping.addKeyword( PvlKeyword("EquatorialRadius",
369  toString(toDouble(radii[0]) * 1000.0),
370  "meters"),
371  PvlContainer::Replace);
372  mapping.addKeyword( PvlKeyword("PolarRadius",
373  toString(toDouble(radii[2]) * 1000.0),
374  "meters"),
375  PvlContainer::Replace);
376  return mapping;
377  }
378  }
379  }
380  }
381 
382  // If we get this far, we know the cube has no NaifKeywords object and previous attempts to
383  // find radii in the mapping group or using spice IDs have failed
384  QString msg = "Unable to find Equatorial and Polar radii for target [" + target + "].";
385  throw IException(e, IException::Unknown, msg, _FILEINFO_);
386  }
387  }
388 
389 
403  PvlGroup Target::radiiGroup(QString target) {
404 
405  if (target.isEmpty()) {
406  throw IException(IException::Unknown,
407  "Unable to find TargetRadii. The given TargetName is empty.",
408  _FILEINFO_);
409  }
410 
411  static QMap<QString, PvlGroup> cachedResults;
412 
413  PvlGroup mapping("Mapping");
414  if (cachedResults.contains(target)) {
415  mapping = cachedResults[target];
416  }
417  else {
418 
419  SpiceInt bodyCode = 0;
420  try {
421  bodyCode = lookupNaifBodyCode(target);
422  }
423  catch (IException &e) {
424  QString msg = "Unable to find target radii for given target ["
425  + target + "].";
426  throw IException(IException::Io, msg, _FILEINFO_);
427  }
428 
429  PvlGroup radiiGroup = Target::radiiGroup(int(bodyCode));
430  mapping += PvlKeyword("TargetName", target);
431  mapping += radiiGroup.findKeyword("EquatorialRadius");
432  mapping += radiiGroup.findKeyword("PolarRadius");
433  cachedResults[target] = mapping;
434  }
435 
436  return mapping;
437  }
438 
439 
451  PvlGroup Target::radiiGroup(int bodyCode) {
452 
453  // Load the most recent target attitude and shape kernel for NAIF
454  static bool pckLoaded = false;
455 
456  NaifStatus::CheckErrors();
457 
458  FileName kern("$base/kernels/pck/pck?????.tpc");
459  kern = kern.highestVersion();
460  QString kernName = kern.expanded();
461 
462  if(!pckLoaded) {
463  furnsh_c(kernName.toLatin1().data());
464  pckLoaded = true;
465  }
466 
467  // Get the radii from NAIF
468  SpiceInt n;
469  SpiceDouble radii[3];
470  bodvar_c(bodyCode, "RADII", &n, radii);
471 
472  try {
473  NaifStatus::CheckErrors();
474  }
475  catch (IException &e) {
476  QString msg = "Unable to find radii for target code [" + toString(bodyCode)
477  + "]. Target code was not found in furnished kernels.";
478 
479  throw IException(e, IException::Unknown, msg, _FILEINFO_);
480  }
481 
482  PvlGroup radiiGroup;
483  radiiGroup += PvlKeyword("EquatorialRadius", toString(radii[0] * 1000.0), "meters");
484  radiiGroup += PvlKeyword("PolarRadius", toString(radii[2] * 1000.0), "meters");
485 
486  return radiiGroup;
487 
488  }
489 
490 
497  SpiceInt Target::naifBodyCode() const {
498  return *m_bodyCode;
499  }
500 
501 
510  SpiceInt Target::naifPlanetSystemCode() const {
511  return *m_systemCode;
512  }
513 
514 
516  QString Target::name() const {
517  return *m_name;
518  }
519 
520 
522  QString Target::systemName() const {
523  return *m_systemName;
524  }
525 
526 
532  std::vector<Distance> Target::radii() const {
533  return m_radii;
534  }
535 
536 
537  int Target::frameType() {
538  return spice()->bodyRotation()->getFrameType();
539  }
540 
541 
542  std::vector<Angle> Target::poleRaCoefs() {
543  return spice()->bodyRotation()->poleRaCoefs();
544  }
545 
546 
547  std::vector<Angle> Target::poleDecCoefs() {
548  return spice()->bodyRotation()->poleDecCoefs();
549  }
550 
551 
552  std::vector<Angle> Target::pmCoefs() {
553  return spice()->bodyRotation()->pmCoefs();
554  }
555 
556 
557  std::vector<double> Target::poleRaNutPrecCoefs() {
558  return spice()->bodyRotation()->poleRaNutPrecCoefs();
559  }
560 
561 
562  std::vector<double> Target::poleDecNutPrecCoefs() {
563  return spice()->bodyRotation()->poleDecNutPrecCoefs();
564  }
565 
566 
567  std::vector<double> Target::pmNutPrecCoefs() {
568  return spice()->bodyRotation()->pmNutPrecCoefs();
569  }
570 
571 
572  std::vector<Angle> Target::sysNutPrecConstants() {
573  return spice()->bodyRotation()->sysNutPrecConstants();
574  }
575 
576 
577  std::vector<Angle> Target::sysNutPrecCoefs() {
578  return spice()->bodyRotation()->sysNutPrecCoefs();
579  }
580 
581 
585  void Target::restoreShape() {
586  if (m_shape->name() != "Ellipsoid") {
587  // Nothing to do
588  return;
589  }
590  // If we don't have a saved original shape, just stick to the current shape
591  else if (m_originalShape == NULL) {
592  // Nothing to do
593  return;
594  }
595  m_shape = m_originalShape;
596  m_originalShape = NULL;
597  }
598 
599 
603  void Target::setShapeEllipsoid() {
604  // Save the current shape to restore later
605  m_originalShape = m_shape;
606  m_shape = new EllipsoidShape(this);
607  }
608 
609 
615  void Target::setRadii(std::vector<Distance> radii) {
616  if (m_radii.size() < 3) {
617  m_radii.resize(3, Distance());
618  }
619  m_radii[0] = radii[0];
620  m_radii[1] = radii[1];
621  m_radii[2] = radii[2];
622  }
623 
624 
632  void Target::setName(QString name) {
633  if (m_name == NULL) {
634  m_name = new QString;
635  }
636  *m_name = name;
637  }
638 
639 
647  void Target::setSpice(Spice *spice) {
648  m_spice = spice;
649  }
650 
651 
655  ShapeModel *Target::shape() const {
656  return m_shape;
657  }
658 
659 
663  Spice *Target::spice() const {
664  return m_spice;
665  }
666 }
Isis::PvlObject::findGroup
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:129
Isis::PvlObject
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:61
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::PvlContainer::addKeyword
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
Definition: PvlContainer.cpp:202
Isis::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::PvlContainer::hasKeyword
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Definition: PvlContainer.cpp:159
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::IException::what
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:375
Isis::EllipsoidShape
Define shapes and provide utilities for ISIS targets.
Definition: EllipsoidShape.h:46
Isis::Distance
Distance measurement, usually in meters.
Definition: Distance.h:34
Isis::IException::append
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
Definition: IException.cpp:409
Isis::FileName::expanded
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:196
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::toInt
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:93
Isis::PvlObject::hasKeyword
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 ...
Definition: PvlObject.cpp:236
Isis::PvlObject::findObject
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:274
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Spice
Obtain SPICE information for a spacecraft.
Definition: Spice.h:283
Isis::PvlObject::hasObject
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not.
Definition: PvlObject.h:323
Isis::toDouble
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:149
std
Namespace for the standard library.
Isis::ShapeModel
Define shapes and provide utilities for Isis targets.
Definition: ShapeModel.h:62
QMap
This is free and unencumbered software released into the public domain.
Definition: CubeIoHandler.h:22
Isis::PvlObject::findKeyword
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
Definition: PvlObject.cpp:177
Isis::PvlContainer::findKeyword
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Definition: PvlContainer.cpp:62
Isis::FileName::highestVersion
FileName highestVersion() const
Searches the directory specified in the file name for the highest version of the file name.
Definition: FileName.cpp:313
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the USGS Astrogeology Discussion Board
To report a bug, or suggest a feature go to: ISIS Github
File Modified: 07/13/2023 15:17:22