23 const std::map<double, std::pair<T, T>> &
points() const noexcept
37 void appendPoint(
const std::pair<
double, std::pair<T, T>> & point)
54 throw std::runtime_error(
"[CubicHermiteSpline] Invalid points size: " + std::to_string(n));
59 for(
size_t k = 0; k < n - 1; k++, pointIt++)
61 const T & pk = pointIt->second.first;
62 const T & pk1 = std::next(pointIt)->second.first;
63 const T & vk = pointIt->second.second;
64 const T & vk1 = std::next(pointIt)->second.second;
65 double deltaT = std::next(pointIt)->first - pointIt->first;
68 std::array<T, 4> coeff = {
71 -3 * pk - 2 * deltaT * vk + 3 * pk1 - deltaT * vk1,
72 2 * pk + deltaT * vk - 2 * pk1 + deltaT * vk1};
74 std::shared_ptr<CubicPolynomial<T>> cubicFunc = std::make_shared<CubicPolynomial<T>>(coeff);
75 this->
funcs_.emplace(std::next(pointIt)->first, cubicFunc);
89 auto funcIt = this->
funcs_.lower_bound(t);
92 double scaledT = (t - seg.first) / (seg.second - seg.first);
93 return (*(funcIt->second))(scaledT);
103 auto funcIt = this->
funcs_.lower_bound(t);
106 double scaledT = (t - seg.first) / (seg.second - seg.first);
107 return (funcIt->second)->derivative(scaledT, order) / std::pow(seg.second - seg.first, order);
119 std::vector<T> delta;
120 std::vector<T> alpha;
124 for(
auto it =
points_.begin(); it != std::prev(
points_.end()); it++)
126 delta.push_back((std::next(it)->second.first - it->second.first) / (std::next(it)->first - it->first));
138 it->second.second = delta[i];
141 else if(it == std::prev(
points_.end()))
145 it->second.second = delta[i - 1];
150 it->second.second = (delta[i - 1] + delta[i]) / 2;
151 for(
int j = 0; j <
dim_; j++)
153 if(delta[i - 1][j] * delta[i][j] < 0)
155 it->second.second[j] = 0;
166 for(
auto it =
points_.begin(); it != std::prev(
points_.end()); it++)
168 for(
int j = 0; j <
dim_; j++)
170 if(std::abs(delta[i][j]) < std::numeric_limits<double>::min())
172 it->second.second[j] = 0;
173 std::next(it)->second.second[j] = 0;
183 for(
auto it =
points_.begin(); it != std::prev(
points_.end()); it++)
185 alpha.push_back(it->second.second.cwiseProduct(delta[i].cwiseInverse()));
186 beta.push_back(std::next(it)->second.second.cwiseProduct(delta[i].cwiseInverse()));
187 for(
int j = 0; j <
dim_; j++)
191 it->second.second[j] = 0;
195 std::next(it)->second.second[j] = 0;
205 for(
auto it =
points_.begin(); it != std::prev(
points_.end()); it++)
207 for(
int j = 0; j <
dim_; j++)
209 if(std::abs(delta[i][j]) < std::numeric_limits<double>::min())
213 if(!(alpha[i][j] - std::pow(2 * alpha[i][j] + beta[i][j] - 3, 2) / (3 * (alpha[i][j] + beta[i][j] - 2)) > 0
214 || alpha[i][j] + 2 * beta[i][j] - 3 <= 0 || 2 * alpha[i][j] + beta[i][j] - 3 <= 0))
216 double tau = 3 / std::sqrt(std::pow(alpha[i][j], 2) + std::pow(beta[i][j], 2));
217 it->second.second[j] = tau * alpha[i][j] * delta[i][j];
218 std::next(it)->second.second[j] = tau * beta[i][j] * delta[i][j];
232 auto funcIt =
points_.lower_bound(t);
237 return {std::prev(funcIt)->first, funcIt->first};