BSplinebasis
Loading...
Searching...
No Matches
BSplineGenerator.h
1/*
2 * ########################################################################
3 * The contents of this file is free and unencumbered software released into the
4 * public domain. For more information, please refer to <http://unlicense.org/>
5 * ########################################################################
6 *
7 * [1] https://en.wikipedia.org/wiki/B-spline
8 */
9
10#ifndef BSPLINE_BSPLINEGENERATOR_H
11#define BSPLINE_BSPLINEGENERATOR_H
12
13#include <bspline/Spline.h>
14#include <bspline/exceptions/BSplineException.h>
15#include <bspline/operators/CompoundOperators.h>
16#include <bspline/operators/Position.h>
17#include <bspline/operators/ScalarOperators.h>
18
19#include <algorithm>
20
21namespace bspline {
22using namespace bspline::exceptions;
23
32template <typename T>
33class BSplineGenerator final {
34 private:
36 Grid<T> _grid;
37
40 std::vector<T> _knots;
41
54 Grid<T> generateGrid(std::vector<T> knots) {
55 const auto endIterator = std::unique(knots.begin(), knots.end());
56 knots.erase(endIterator, knots.end());
57 return Grid<T>(std::move(knots));
58 }
59
60 public:
67 explicit BSplineGenerator(std::vector<T> knots)
68 : _grid(generateGrid(knots)), _knots(std::move(knots)){};
69
80 BSplineGenerator(std::vector<T> knots, const Grid<T> &grid)
81 : _grid(grid), _knots(std::move(knots)) {
82 // Check, whether the given knots vector and grid are consistent.
83 const Grid<T> secondGrid = generateGrid(_knots);
84 if (_grid != secondGrid) {
85 throw BSplineException(ErrorCode::INCONSISTENT_DATA);
86 }
87 };
88
93 Grid<T> getGrid() const { return _grid; };
94
102 template <size_t order>
103 std::vector<Spline<T, order>> generateBSplines() const {
104 static constexpr size_t k = order + 1;
105 if (_knots.size() < k) {
106 throw BSplineException(ErrorCode::UNDETERMINED,
107 "The knots vector contains too few elements to "
108 "generate BSplines of the requested order.");
109 }
110
111 if constexpr (order == 0) {
112 return generateZerothOrderSplines();
113 } else {
114 const auto nextLowerOrderSplines = generateBSplines<order - 1>();
115 std::vector<Spline<T, order>> ret;
116 ret.reserve(_knots.size() - k);
117 for (size_t i = 0; i < _knots.size() - k; i++) {
120 }
121 return ret;
122 }
123 }
124
125 private:
141 template <size_t k>
142 Spline<T, k - 1> applyRecursionRelation(
143 size_t i, const Spline<T, k - 2> &splinei,
144 const Spline<T, k - 2> &splineip1) const {
145 static_assert(k >= 2, "k has to be at least 2.");
146
147 Spline<T, k - 1> ret(_grid);
148
149 const T &xi = _knots.at(i);
150 const T &xipkm1 = _knots.at(i + k - 1);
151 if (xipkm1 > xi) {
152 const T prefac = static_cast<T>(1) / (xipkm1 - xi);
153 const auto op = prefac * (operators::X<1>{} - xi);
154 ret = op * splinei;
155 }
156
157 const T &xip1 = _knots.at(i + 1);
158 const T &xipk = _knots.at(i + k);
159 if (xipk > xip1) {
160 const T prefac = static_cast<T>(1) / (xipk - xip1);
161 const auto op = prefac * (xipk - operators::X<1>{});
162 ret += op * splineip1;
163 }
164
165 return ret;
166 }
167
173 std::vector<Spline<T, 0>> generateZerothOrderSplines() const {
174 std::vector<Spline<T, 0>> ret;
175 const size_t numberOfSplines = (_knots.empty()) ? 0 : _knots.size() - 1;
176 ret.reserve(numberOfSplines);
177
178 for (size_t i = 0; i < numberOfSplines; i++) {
179 const T &xi = _knots.at(i);
180 const T &xip1 = _knots.at(i + 1);
181
182 if (xi > xip1) {
183 throw BSplineException(ErrorCode::UNDETERMINED);
184 } else if (xi == xip1) {
185 ret.push_back(Spline<T, 0>{_grid});
186 } else {
187 std::vector<std::array<T, 1>> coefficients{{static_cast<T>(1)}};
188
189 const size_t gridIndex = _grid.findElement(xi);
190
191 ret.push_back(Spline<T, 0>{Support(_grid, gridIndex, gridIndex + 2),
192 std::move(coefficients)});
193 }
194 }
195 return ret;
196 }
197};
198
210template <size_t order, typename T>
211std::vector<Spline<T, order>> generateBSplines(std::vector<T> knots) {
212 BSplineGenerator gen(std::move(knots));
213 return gen.template generateBSplines<order>();
214}
215
216} // namespace bspline
217#endif // BSPLINE_BSPLINEGENERATOR_H
Generates the BSplines on a grid.
Definition BSplineGenerator.h:33
std::vector< Spline< T, order > > generateBSplines() const
Generates all BSplines with respect to the knots vector.
Definition BSplineGenerator.h:103
BSplineGenerator(std::vector< T > knots, const Grid< T > &grid)
Constructor using the provided grid instance.
Definition BSplineGenerator.h:80
BSplineGenerator(std::vector< T > knots)
Constructor generating the grid from the knots vector.
Definition BSplineGenerator.h:67
Grid< T > getGrid() const
Returns the grid.
Definition BSplineGenerator.h:93
The central Spline class of the library.
Definition Spline.h:59
The main exception class.
Definition BSplineException.h:84
Represents a global Grid.
Definition Grid.h:27
const T & at(size_t i) const
Gives access to the i-th element of the Grid.
Definition Grid.h:218
size_t size() const
Returns the number of elements of the Grid.
Definition Grid.h:169
size_t findElement(const T &x) const
Returns the index corresponding to the element x.
Definition Grid.h:275
Represents the Spline's Support.
Definition Support.h:33
Exceptions and error codes.
Definition BSplineException.h:19
Main namespace for this library.
Definition BSplineGenerator.h:21
std::vector< Spline< T, order > > generateBSplines(std::vector< T > knots)
Convenience method to generate a set of BSplines.
Definition BSplineGenerator.h:211