philsupertramp/game-math
Loading...
Searching...
No Matches
Spline.h
Go to the documentation of this file.
1
9#pragma once
10
11#include "../../Matrix.h"
12#include "../../matrix_utils.h"
13#include "../lin_alg/gaussSeidel.h"
14#include "../utils.h"
15
21class Spline
22{
34 bool isEquidistant = true;
35
36public:
42 Spline(const Matrix<double>& X, const Matrix<double>& Y) {
43 bool isRows = X.rows() > X.columns();
44 XI = isRows ? X : X.Transpose();
45 YI = isRows ? Y : Y.Transpose();
46 double h = fabs(XI(1, 0) - XI(0, 0));
47 for(size_t i = 0; i < XI.rows() - 1; ++i) {
48 auto dist = fabs(XI(i + 1, 0) - XI(i, 0));
49 if((dist - h) > EPS) { isEquidistant = false; }
50 }
51 }
52
59 Spline(const Matrix<double>& X, const Matrix<double>& Y, const Matrix<double>& Z) {
60 bool isRows = X.rows() > X.columns();
61 XI = isRows ? X : X.Transpose();
62 YI = isRows ? Y : Y.Transpose();
63 ZI = isRows ? Z : Z.Transpose();
64 double h = fabs(XI(1, 0) - XI(0, 0));
65 for(size_t i = 0; i < XI.rows() - 1; ++i) {
66 auto dist = fabs(XI(i + 1, 0) - XI(i, 0));
67 if((dist - h) > EPS) { isEquidistant = false; }
68 }
69 }
74 double eval_spline_j(double x_act, size_t j, const Matrix<double>& mi) {
75 auto h = XI(j + 1, 0) - XI(j, 0);
76 return ((mi(j, 0) * pow((XI(j + 1, 0) - x_act), 3.0) + mi(j + 1, 0) * pow((x_act - XI(j, 0)), 3.0)) / 6.0) / h
77 + (YI(j, 0) * (XI(j + 1, 0) - x_act) + YI(j + 1, 0) * (x_act - XI(j, 0))) / h
78 - ((mi(j, 0) * (XI(j + 1, 0) - x_act) + mi(j + 1, 0) * (x_act - XI(j, 0))) * h) / 6.0;
79 }
80
86 Matrix<double> curv(double h) {
87 auto mi = zeros(XI.rows(), XI.columns());
88 auto dim = XI.rows() - 2;
89 auto rhs = 6.0 / (h * h) * (tridiag(dim, dim, 1, -2, 1) * YI.GetSlice(1, YI.rows() - 2, 0, YI.columns() - 1));
90 auto lhs = tridiag(dim, dim, 1, 4, 1);
91 auto res = gaussSeidel(lhs, rhs);
92 for(size_t i = 0; i < res.rows(); ++i) { mi(i + 1, 0) = res(i, 0); }
93 return mi;
94 }
95
102 Tx = tx;
103 Ty = ty;
104 }
105
112 if(isEquidistant && ZI.rows() == 0) return calculateEquidistant(xi);
113 else {
115 if(Tx.rows() > 0) {
116 ti = Tx;
117 } else {
118 ti = linspace(min(xi), max(xi), XI.rows()).Transpose();
119 }
120 auto s = Spline(ti, XI)(xi);
121
122 if(YI.rows() > 0) { s = s.HorizontalConcat(Spline(ti, YI)(xi)); }
123 if(ZI.rows() > 0) { s = s.HorizontalConcat(Spline(ti, ZI)(xi)); }
124 return s;
125 }
126 }
127
134 auto innerXI = xi.rows() > xi.columns() ? xi : xi.Transpose();
135 auto mi = curv(XI(1, 0) - XI(0, 0));
136 auto y = zeros(innerXI.rows(), innerXI.columns());
137 // Elementwise evaluate splines, for all
138 // elements xi with i = 0, ..., n-1
139 for(size_t j = 0; j < XI.rows() - 1; ++j) {
140 // all elements x, between x_j and x_{j+1}
141 auto xl = XI(j, 0);
142 auto xr = XI(j + 1, 0);
143 auto ind = nonzero([xl, xr](const double& x) { return bool((xl <= x) && (x <= xr)); }, innerXI).Transpose();
144 // evaluate using the j-th spline
145 for(size_t i = 0; i < ind.rows(); ++i) { y(ind(i, 0), 0) += eval_spline_j(innerXI(ind(i, 0), 0), j, mi); }
146 }
147 return y;
148 }
149};
150
double pow(double x, int exponent)
Definition: Matrix.h:42
constexpr Matrix< T > Transpose() const
Definition: Matrix.h:256
size_t rows() const
Definition: Matrix.h:193
size_t columns() const
Definition: Matrix.h:198
Matrix GetSlice(size_t rowStart) const
Definition: Matrix.h:609
Definition: Spline.h:22
Matrix< double > calculateEquidistant(const Matrix< double > &xi)
Definition: Spline.h:133
double eval_spline_j(double x_act, size_t j, const Matrix< double > &mi)
Definition: Spline.h:74
Matrix< double > curv(double h)
Definition: Spline.h:86
Spline(const Matrix< double > &X, const Matrix< double > &Y, const Matrix< double > &Z)
Definition: Spline.h:59
Matrix< double > ZI
z-axis support values
Definition: Spline.h:28
Matrix< double > Tx
t-Values for x
Definition: Spline.h:30
Matrix< double > operator()(const Matrix< double > &xi)
Definition: Spline.h:111
void SetAbstractionValue(const Matrix< double > &tx, const Matrix< double > &ty)
Definition: Spline.h:101
Matrix< double > Ty
t-Values for y
Definition: Spline.h:32
Spline(const Matrix< double > &X, const Matrix< double > &Y)
Definition: Spline.h:42
bool isEquidistant
flag to signalize that support values do not lie equidistant to each other
Definition: Spline.h:34
Matrix< double > YI
y-axis support values
Definition: Spline.h:26
Matrix< double > XI
x-axis support values
Definition: Spline.h:24
Matrix< double > gaussSeidel(const Matrix< double > &A, const Matrix< double > &b)
Definition: gaussSeidel.h:29
T min(const Matrix< T > &mat)
Definition: matrix_utils.h:324
T max(const Matrix< T > &mat)
Definition: matrix_utils.h:292
#define EPS
accuracy of calculated results
Definition: utils.h:24
Matrix< size_t > nonzero(const std::function< bool(const double &)> &validation, const Matrix< double > &x)
Matrix< double > tridiag(size_t rows, size_t columns, double left, double center, double right)
Matrix< double > zeros(size_t rows, size_t columns, size_t elements=1)
Matrix< double > linspace(double start, double end, unsigned long num_elements)