Refactor geom::bezier: extract a free-function de Casteljau's algorithm & support changing control points
This commit is contained in:
parent
a368eb32ff
commit
a22ea3d02e
1 changed files with 33 additions and 7 deletions
|
|
@ -8,9 +8,24 @@
|
||||||
namespace psemek::geom
|
namespace psemek::geom
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// In-place de Casteljau's algorithm
|
||||||
|
template <typename Iterator, typename T>
|
||||||
|
auto de_casteljau(Iterator begin, Iterator end, T const & t)
|
||||||
|
{
|
||||||
|
while (std::next(begin) != end)
|
||||||
|
{
|
||||||
|
for (auto it = begin, jt = std::next(begin); jt != end; it = jt++)
|
||||||
|
*it = lerp(*it, *jt, t);
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
return *begin;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Point>
|
template <typename Point>
|
||||||
struct bezier
|
struct bezier
|
||||||
{
|
{
|
||||||
|
bezier() = default;
|
||||||
|
|
||||||
bezier(std::vector<Point> points)
|
bezier(std::vector<Point> points)
|
||||||
: points_(std::move(points))
|
: points_(std::move(points))
|
||||||
{
|
{
|
||||||
|
|
@ -19,23 +34,34 @@ namespace psemek::geom
|
||||||
temp_.resize(points_.size());
|
temp_.resize(points_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Point> & points()
|
||||||
|
{
|
||||||
|
return points_;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto operator()(T const & t) const
|
auto operator()(T const & t) const
|
||||||
{
|
{
|
||||||
// In-place de Casteljau's algorithm
|
|
||||||
temp_ = points_;
|
temp_ = points_;
|
||||||
|
return de_casteljau(temp_.begin(), temp_.end(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto tangent(T const & t) const
|
||||||
|
{
|
||||||
|
// In-place de Casteljau's algorithm for derivative
|
||||||
|
tangent_temp_.resize(points_.size() - 1);
|
||||||
for (std::size_t k = 0; k + 1 < points_.size(); ++k)
|
for (std::size_t k = 0; k + 1 < points_.size(); ++k)
|
||||||
{
|
tangent_temp_[k] = points_[k + 1] - points_[k];
|
||||||
for (std::size_t i = 0; i + k + 1 < points_.size(); ++i)
|
return static_cast<T>(points_.size()) * de_casteljau(tangent_temp_.begin(), tangent_temp_.end(), t);
|
||||||
temp_[i] = lerp(temp_[i], temp_[i + 1], t);
|
|
||||||
}
|
|
||||||
return temp_.front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Point> const points_;
|
using vector_type = decltype(Point{} - Point{});
|
||||||
|
|
||||||
|
std::vector<Point> points_;
|
||||||
std::vector<Point> mutable temp_;
|
std::vector<Point> mutable temp_;
|
||||||
|
std::vector<vector_type> mutable tangent_temp_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue