Isis 3 Programmer Reference
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  // Get body code from Isis Naif object if it exists or Naif data pool
200  if (m_spice) {
201  code = m_spice->getInteger("BODY_CODE", 0);
202  return code;
203  }
204  // getInteger automatically calls Spice::readValue which looks in the NaifKeywords
205  else if (lab.hasObject("NaifKeywords")
206  && lab.findObject("NaifKeywords").hasKeyword("BODY_CODE") ) {
207  code = int(lab.findObject("NaifKeywords").findKeyword("BODY_CODE"));
208  return code;
209  }
210  else {
211  throw IException(e,
212  IException::Unknown,
213  "BODY_CODE not found for this Target.",
214  _FILEINFO_);
215  }
216  }
217  catch (IException &e2) {
218  e.append(e2);
219  throw IException(e,
220  IException::Unknown,
221  "Unable to look up NAIF body code for this Target.",
222  _FILEINFO_);
223  }
224  }
225  }
226 
227 
234  SpiceInt Target::lookupNaifBodyCode(QString name) {
235 
236  NaifStatus::CheckErrors();
237  SpiceInt code;
238  SpiceBoolean found;
239  bodn2c_c(name.toLatin1().data(), &code, &found);
240  if (!found) {
241  QString msg = "Could not convert Target [" + name +
242  "] to NAIF body code";
243  throw IException(IException::Io, msg, _FILEINFO_);
244  }
245  NaifStatus::CheckErrors();
246  return code;
247 
248  }
249 
250 
265  PvlGroup Target::radiiGroup(Pvl &cubeLab, const PvlGroup &mapGroup) {
266  PvlGroup mapping = mapGroup;
267 
268  // Check to see if the mapGroup already has the target radii.
269  // If BOTH radii are already in the mapGroup then just return the given
270  // mapping group as is.
271  if (mapping.hasKeyword("EquatorialRadius")
272  && mapping.hasKeyword("PolarRadius")) {
273  return mapping;
274  }
275 
276  // If radii values are not in the given mapping group, we will get the target from the mapping
277  // group or cube label and attempt to use NAIF routines to find the radii.
278  QString target = "";
279  try {
280  if (mapping.hasKeyword("TargetName")) {
281  target = mapping["TargetName"][0];
282  }
283 
284  // if target name not found in mapping group or value was empty string, try instrument group
285  if (target.isEmpty()) {
286  bool hasInstrumentGroup = cubeLab.findObject("IsisCube").hasGroup("Instrument");
287  if (hasInstrumentGroup) {
288  PvlGroup inst = cubeLab.findGroup("Instrument", Pvl::Traverse);
289  if (inst.hasKeyword("TargetName")) {
290  target = inst["TargetName"][0];
291  mapping.addKeyword( PvlKeyword("TargetName", target), PvlContainer::Replace );
292  }
293  }
294  }
295 
296  // target name still not found, throw error
297  if (target.isEmpty()) {
298  throw IException(IException::Unknown,
299  "Unable to find a TargetName keyword in the given PVL.",
300  _FILEINFO_);
301  }
302 
303  // first, attempt to use cached values or run NAIF routine on the target name to get the
304  // radii values. if this fails, the exception will be caught and we will try to find
305  // radii in the NaifKeywords object of the labels
306  PvlGroup radii = Target::radiiGroup(target);
307 
308  // Successfully found radii using target name.
309  // Copy the EquatorialRadius and PolorRadius and we are done.
310  mapping.addKeyword( radii.findKeyword("EquatorialRadius"), PvlContainer::Replace );
311  mapping.addKeyword( radii.findKeyword("PolarRadius"), PvlContainer::Replace );
312  return mapping;
313  }
314  catch (IException &e) {
315  // If all previous attempts fail, look for the radii using the body frame
316  // code in the NaifKeywords object.
317  // Note: We will only look in the given label for the values after SPICELIB
318  // routines have failed, to preserve backwards compatibility (since this
319  // label check is new).
320  if (cubeLab.hasObject("NaifKeywords")) {
321 
322  PvlObject naifKeywords = cubeLab.findObject("NaifKeywords");
323 
324  // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object
325 
326  try {
327 
328  SpiceInt bodyCode = 0;
329  try {
330  // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object
331  bodyCode = lookupNaifBodyCode(target);
332  }
333  catch (IException &e2) {
334  throw IException(e, IException::Unknown, e2.what(), _FILEINFO_);
335  }
336  QString radiiKeyword = "BODY" + toString(int(bodyCode)) + "_RADII";
337 
338  if (naifKeywords.hasKeyword(radiiKeyword)) {
339  PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword);
340  mapping.addKeyword( PvlKeyword("EquatorialRadius",
341  toString(toDouble(radii[0]) * 1000.0), "meters"),
342  PvlContainer::Replace);
343  mapping.addKeyword( PvlKeyword("PolarRadius",
344  toString(toDouble(radii[2]) * 1000.0), "meters"),
345  PvlContainer::Replace);
346  return mapping;
347  }
348  }
349  catch (IException &e) {
350  // Try using the value of the BODY_FRAME_CODE keyword in the NaifKeywords PVL object
351  if (naifKeywords.hasKeyword("BODY_FRAME_CODE")) {
352 
353  PvlKeyword bodyFrame = naifKeywords.findKeyword("BODY_FRAME_CODE");
354  QString radiiKeyword = "BODY" + bodyFrame[0] + "_RADII";
355 
356  if (naifKeywords.hasKeyword(radiiKeyword)) {
357  PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword);
358  mapping.addKeyword( PvlKeyword("EquatorialRadius",
359  toString(toDouble(radii[0]) * 1000.0),
360  "meters"),
361  PvlContainer::Replace);
362  mapping.addKeyword( PvlKeyword("PolarRadius",
363  toString(toDouble(radii[2]) * 1000.0),
364  "meters"),
365  PvlContainer::Replace);
366  return mapping;
367  }
368  }
369  }
370  }
371 
372  // If we get this far, we know the cube has no NaifKeywords object and previous attempts to
373  // find radii in the mapping group or using spice IDs have failed
374  QString msg = "Unable to find Equatorial and Polar radii for target [" + target + "].";
375  throw IException(e, IException::Unknown, msg, _FILEINFO_);
376  }
377  }
378 
379 
393  PvlGroup Target::radiiGroup(QString target) {
394 
395  if (target.isEmpty()) {
396  throw IException(IException::Unknown,
397  "Unable to find TargetRadii. The given TargetName is empty.",
398  _FILEINFO_);
399  }
400 
401  static QMap<QString, PvlGroup> cachedResults;
402 
403  PvlGroup mapping("Mapping");
404  if (cachedResults.contains(target)) {
405  mapping = cachedResults[target];
406  }
407  else {
408 
409  SpiceInt bodyCode = 0;
410  try {
411  bodyCode = lookupNaifBodyCode(target);
412  }
413  catch (IException &e) {
414  QString msg = "Unable to find target radii for given target ["
415  + target + "].";
416  throw IException(IException::Io, msg, _FILEINFO_);
417  }
418 
419  PvlGroup radiiGroup = Target::radiiGroup(int(bodyCode));
420  mapping += PvlKeyword("TargetName", target);
421  mapping += radiiGroup.findKeyword("EquatorialRadius");
422  mapping += radiiGroup.findKeyword("PolarRadius");
423  cachedResults[target] = mapping;
424  }
425 
426  return mapping;
427  }
428 
429 
441  PvlGroup Target::radiiGroup(int bodyCode) {
442 
443  // Load the most recent target attitude and shape kernel for NAIF
444  static bool pckLoaded = false;
445 
446  NaifStatus::CheckErrors();
447 
448  FileName kern("$base/kernels/pck/pck?????.tpc");
449  kern = kern.highestVersion();
450  QString kernName = kern.expanded();
451 
452  if(!pckLoaded) {
453  furnsh_c(kernName.toLatin1().data());
454  pckLoaded = true;
455  }
456 
457  // Get the radii from NAIF
458  SpiceInt n;
459  SpiceDouble radii[3];
460  bodvar_c(bodyCode, "RADII", &n, radii);
461 
462  try {
463  NaifStatus::CheckErrors();
464  }
465  catch (IException &e) {
466  QString msg = "Unable to find radii for target code [" + toString(bodyCode)
467  + "]. Target code was not found in furnished kernels.";
468 
469  throw IException(e, IException::Unknown, msg, _FILEINFO_);
470  }
471 
472  PvlGroup radiiGroup;
473  radiiGroup += PvlKeyword("EquatorialRadius", toString(radii[0] * 1000.0), "meters");
474  radiiGroup += PvlKeyword("PolarRadius", toString(radii[2] * 1000.0), "meters");
475 
476  return radiiGroup;
477 
478  }
479 
480 
487  SpiceInt Target::naifBodyCode() const {
488  return *m_bodyCode;
489  }
490 
491 
500  SpiceInt Target::naifPlanetSystemCode() const {
501  return *m_systemCode;
502  }
503 
504 
506  QString Target::name() const {
507  return *m_name;
508  }
509 
510 
512  QString Target::systemName() const {
513  return *m_systemName;
514  }
515 
516 
522  std::vector<Distance> Target::radii() const {
523  return m_radii;
524  }
525 
526 
527  int Target::frameType() {
528  return spice()->bodyRotation()->getFrameType();
529  }
530 
531 
532  std::vector<Angle> Target::poleRaCoefs() {
533  return spice()->bodyRotation()->poleRaCoefs();
534  }
535 
536 
537  std::vector<Angle> Target::poleDecCoefs() {
538  return spice()->bodyRotation()->poleDecCoefs();
539  }
540 
541 
542  std::vector<Angle> Target::pmCoefs() {
543  return spice()->bodyRotation()->pmCoefs();
544  }
545 
546 
547  std::vector<double> Target::poleRaNutPrecCoefs() {
548  return spice()->bodyRotation()->poleRaNutPrecCoefs();
549  }
550 
551 
552  std::vector<double> Target::poleDecNutPrecCoefs() {
553  return spice()->bodyRotation()->poleDecNutPrecCoefs();
554  }
555 
556 
557  std::vector<double> Target::pmNutPrecCoefs() {
558  return spice()->bodyRotation()->pmNutPrecCoefs();
559  }
560 
561 
562  std::vector<Angle> Target::sysNutPrecConstants() {
563  return spice()->bodyRotation()->sysNutPrecConstants();
564  }
565 
566 
567  std::vector<Angle> Target::sysNutPrecCoefs() {
568  return spice()->bodyRotation()->sysNutPrecCoefs();
569  }
570 
571 
575  void Target::restoreShape() {
576  if (m_shape->name() != "Ellipsoid") {
577  // Nothing to do
578  return;
579  }
580  // If we don't have a saved original shape, just stick to the current shape
581  else if (m_originalShape == NULL) {
582  // Nothing to do
583  return;
584  }
585  m_shape = m_originalShape;
586  m_originalShape = NULL;
587  }
588 
589 
593  void Target::setShapeEllipsoid() {
594  // Save the current shape to restore later
595  m_originalShape = m_shape;
596  m_shape = new EllipsoidShape(this);
597  }
598 
599 
605  void Target::setRadii(std::vector<Distance> radii) {
606  m_radii[0] = radii[0];
607  m_radii[1] = radii[1];
608  m_radii[2] = radii[2];
609  }
610 
611 
615  ShapeModel *Target::shape() const {
616  return m_shape;
617  }
618 
619 
623  Spice *Target::spice() const {
624  return m_spice;
625  }
626 }
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
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:116
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
Namespace for the standard library.
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
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
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:40
A single keyword-value pair.
Definition: PvlKeyword.h:98
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
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:78
FileName highestVersion() const
Searches the directory specified in the file name for the highest version of the file name...
Definition: FileName.cpp:329
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Obtain SPICE information for a spacecraft.
Definition: Spice.h:294
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74