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

Added PiecewisePolynomial class and updated SpicePosition to use it. References #4650, #5000.

parent 506707fd
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -571,8 +571,8 @@ namespace Isis {
    p_degreesOfFreedom = p_sparseRows + p_constrainedParameters - p_sparseCols;

    if( p_degreesOfFreedom <= 0.0 ) {
      printf("Observations: %d\nConstrained: %d\nParameters: %d\nDOF: %d\n",
             p_sparseRows,p_constrainedParameters,p_sparseCols,p_degreesOfFreedom);
//       printf("Observations: %d\nConstrained: %d\nParameters: %d\nDOF: %d\n",
//              p_sparseRows,p_constrainedParameters,p_sparseCols,p_degreesOfFreedom);
      p_sigma0 = 1.0;
    }
    else
@@ -582,7 +582,7 @@ namespace Isis {
    p_sigma0 = sqrt(p_sigma0);

    // kle testing - output residuals and some stats
    printf("Sigma0 = %20.10lf\nNumber of Observations = %d\nNumber of Parameters = %d\nNumber of Constrained Parameters = %d\nDOF = %d\n",p_sigma0,p_sparseRows,p_sparseCols,p_constrainedParameters,p_degreesOfFreedom);
//     printf("Sigma0 = %20.10lf\nNumber of Observations = %d\nNumber of Parameters = %d\nNumber of Constrained Parameters = %d\nDOF = %d\n",p_sigma0,p_sparseRows,p_sparseCols,p_constrainedParameters,p_degreesOfFreedom);
//    printf("printing residuals\n");
//    for( int k = 0; k < p_sparseRows; k++ )
//    {
+7 −0
Original line number Diff line number Diff line
ifeq ($(ISISROOT), $(BLANK))
.SILENT:
error:
	echo "Please set ISISROOT";
else
	include $(ISISROOT)/make/isismake.objs
endif
 No newline at end of file
+854 −0

File added.

Preview size limit exceeded, changes collapsed.

+105 −0
Original line number Diff line number Diff line
#ifndef PiecewisePolynomial_h
#define PiecewisePolynomial_h
/**
 * @file
 * $Revision: 1.17 $
 * $Date: 2010/03/27 07:01:33 $
 *
 *   Unless noted otherwise, the portions of Isis written by the USGS are public
 *   domain. See individual third-party library and package descriptions for
 *   intellectual property information,user agreements, and related information.
 *
 *   Although Isis has been used by the USGS, no warranty, expressed or implied,
 *   is made by the USGS as to the accuracy and functioning of such software
 *   and related material nor shall the fact of distribution constitute any such
 *   warranty, and no responsibility is assumed by the USGS in connection
 *   therewith.
 *
 *   For additional information, launch
 *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see
 *   the Privacy &amp; Disclaimers page on the Isis website,
 *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
 *   http://www.usgs.gov/privacy.html.
 */

#include <vector>

#include "LinearAlgebra.h"
#include "PolynomialUnivariate.h"

namespace Isis {

  /**
   * The PiecewisePolynomial class encapsulates a piecewise-polynomial
   * function. It can be set based on a known function or it can be fit to a
   * data set. Specifically, this class is designed to represent a
   * parameterized space curve such as an object's position over time.
   *
   * @author 2017-03-02 Jesse Mapel
   *
   * @internal
   *   @history 2017-03-02 Jesse Mapel - Original version. References #4650.
   *   @history 2017-03-11 Jesse Mapel - Reordered input data vector, improved
   *                           documentation and error throws and unit test.
   *                           References #4650.
   */
  class PiecewisePolynomial {

    public:
      PiecewisePolynomial();
      PiecewisePolynomial(double minValue, double maxValue,
                          int degree, int dimensions);
      PiecewisePolynomial(const PiecewisePolynomial &other);

      ~PiecewisePolynomial();

      PiecewisePolynomial &operator=(const PiecewisePolynomial &other);

      std::vector<double> evaluate(double value);
      std::vector<double> derivativeVariable(double value);
      void fitPolynomials(const std::vector<double> &values,
                          const std::vector< std::vector<double> > &data,
                          int segments);

      int degree() const;
      std::vector< std::vector<double> > coefficients(int segment) const;
      int dimensions() const;
      const std::vector<double> knots() const;
      int segments() const;

      void setDegree(int degree);
      void setCoefficients(int segment,
                           const std::vector< std::vector<double> > &coefficients);
      void setDimensions(int dimensions);
      void setKnots(std::vector<double> &knots);

    private:
      void validateData(const std::vector<double> &values,
                        const std::vector< std::vector<double> > &data,
                        int segments);
      void computeKnots(const std::vector<double> &values,
                        const std::vector< std::vector<double> > &data,
                        int segments);
      double computeCurvature(const std::vector<double> &localValues,
                              const std::vector<double> &firstPoint,
                              const std::vector<double> &secondPoint,
                              const std::vector<double> &thirdPoint);
      double computeArcLength(const std::vector<double> &firstPoint,
                              const std::vector<double> &secondPoint);
      void computePolynomials(const std::vector<double> &values,
                              const std::vector< std::vector<double> > &data);
      int segmentIndex(double value);
      int derivativeCoefficient(int coeffOrder, int derivativeOrder);

      int m_degree; //< The degree of the polynomials.
      int m_dimensions; //< The number of dimensions of the space curve.
      std::vector<double> m_knots; //!< The knots or segment boundaries.
      std::vector< std::vector<PolynomialUnivariate> > m_polynomials;
      /**!< Vector containing vectors of polynomials for each segment.
       *    Each inner vector represents a segment. Each inner vector
       *    has m_dimensions polynomial functions.**/
      
  };
};

#endif
+201 −0
Original line number Diff line number Diff line
Unit test for PiecewisePolynomial

Create 1D PiecewisePolynomial:

Number of segments: 1
Space curve dimensions: 1
Polynomial degree: 2
Polynomial knots:
  -5.0
  5.0

Segment 1 polynomial:
Dimension 1 coefficients:
  0.0
  0.0
  0.0

Fit to 1D data:

Number of segments: 2
Space curve dimensions: 1
Polynomial degree: 2
Polynomial knots:
  -4.0
  -0.45
  4.0

Segment 1 polynomial:
Dimension 1 coefficients:
  1.71009
  3.96381
  1.41881

Segment 2 polynomial:
Dimension 1 coefficients:
  1.30584
  2.16714
  -0.577498

Calculating residuals for 17 points.
  -4.0  0.555796
  -3.5  0.0328341
  -3.0  0.412059
  -2.5  0.58188
  -2.0  0.542296
  -1.5  0.293306
  -1.0  0.165088
  -0.5  0.832887
  0.0  1.30584
  0.5  0.495033
  1.0  0.104523
  1.5  0.492827
  2.0  0.669881
  2.5  0.635683
  3.0  0.390234
  3.5  0.0664653
  4.0  0.734416
RMS Error: 0.699203

Create 3D PiecewisePolynomial:

Number of segments: 1
Space curve dimensions: 3
Polynomial degree: 2
Polynomial knots:
  -6.0
  4.0

Segment 1 polynomial:
Dimension 1 coefficients:
  0.0
  0.0
  0.0
Dimension 2 coefficients:
  0.0
  0.0
  0.0
Dimension 3 coefficients:
  0.0
  0.0
  0.0

Fit to 3D data:

Number of segments: 3
Space curve dimensions: 3
Polynomial degree: 2
Polynomial knots:
  -5.0
  -2.20163
  -0.143386
  3.0

Segment 1 polynomial:
Dimension 1 coefficients:
  0.326338
  -1.81105
  -0.474491
Dimension 2 coefficients:
  0.217688
  0.459387
  0.0170194
Dimension 3 coefficients:
  2.78236
  -0.126021
  -0.0170146

Segment 2 polynomial:
Dimension 1 coefficients:
  -0.143298
  -2.23768
  -0.571379
Dimension 2 coefficients:
  -0.0955277
  0.174856
  -0.0475988
Dimension 3 coefficients:
  3.09553
  0.158469
  0.0475944

Segment 3 polynomial:
Dimension 1 coefficients:
  -0.112189
  -1.80376
  0.941727
Dimension 2 coefficients:
  -0.074788
  0.46414
  0.961159
Dimension 3 coefficients:
  3.07479
  -0.130813
  -0.961156

Calculating residuals for 17 points.
  -5.0  0.026584
  -4.5  0.0101199
  -4.0  0.029289
  -3.5  0.0309233
  -3.0  0.0150228
  -2.5  0.0184126
  -2.0  0.0639684
  -1.5  0.0723248
  -1.0  0.0316254
  -0.5  0.0581297
  0.0  0.154185
  0.5  0.0393608
  1.0  0.0354222
  1.5  0.0701638
  2.0  0.0648641
  2.5  0.0195231
  3.0  0.0658593
RMS Error: 0.0580648

Test fitting to a single point
Number of segments: 1
Space curve dimensions: 3
Polynomial degree: 0
Polynomial knots:
  -1.797693e+308
  1.797693e+308

Segment 1 polynomial:
Dimension 1 coefficients:
  -2.5
Dimension 2 coefficients:
  -1.66667
Dimension 3 coefficients:
  3.0

Calculating residuals for 1 points.
  -5.0  0.0
RMS Error: 0.0

Test error throws

Attempt to evaluate at value outside of range:
**PROGRAMMER ERROR** Failed evaluating piecewise polynomial at value [20.0].
**PROGRAMMER ERROR** Value [20.0] is not within valid range [-4.0, 4.0].

Polynomial fit errors:
**PROGRAMMER ERROR** The number of input values [3] and data points [1] do not match.
**PROGRAMMER ERROR** The number of data points [2] is insufficient to fit polynomials. at least [5] data points are required.
**PROGRAMMER ERROR** Input values are not sorted in ascending order.
**PROGRAMMER ERROR** Data point number [7] has the incorrect number of dimensions [2]. Expected [1] dimensions.
**PROGRAMMER ERROR** Cannot compute curvature. The triangle between points is degenerate.

Attempt to set to negative degree:
**PROGRAMMER ERROR** Input degree [-1] must be greater than or equal to 0.

Attempt to set non-positive dimensions:
**PROGRAMMER ERROR** Input dimensions [0] must be greater than 0.

Setting coefficients errors:
**PROGRAMMER ERROR** Segment index [4] is invalid. Valid segment indices are between [0] and [1] inclusive.
**PROGRAMMER ERROR** Invalid number of dimensions [1]. Expected [3] dimensions.
**PROGRAMMER ERROR** Invalid number of coefficients [2] for dimension number [3]. Expected [3] coefficients.

Attempt to set less than 2 knots:
**PROGRAMMER ERROR** Invalid number of knots [1]. At least 2 knots must be specified.
Loading