Isis 3.0 Programmer Reference
Back | Home
Target.cpp
Go to the documentation of this file.
1 
22 #include "Target.h"
23 
24 #include "Angle.h"
25 #include "Distance.h"
26 #include "EllipsoidShape.h"
27 #include "FileName.h"
28 #include "IException.h"
29 #include "NaifStatus.h"
30 #include "Pvl.h"
31 #include "PvlGroup.h"
32 #include "ShapeModelFactory.h"
33 #include "SpecialPixel.h"
34 #include "Spice.h"
35 
36 
37 using namespace std;
38 
39 namespace Isis {
40 
52  // TODO: what is needed to initialize?
53  Target::Target(Spice *spice, Pvl &lab) {
54 
55  // Initialize members
56  init();
57  m_bodyCode = new SpiceInt;
58  m_systemCode = new SpiceInt;
59  m_radii.resize(3, Distance());
60 
61  m_spice = spice;
62 
63  // If we get this far, we know we have a kernels group. Spice requires it.
64  PvlGroup &kernels = lab.findGroup("Kernels", Pvl::Traverse);
65 
66  PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
67  m_name = new QString;
68  *m_name = inst["TargetName"][0];
69  QString trykey = "NaifIkCode";
70 
71  m_systemName = new QString;
72 
73  if (kernels.hasKeyword("NaifFrameCode")) {
74  trykey = "NaifFrameCode";
75  }
76 
77  if (name().toUpper() == "SKY") {
78  m_radii[0] = m_radii[1] = m_radii[2] = Distance(1000.0, Distance::Meters);
79  m_sky = true;
80  int ikCode = toInt(kernels[trykey][0]);
81  *m_bodyCode = ikCode / 1000;
82  // Check for override in kernel group
83  if (kernels.hasKeyword("NaifSpkCode")) {
84  *m_bodyCode = (int) kernels["NaifSpkCode"];
85  }
86 
87  *m_systemCode = -1;
88  (*m_systemName).append("THE COSMOS");
89 
90  }
91  else {
92  *m_bodyCode = lookupNaifBodyCode(lab);
93  m_sky = false;
94 
95  *m_systemCode = (*m_bodyCode/100)*100 + 99;
96 
97  SpiceChar naifBuf[40];
98  SpiceBoolean found;
99  bodc2n_c((SpiceInt) *m_systemCode, sizeof(naifBuf), naifBuf, &found);
100  string s(naifBuf);
101  (*m_systemName).append(s.c_str());
102 
103  // QString radiiKey = "BODY" + QString((BigInt) naifBodyCode()) + "_RADII";
104  // m_radii[0] = Distance(getDouble(radiiKey, 0), Distance::Kilometers);
105  // m_radii[1] = Distance(getDouble(radiiKey, 1), Distance::Kilometers);
106  // m_radii[2] = Distance(getDouble(radiiKey, 2), Distance::Kilometers);
107  }
108  // Override it if it exists in the labels
109  if (kernels.hasKeyword("NaifBodyCode")) {
110  *m_bodyCode = (int) kernels["NaifBodyCode"];
111  }
112  m_shape = ShapeModelFactory::create(this, lab);
113  }
114 
115 
124  Target::Target() {
125  m_bodyCode = NULL;
126  m_systemCode = NULL;
127  m_name = NULL;
128  m_systemName = NULL;
129  m_spice = NULL;
130  init();
131  }
132 
133 
142  void Target::init() {
143  m_shape = NULL;
144  m_originalShape = NULL;
145  m_sky = false;
146  }
147 
148 
152  Target::~Target() {
153  NaifStatus::CheckErrors();
154 
155  delete m_bodyCode;
156  m_bodyCode = NULL;
157 
158  delete m_systemCode;
159  m_systemCode = NULL;
160 
161  delete m_name;
162  m_name = NULL;
163 
164  delete m_systemName;
165  m_systemName = NULL;
166 
167  if (m_radii.size() != 0) {
168  m_radii.clear();
169  }
170 
171  delete m_originalShape;
172  m_originalShape = NULL;
173 
174  delete m_shape;
175  m_shape = NULL;
176  }
177 
178 
180  bool Target::isSky() const {
181  return m_sky;
182  }
183 
184 
191  SpiceInt Target::lookupNaifBodyCode(Pvl &lab) const {
192  SpiceInt code;
193  try {
194  code = lookupNaifBodyCode(*m_name);
195  return code;
196  }
197  catch (IException &e) {
198  try {
199  if (m_spice) {
200  code = m_spice->getInteger("BODY_FRAME_CODE", 0);
201  return code;
202  }
203  else if (lab.hasObject("NaifKeywords")
204  && lab.findObject("NaifKeywords").hasKeyword("BODY_FRAME_CODE") ) {
205  code = int(lab.findObject("NaifKeywords").findKeyword("BODY_FRAME_CODE"));
206  return code;
207  }
208  else {
209  throw IException(e,
210  IException::Unknown,
211  "BODY_FRAME_CODE not found for this Target.",
212  _FILEINFO_);
213  }
214  }
215  catch (IException &e2) {
216  e.append(e2);
217  throw IException(e,
218  IException::Unknown,
219  "Unable to look up NAIF body code for this Target.",
220  _FILEINFO_);
221  }
222  }
223  }
224 
225 
232  SpiceInt Target::lookupNaifBodyCode(QString name) {
233 
234  NaifStatus::CheckErrors();
235  SpiceInt code;
236  SpiceBoolean found;
237  bodn2c_c(name.toLatin1().data(), &code, &found);
238  if (!found) {
239  QString msg = "Could not convert Target [" + name +
240  "] to NAIF body code";
241  throw IException(IException::Io, msg, _FILEINFO_);
242  }
243  NaifStatus::CheckErrors();
244  return code;
245 
246  }
247 
248 
263  PvlGroup Target::radiiGroup(Pvl &cubeLab, const PvlGroup &mapGroup) {
264  PvlGroup mapping = mapGroup;
265  // Check to see if the mapGroup already has the target radii.
266  // If BOTH radii are already in the mapGroup then just return the given
267  // mapping group as is.
268  if (mapping.hasKeyword("EquatorialRadius")
269  && mapping.hasKeyword("PolarRadius")) {
270  return mapping;
271  }
272 
273  // If radii values are not in the given mapping group, we will get the target from the mapping
274  // group or cube label and attempt use NAIF routines to find the radii.
275  QString target = "";
276  try {
277  if (mapping.hasKeyword("TargetName")) {
278  target = mapping["TargetName"][0];
279  }
280 
281  // if target name not found in mapping group or value was empty string, try instrument group
282  if (target.isEmpty()) {
283  bool hasInstrumentGroup = cubeLab.findObject("IsisCube").hasGroup("Instrument");
284  if (hasInstrumentGroup) {
285  PvlGroup inst = cubeLab.findGroup("Instrument", Pvl::Traverse);
286  if (inst.hasKeyword("TargetName")) {
287  target = inst["TargetName"][0];
288  mapping.addKeyword( PvlKeyword("TargetName", target), PvlContainer::Replace );
289  }
290  }
291  }
292 
293  // target name still not found, throw error
294  if (target.isEmpty()) {
295  throw IException(IException::Unknown,
296  "Unable to find a TargetName keyword in the given PVL.",
297  _FILEINFO_);
298  }
299 
300  // first, attempt to use cached values or run NAIF routine on the target name to get the
301  // radii values. if this fails, the exception will be caught and we will try to find
302  // radii in the NaifKeywords object of the labels
303  PvlGroup radii = Target::radiiGroup(target);
304 
305  // Successfully found radii using target name.
306  // Copy the EquatorialRadius and PolorRadius and we are done.
307  mapping.addKeyword( radii.findKeyword("EquatorialRadius"), PvlContainer::Replace );
308  mapping.addKeyword( radii.findKeyword("PolarRadius"), PvlContainer::Replace );
309  return mapping;
310  }
311  catch (IException &e) {
312  // If all previous attempts fail, look for the radii using the body frame
313  // code in the NaifKeywords object.
314  // Note: We will only look in the given label for the values after NAIF
315  // routines have failed to preserve backwards compatibility (since this
316  // label check is new).
317  if (cubeLab.hasObject("NaifKeywords")) {
318 
319  PvlObject naifKeywords = cubeLab.findObject("NaifKeywords");
320  if (naifKeywords.hasKeyword("BODY_FRAME_CODE")) {
321 
322  PvlKeyword bodyFrame = naifKeywords.findKeyword("BODY_FRAME_CODE");
323  QString radiiKeyword = "BODY"
324  + bodyFrame[0]
325  + "_RADII";
326 
327  if (naifKeywords.hasKeyword(radiiKeyword)) {
328  PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword);
329  mapping.addKeyword( PvlKeyword("EquatorialRadius",
330  toString(toDouble(radii[0]) * 1000.0),
331  "meters"),
332  PvlContainer::Replace);
333  mapping.addKeyword( PvlKeyword("PolarRadius",
334  toString(toDouble(radii[2]) * 1000.0),
335  "meters"),
336  PvlContainer::Replace);
337  return mapping;
338  }
339  else {
340  PvlGroup radiiGroup = Target::radiiGroup(toInt(bodyFrame[0]));
341  // Now APPEND the EquatorialRadius and PolorRadius
342  mapping.addKeyword( radiiGroup.findKeyword("EquatorialRadius"), PvlContainer::Replace);
343  mapping.addKeyword( radiiGroup.findKeyword("PolarRadius"), PvlContainer::Replace);
344  return mapping;
345 
346 
347  }
348  }
349  }
350 
351  // If we get this far, we know the cube has no NaifKeywords object and previous attempts to
352  // find radii in the mapping group or using spice IDs have failed
353  QString msg = "Unable to find Equatorial and Polar radii for target [" + target + "].";
354  throw IException(e, IException::Unknown, msg, _FILEINFO_);
355  }
356  }
357 
358 
372  PvlGroup Target::radiiGroup(QString target) {
373 
374  if (target.isEmpty()) {
375  throw IException(IException::Unknown,
376  "Unable to find TargetRadii. The given TargetName is empty.",
377  _FILEINFO_);
378  }
379 
380  static QMap<QString, PvlGroup> cachedResults;
381 
382  PvlGroup mapping("Mapping");
383  if (cachedResults.contains(target)) {
384  mapping = cachedResults[target];
385  }
386  else {
387 
388  SpiceInt bodyFrame = 0;
389  try {
390  bodyFrame = lookupNaifBodyCode(target);
391  }
392  catch (IException &e) {
393  QString msg = "Unable to find target radii for given target ["
394  + target + "].";
395  throw IException(IException::Io, msg, _FILEINFO_);
396  }
397 
398  PvlGroup radiiGroup = Target::radiiGroup(int(bodyFrame));
399  mapping += PvlKeyword("TargetName", target);
400  mapping += radiiGroup.findKeyword("EquatorialRadius");
401  mapping += radiiGroup.findKeyword("PolarRadius");
402  cachedResults[target] = mapping;
403  }
404 
405  return mapping;
406  }
407 
408 
420  PvlGroup Target::radiiGroup(int bodyFrameCode) {
421 
422  // Load the most recent target attitude and shape kernel for NAIF
423  static bool pckLoaded = false;
424 
425  FileName kern("$base/kernels/pck/pck?????.tpc");
426  kern = kern.highestVersion();
427  QString kernName = kern.expanded();
428 
429  if(!pckLoaded) {
430  furnsh_c(kernName.toLatin1().data());
431  pckLoaded = true;
432  }
433 
434  // Get the radii from NAIF
435  SpiceInt n;
436  SpiceDouble radii[3];
437  bodvar_c(bodyFrameCode, "RADII", &n, radii);
438 
439  try {
440  NaifStatus::CheckErrors();
441  }
442  catch (IException &e) {
443  QString msg = "Unable to find radii for target code [" + toString(bodyFrameCode)
444  + "]. Target code was not found in furnished kernels.";
445 
446  throw IException(e, IException::Unknown, msg, _FILEINFO_);
447  }
448 
449  PvlGroup radiiGroup;
450  radiiGroup += PvlKeyword("EquatorialRadius", toString(radii[0] * 1000.0), "meters");
451  radiiGroup += PvlKeyword("PolarRadius", toString(radii[2] * 1000.0), "meters");
452 
453  return radiiGroup;
454 
455  }
456 
457 
464  SpiceInt Target::naifBodyCode() const {
465  return *m_bodyCode;
466  }
467 
468 
477  SpiceInt Target::naifPlanetSystemCode() const {
478  return *m_systemCode;
479  }
480 
481 
483  QString Target::name() const {
484  return *m_name;
485  }
486 
487 
489  QString Target::systemName() const {
490  return *m_systemName;
491  }
492 
493 
499  std::vector<Distance> Target::radii() const {
500  return m_radii;
501  }
502 
503 
504  int Target::frameType() {
505  return spice()->bodyRotation()->getFrameType();
506  }
507 
508 
509  std::vector<Angle> Target::poleRaCoefs() {
510  return spice()->bodyRotation()->poleRaCoefs();
511  }
512 
513 
514  std::vector<Angle> Target::poleDecCoefs() {
515  return spice()->bodyRotation()->poleDecCoefs();
516  }
517 
518 
519  std::vector<Angle> Target::pmCoefs() {
520  return spice()->bodyRotation()->pmCoefs();
521  }
522 
523 
524  std::vector<double> Target::poleRaNutPrecCoefs() {
525  return spice()->bodyRotation()->poleRaNutPrecCoefs();
526  }
527 
528 
529  std::vector<double> Target::poleDecNutPrecCoefs() {
530  return spice()->bodyRotation()->poleDecNutPrecCoefs();
531  }
532 
533 
534  std::vector<double> Target::pmNutPrecCoefs() {
535  return spice()->bodyRotation()->pmNutPrecCoefs();
536  }
537 
538 
539  std::vector<Angle> Target::sysNutPrecConstants() {
540  return spice()->bodyRotation()->sysNutPrecConstants();
541  }
542 
543 
544  std::vector<Angle> Target::sysNutPrecCoefs() {
545  return spice()->bodyRotation()->sysNutPrecCoefs();
546  }
547 
548 
552  void Target::restoreShape() {
553  if (m_shape->name() != "Ellipsoid") {
554  // Nothing to do
555  return;
556  }
557  // If we don't have a saved original shape, just stick to the current shape
558  else if (m_originalShape == NULL) {
559  // Nothing to do
560  return;
561  }
562  m_shape = m_originalShape;
563  m_originalShape = NULL;
564  }
565 
566 
570  void Target::setShapeEllipsoid() {
571  // Save the current shape to restore later
572  m_originalShape = m_shape;
573  m_shape = new EllipsoidShape(this);
574  }
575 
576 
582  void Target::setRadii(std::vector<Distance> radii) {
583  m_radii[0] = radii[0];
584  m_radii[1] = radii[1];
585  m_radii[2] = radii[2];
586  }
587 
588 
592  ShapeModel *Target::shape() const {
593  return m_shape;
594  }
595 
596 
600  Spice *Target::spice() const {
601  return m_spice;
602  }
603 }
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
File name manipulation and expansion.
Definition: FileName.h:111
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception&#39;s causational exc...
Definition: IException.cpp:425
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
Define shapes and provide utilities for Isis3 targets.
Distance measurement, usually in meters.
Definition: Distance.h:47
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:207
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:148
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
A single keyword-value pair.
Definition: PvlKeyword.h:98
Container for cube-like labels.
Definition: Pvl.h:135
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Define shapes and provide utilities for Isis3 targets.
Definition: ShapeModel.h:68
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:335
Isis exception class.
Definition: IException.h:99
Obtain SPICE information for a spacecraft.
Definition: Spice.h:282
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.

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 ISIS Support Center
File Modified: 07/12/2023 23:30:31