Commit c624fcf4 authored by Jesse Mapel's avatar Jesse Mapel
Browse files

Added new table functionality to SpicePosition. Fixes #5000.

parent d1e68958
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -587,4 +587,34 @@ namespace Isis {
    validateAllKeywords((PvlContainer &)pPvlResults);
  }


  /**
   * Helper function to convert a value stored as a hex string into a double.
   * 
   * @param hexString The hex string to convert.
   * 
   * @return @b double The resultant value.
   */
  double Pvl::hexStringToDouble(const QString &hexString) {
    QByteArray hexBitArray = hexString.toLatin1();
    QByteArray doubleBitArray = QByteArray::fromHex(hexBitArray);
    double result = *reinterpret_cast<double*>( doubleBitArray.data() );
    return result;
  }


  /**
   * Helper function to convert a double into a hex string.
   * 
   * @param double The value to convert.
   * 
   * @return @b QString The resultant hex string.
   */
  QString Pvl::doubleToHexString(const double &value) {
    QByteArray doubleBitArray(reinterpret_cast<const char*>(&value), sizeof(value));
    QByteArray hexBitArray = doubleBitArray.toHex();
    QString result(hexBitArray);
    return result;
  }

} //end namespace isis
+6 −0
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ namespace Isis {
   *  @history 2010-09-27 Sharmila Prasad - Validate a Pvl with the Template Pvl
   *  @history 2013-03-11 Steven Lambright and Mathew Eis - Brought method names and member variable
   *                          names up to the current Isis 3 coding standards. Fixes #1533.
   *  @history 2017-07-07 Jesse Mapel - Added methods to convert between doubles and hex stirngs.
   *                          References #5000.
   */
  class Pvl : public Isis::PvlObject {
    public:
@@ -177,6 +179,10 @@ namespace Isis {
      //! Validate a Pvl with the Template Pvl
      void validatePvl(const Pvl & pPvl, Pvl & pPvlResults);

      // Methods for storing exact doubles in strings
      static double hexStringToDouble(const QString &hexString);
      static QString doubleToHexString(const double &value);

    private:
      void init();
      bool m_internalTemplate;
+7 −0
Original line number Diff line number Diff line
@@ -379,3 +379,10 @@ Object = Filters
  End_Group
End_Object
End

Testing double to hex string methods...

Converting [3.14159] to a hex string...
Hex string: 6e861bf0f9210940
Converting back to a double...
Values match? Yes
+10 −0
Original line number Diff line number Diff line
@@ -141,4 +141,14 @@ int main() {
  Pvl pvlResults;
  pvlTmpl.validatePvl(pvlUser, pvlResults);
  cout << "\n\n**Result PVL**\n" << pvlResults << endl;

  cout << endl;
  cout << "Testing double to hex string methods..." << endl << endl;
  double testDouble = 3.14159;
  cout << "Converting [" << testDouble << "] to a hex string..." << endl;
  QString convertedString = Pvl::doubleToHexString(testDouble);
  cout << "Hex string: " << convertedString << endl;
  cout << "Converting back to a double..." << endl;
  double reconvertedDouble = Pvl::hexStringToDouble(convertedString);
  cout << "Values match? " << toString(testDouble == reconvertedDouble) << endl;
}
+99 −25
Original line number Diff line number Diff line
@@ -4,9 +4,10 @@
#include <cfloat>
#include <iomanip>

#include <QByteArray>
#include <QChar>
#include <QString>
#include <QStringList>
#include <QChar>

#include "BasisFunction.h"
#include "IException.h"
@@ -15,6 +16,7 @@
#include "NaifStatus.h"
#include "NumericalApproximation.h"
#include "PolynomialUnivariate.h"
#include "Pvl.h"
#include "TableField.h"

namespace Isis {
@@ -434,10 +436,47 @@ namespace Isis {
      }
    }
    else {
      int degree = 0;
      int segments = 1;
      std::vector<double> knots;
      double baseTime = 0;
      double timeScale = 1;
      // Get the degree, knots, baseTime, and timeScale from the label if available
      if ( table.Label().hasKeyword("PolynomialDegree")
           && table.Label().hasKeyword("ExactBaseTime")
           && table.Label().hasKeyword("ExactTimeScale")
           && table.Label().hasKeyword("ExactPolynomialKnots") ) {
        degree = table.Label().findKeyword("PolynomialDegree");
        baseTime = Pvl::hexStringToDouble(table.Label().findKeyword("ExactBaseTime")[0]);
        timeScale = Pvl::hexStringToDouble(table.Label().findKeyword("ExactTimeScale")[0]);
        PvlKeyword knotsKey = table.Label().findKeyword("ExactPolynomialKnots");
        segments = knotsKey.size() - 1;
        for (int i = 0; i < knotsKey.size(); i++) {
          knots.push_back(Pvl::hexStringToDouble(table.Label().findKeyword("ExactPolynomialKnots")[i]));
        }
      }
      // If these values are not in the label, then they are in the last record of the table
      else {
        TableRecord &rec = table[table.Records()-1];
        baseTime = (double)rec[0];
        timeScale = (double)rec[1];
        degree = (double)rec[2];
        knots.push_back(-DBL_MAX);
        knots.push_back(DBL_MAX);
      }

      // Initialize polynomial
      SetPolynomialDegree((int) degree);
      SetOverrideBaseTime(baseTime, timeScale);
      m_polynomial.setKnots(knots);

      for (int i = 0; i < segments; i++) {
        // Coefficient table for postion coordinates x, y, and z
        std::vector<double> coeffX, coeffY, coeffZ;
        int startRecord = (degree + 1) * i;
        int endRecord = (degree + 1) * (i + 1);

      for (int r = 0; r < table.Records() - 1; r++) {
        for (int r = startRecord; r < endRecord; r++) {
          TableRecord &rec = table[r];

          if(rec.Fields() != 3) {
@@ -447,14 +486,10 @@ namespace Isis {
          coeffY.push_back((double)rec[1]);
          coeffZ.push_back((double)rec[2]);
        }
      // Take care of function time parameters
      TableRecord &rec = table[table.Records()-1];
      double baseTime = (double)rec[0];
      double timeScale = (double)rec[1];
      double degree = (double)rec[2];
      SetPolynomialDegree((int) degree);
      SetOverrideBaseTime(baseTime, timeScale);
      SetPolynomial(coeffX, coeffY, coeffZ);
        SetPolynomial(coeffX, coeffY, coeffZ, p_source, i);
      }

      // Flag if velocities can be computed
      if (degree > 0)  p_hasVelocity = true;
      if(degree == 0  && p_cacheVelocity.size() > 0) p_hasVelocity = true;
    }
@@ -532,9 +567,10 @@ namespace Isis {
      return table;
    }

    else if(p_source == PolyFunction  &&  p_degree == 0  &&  p_fullCacheSize == 1)
    else if(p_source == PolyFunction  &&  p_degree == 0  &&  p_fullCacheSize == 1) {
      // Just load the position for the single epoch
      return LineCache(tableName);
    }

    // Load the coefficients for the curves fit to the 3 camera angles
    else if (p_source == PolyFunction) {
@@ -550,12 +586,15 @@ namespace Isis {

      Table table(tableName, record);

      for (int segmentIndex = 0; segmentIndex < numPolynomialSegments(); segmentIndex++) {
        std::vector< std::vector<double> > segmentCoeffs = m_polynomial.coefficients(segmentIndex);
        for(int cindex = 0; cindex < p_degree + 1; cindex++) {
        record[0] = p_coefficients[0][cindex];
        record[1] = p_coefficients[1][cindex];
        record[2] = p_coefficients[2][cindex];
          record[0] = segmentCoeffs[0][cindex];
          record[1] = segmentCoeffs[1][cindex];
          record[2] = segmentCoeffs[2][cindex];
          table += record;
        }
      }

      // Load one more table entry with the time adjustments for the fit equation
      // t = (et - baseTime)/ timeScale
@@ -564,6 +603,7 @@ namespace Isis {
      record[2] = (double) p_degree;

      CacheLabel(table);
      PolynomialLabel(table);
      table += record;
      return table;
    }
@@ -578,7 +618,8 @@ namespace Isis {



  /** Add labels to a SpicePosition table.
  /** 
   * Add labels to a SpicePosition table.
   *
   * Return a table containing the labels defining the position table.
   *
@@ -616,6 +657,39 @@ namespace Isis {
  }


  /**
   * Add polynomial keywords to a SpicePosition table. The knots, base time,
   * and time scale are saved as both exact hex and human readable decimal
   * numbers. Only the hex numbers are actually used.
   * 
   * @param[in,out] Table The Table to add keywords to.
   */
  void SpicePosition::PolynomialLabel(Table &table) {
    table.Label() += PvlKeyword("PolynomialDegree");
    table.Label()["PolynomialDegree"].addValue(toString(p_degree));

    table.Label() += PvlKeyword("BaseTime");
    table.Label()["BaseTime"].addValue(toString(p_baseTime));

    table.Label() += PvlKeyword("ExactBaseTime");
    table.Label()["ExactBaseTime"].addValue(Pvl::doubleToHexString(p_baseTime));

    table.Label() += PvlKeyword("TimeScale");
    table.Label()["TimeScale"].addValue(toString(p_timeScale));

    table.Label() += PvlKeyword("ExactTimeScale");
    table.Label()["ExactTimeScale"].addValue(Pvl::doubleToHexString(p_timeScale));

    table.Label() += PvlKeyword("PolynomialKnots");
    table.Label() += PvlKeyword("ExactPolynomialKnots");
    std::vector<double> knots = polynomialKnots();
    for (int i = 0; i < (int)knots.size(); i++) {
      table.Label()["PolynomialKnots"].addValue(toString(knots[i]));
      table.Label()["ExactPolynomialKnots"].addValue(Pvl::doubleToHexString(knots[i]));
    }
  }



  /** Return a table with J2000 to reference positions.
   *
Loading