Commit 29b9709f authored by Philipp Schäfer's avatar Philipp Schäfer
Browse files

Splines

- added interface for piecewise polynomials and splines
- added (a so far empty) test
parent b65c0560
......@@ -70,6 +70,7 @@ include_directories( "include" )
set( ITABaseHeader
"include/ITABase/ITAProgress.h"
"include/ITABase/Spline.h"
"include/ITAAudioSample.h"
"include/ITABaseDefinitions.h"
......@@ -141,6 +142,7 @@ set( ITABaseSources
"src/ITAWinPCClock.cpp"
"src/ITABase/ITAProgress.cpp"
"src/ITABase/Spline.cpp"
)
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2020
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef IW_ITA_BASE_SPLINE
#define IW_ITA_BASE_SPLINE
#include <ITABaseDefinitions.h>
#include <vector>
namespace ITABase
{
//! This class represents a piecewise polynomial of order M
/**
* A piecewise polynomial persists of a series of N break points which from N-1 intervals. For each interval, there is a polynom of order M represented by M+1 coefficients.
* See "Piecewise Polynomials and Splines" by University of Lundt for more information:
* https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcofWO_IrqAhUux4sKHT52AigQFjABegQIBRAB&url=http%3A%2F%2Fwww.maths.lth.se%2Fna%2Fcourses%2FFMN050%2Fmedia%2Fmaterial%2Fpart8.pdf&usg=AOvVaw068JsSpsLz4z2yUAK9Vkd0
*
* This class is inspired by the piecewise polynomials of MATLAB:
* The coefficients are arranged in groups for each interval (piece) starting the coefficient of highest order. Example:
* Coefficients [a0, b0, c0, d0, a1, b1, c1, d1] belong to interval 0 [x0, x1] and interval 1 [x1, x2] respectively.
* The coefficients for interval 1 represent the following polynomial of order 3:
* f(x) = a1(x−x1)^3 + b1(x−x1)^2 + c1(x−x1) + d1
*/
class ITA_BASE_API CPiecewisePolynomial
{
public:
CPiecewisePolynomial( const std::vector<float>& vdBreakPoints, const std::vector<float>& vdCoeffs, const int iOrder );
// Returns the polynomial order
inline int Order() const { return iOrder; };
//! Returns the number of intervals (pieces) between break points
inline int NumIntervals() const { return vdBreakPoints.size() - 1; };
//! Returns the number of coefficients for a single polynomial
inline int NumCoefficients() const { return Order() + 1; };
//! Returns the break points defining the intervals for the polynomials
inline const std::vector<float>& BreakPoints() const { return vdBreakPoints; };
//! Evaluate the piecewise polynomial at a given x value.
float Value(const float xValue) const;
//! Return a piecewise polynomial containing the derivations of the polynomials of this one
CPiecewisePolynomial Derivation() const;
private:
//! Returns the iterator to the first coefficient of the interval with given index
/**
* The iterator ending this set of coefficients is then:
* std::vector<float>::const_iterator itEnd = itStart + NumCoefficients();
*/
std::vector<float>::const_iterator CoefficientsOfInterval(const int idxInterval) const;
private:
// Order of polynomials
int iOrder;
//! Vector with break points. Defines the interval for each polynomial.
std::vector<float> vdBreakPoints;
//! Vector with all coefficients. Represents a 2D matrix: First dimension = number of intervals (pieces), second dimension = number of coefficients (order+1).
/**
* The Coefficients are arranged in groups for each interval (piece) starting the coefficient of highest order. Example:
* coefficients [a1, b1, c1, d1, a2, b2, c2, d2] belong to interval 1 [x1, x2] and interval2 [x2, x3] respectively.
* The coefficients for interval 1 represent the following polynomial:
* f(x) = a1(x−x1)^3 + b1(x−x1)^2 + c1(x−x1) + d1
*/
std::vector<float> vdCoefficients;
};
//! Uses splines of given polynomial order to create a piecewise polynomial for the given data pairs
ITA_BASE_API CPiecewisePolynomial Spline(const std::vector<float>& vdSupportingPoints, const std::vector<float>& vdDataPoints, const int iPolynomialOrder);
//! Uses cubic splines to create a piecewise polynomial (order 3) for the given data pairs
ITA_BASE_API CPiecewisePolynomial CubicSpline(const std::vector<float>& vdSupportingPoints, const std::vector<float>& vdDataPoints) { return Spline(vdSupportingPoints, vdDataPoints, 3); };
}
#endif // IW_ITA_BASE_SPLINE
#include <ITABase/Spline.h>
#include <ITAException.h>
#include <string>
#include <algorithm>
using namespace ITABase;
CPiecewisePolynomial::CPiecewisePolynomial(const std::vector<float>& vdBreakPoints, const std::vector<float>& vdCoeffs, const int iOrder)
: iOrder(iOrder)
, vdBreakPoints(vdBreakPoints)
, vdCoefficients(vdCoeffs)
{
if (iOrder < 0)
ITA_EXCEPT_INVALID_PARAMETER("Polynom order must be greater or equal zero.");
const int iMinimumNBreakPoints = std::max(2, iOrder + 1); // At least one interval
if ( vdBreakPoints.size() < iMinimumNBreakPoints )
ITA_EXCEPT_INVALID_PARAMETER("Number of break points not sufficient for polynom order: Expected " + std::to_string(iMinimumNBreakPoints) + " but got " + std::to_string(vdBreakPoints.size()) + ".");
const int nCoeffs = NumIntervals() * (iOrder + 1);
if (vdCoeffs.size() != nCoeffs)
ITA_EXCEPT_INVALID_PARAMETER("Invalid number of coefficients: Expected " + std::to_string(nCoeffs) + " but got " + std::to_string(vdCoeffs.size()) + ".");
}
float CPiecewisePolynomial::Value(const float xValue) const
{
//TODO: Check if x-value is inside boundaries
//TODO: Find index of interval, get corresponding coefficients and calculate values
//Something like this might be necessary
std::vector<float>::const_iterator itStart = CoefficientsOfInterval(0);
std::vector<float>::const_iterator itEnd = itStart + NumCoefficients();
for (std::vector<float>::const_iterator it = itStart; itStart < itEnd; it++)
{
}
return 0.0;
}
CPiecewisePolynomial CPiecewisePolynomial::Derivation() const
{
//TODO: Check if this works correctly
const int iNewOrder = std::max(0, iOrder - 1); // Minimum order is zero
const int iNewNumCoefficients = std::max(1, NumCoefficients() - 1); // At least one coefficient
std::vector<float> vdNewCoeffs( NumIntervals() * iNewNumCoefficients, 0.0);
for (int idxPiece = 0; idxPiece < NumIntervals(); idxPiece++)
{
for (int idxCoeff = 0; idxCoeff < iOrder; idxCoeff++)
{
const int iCurrentOrder = iOrder - idxCoeff;
const int idxOld = idxPiece * NumCoefficients() + idxCoeff;
const int idxNew = idxPiece * iNewNumCoefficients + idxCoeff;
vdNewCoeffs[idxNew] = vdCoefficients[idxOld] * iCurrentOrder;
}
}
return CPiecewisePolynomial(vdBreakPoints, vdNewCoeffs, iNewOrder);
}
std::vector<float>::const_iterator ITABase::CPiecewisePolynomial::CoefficientsOfInterval(const int idxInterval) const
{
if (idxInterval < 0 || idxInterval >= NumIntervals())
ITA_EXCEPT_INVALID_PARAMETER("Index for interval is out of bounds.");
//TODO: Check if this is correct
return vdCoefficients.begin() + idxInterval * NumCoefficients();
}
CPiecewisePolynomial ITABase::Spline(const std::vector<float>& vdSupportingPoints, const std::vector<float>& vdDataPoints, const int iPolynomialOrder)
{
//TODO: Calculate coefficients for polynomials
return CPiecewisePolynomial(vdSupportingPoints, { 0.0, 0.0 }, iPolynomialOrder);
}
......@@ -84,4 +84,14 @@ vista_create_default_info_file( ITABaseSpectrumTests )
set_property( TARGET ITABaseSpectrumTests PROPERTY FOLDER "ITACoreLibs/Tests/ITABase" )
add_executable( SplineTest SplineTest.cpp )
target_link_libraries( SplineTest ${VISTA_USE_PACKAGE_LIBRARIES} )
vista_configure_app( SplineTest )
vista_install( SplineTest )
vista_create_default_info_file( SplineTest )
set_property( TARGET SplineTest PROPERTY FOLDER "ITACoreLibs/Tests/ITABase" )
add_subdirectory( "VistaTests" )
/*
* ----------------------------------------------------------------
*
* ITA Base
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*
*
*/
#include <ITABase/Spline.h>
//#include <iostream>
using namespace std;
int main(int iNumInArgs, char* pcInArgs[])
{
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment