1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/* Copyright (c) 2008-2022 the MRtrix3 contributors.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Covered Software is provided under this License on an "as is"
* basis, without warranty of any kind, either expressed, implied, or
* statutory, including, without limitation, warranties that the
* Covered Software is free of defects, merchantable, fit for a
* particular purpose or non-infringing.
* See the Mozilla Public License v. 2.0 for more details.
*
* For more details, see http://www.mrtrix.org/.
*/
#ifndef __math_cubic_spline_h__
#define __math_cubic_spline_h__
namespace MR
{
namespace Math
{
enum SplineProcessingType
{
Value = 1,
Derivative = 2,
ValueAndDerivative = Value | Derivative
};
template <typename T> class CubicSpline
{ MEMALIGN(CubicSpline<T>)
public:
using BasisMatrix = Eigen::Matrix<T, 4, 4>;
using WeightVector = Eigen::Matrix<T, 1, 4>;
WeightVector weights, deriv_weights;
void set (T position) {
(this->*(_internal_set)) (position);
}
T coef (size_t i) const {
return (weights[i]);
}
protected:
static const BasisMatrix cubic_poly_derivative_operator;
const BasisMatrix basis_matrix;
const BasisMatrix deriv_basis_matrix;
CubicSpline (SplineProcessingType processType, const BasisMatrix basis_matrix, const BasisMatrix deriv_basis_matrix) :
basis_matrix (basis_matrix),
deriv_basis_matrix (deriv_basis_matrix)
{
switch (processType) {
case SplineProcessingType::Value:
_internal_set = &CubicSpline::_set_value;
break;
// Could be used for partial derviative so we need to calculate both deriv and value weights
case SplineProcessingType::Derivative:
case SplineProcessingType::ValueAndDerivative:
_internal_set = &CubicSpline::_set_value_deriv;
break;
default:
break;
}
}
private:
CubicSpline () {}
// Function pointer to the internal set function depening on processing type
void (CubicSpline::*_internal_set) (T);
inline void _set_value (T position) {
const T p2 = Math::pow2(position);
const auto vec = WeightVector (p2 * position, p2, position, 1.0);
weights = (vec * basis_matrix);
}
inline void _set_value_deriv (T position) {
const T p2 = Math::pow2(position);
const auto vec = WeightVector (position * p2, p2, position, 1.0);
weights = (vec * basis_matrix);
deriv_weights = (vec * deriv_basis_matrix);
}
};
// Hermite spline implementation
template <typename T> class HermiteSpline :
public CubicSpline<T> { MEMALIGN(HermiteSpline<T>)
public:
using BasisMatrix = typename CubicSpline<T>::BasisMatrix;
static const BasisMatrix hermite_basis_mtrx;
static const BasisMatrix hermite_derivative_basis_mtrx;
HermiteSpline (SplineProcessingType processType)
: CubicSpline<T> (processType, hermite_basis_mtrx, hermite_derivative_basis_mtrx) {}
};
// Uniform bspline implementation
template <typename T> class UniformBSpline :
public CubicSpline<T> { MEMALIGN(UniformBSpline<T>)
public:
using BasisMatrix = typename CubicSpline<T>::BasisMatrix;
static const BasisMatrix uniform_bspline_basis_mtrx;
static const BasisMatrix uniform_bspline_derivative_basis_mtrx;
UniformBSpline (SplineProcessingType processType)
: CubicSpline<T> (processType, uniform_bspline_basis_mtrx, uniform_bspline_derivative_basis_mtrx) {}
};
// Initialise our static const matrices
template <typename T>
const typename CubicSpline<T>::BasisMatrix
CubicSpline<T>::cubic_poly_derivative_operator((BasisMatrix() <<
0, 0, 0, 0,
3, 0, 0, 0,
0, 2, 0, 0,
0, 0, 1, 0).finished());
// Hermite spline
template <typename T>
const typename HermiteSpline<T>::BasisMatrix
HermiteSpline<T>::hermite_basis_mtrx((BasisMatrix() <<
-0.5, 1.5, -1.5, 0.5,
1, -2.5, 2, -0.5,
-0.5, 0, 0.5, 0,
0, 1, 0, 0).finished());
template <typename T>
const typename HermiteSpline<T>::BasisMatrix
HermiteSpline<T>::hermite_derivative_basis_mtrx(CubicSpline<T>::cubic_poly_derivative_operator * hermite_basis_mtrx);
// Uniform b-spline
template <typename T>
const typename UniformBSpline<T>::BasisMatrix
UniformBSpline<T>::uniform_bspline_basis_mtrx((1/6.0) * (BasisMatrix() <<
-1, 3, -3, 1,
3, -6, 3, 0,
-3, 0, 3, 0,
1, 4, 1, 0).finished());
template <typename T>
const typename UniformBSpline<T>::BasisMatrix
UniformBSpline<T>::uniform_bspline_derivative_basis_mtrx(CubicSpline<T>::cubic_poly_derivative_operator * uniform_bspline_basis_mtrx);
}
}
#endif
|