简体   繁体   中英

Bezier Curve in Modern C++

Could someone update this into modern C++ so I could better understand what is going on?

https://stackoverflow.com/a/21642962/10470367

I've been trying to replace the pointer to points with an std::vector to remove the necessity of manual mem allocation.

I've also been trying to utilize for (auto& foo : foos) , but I just cannot follow the logic for this math.

Also, I understand this would improve its optimization a bunch by updating to modern C++.

point getBezierPoint( span<const point>  points, float t ) {
  vector<point> tmp = as_vector(points);
  while (tmp.size()>1) {
    for (auto k:indexes_of(tmp).except_last())
        tmp[k] = tmp[k] + t * ( tmp[k+1] - tmp[k] );
    tmp.resize(tmp.size()-1);
  }
  return tmp[0];
}

span, as_vector and point should be obvious.

Here is indexes_of :

template<class It>
struct range_t{
  It b,e;
  It begin()const{return b;}
  It end()const{return e;}
  range_t except_last(std::size_t i=1)const{
    auto r = *this;
    r.e-=i;
    return r;
  }
};
template<class It>
range_t<It> range(It be, It e){ return {std::move(b),std::move(e)}; }
template<class X>
struct indexer_t {
  X x;
  X operator*()const{return x;}
  void operator++(){ ++x; }
  void operator--(){ --x; }
  void operator+=(std::ptrdiff_t i){ x+=i; }
  void operator-=(std::ptrdiff_t i){ x-=i; }
  friend bool operator==(indexer_t const&lhs, indexer_t  const& rhs){return lhs.x==rhs.x;}
  friend bool operator!=(indexer_t const&lhs, indexer_t  const& rhs){return lhs.x!=rhs.x;}
};
range_t<indexer_t<std::size_t>> count( std::size_t start, std::size_t finish ){
  return {{start}, {finish}};
}
template<class C>
auto indexes_of(C&&c) { return count(0, c.size()); }

or somesuch.

"Also, I understand this would improve its optimization a bunch by updating to modern C++"

Actually, the code looks like the best optimization is vectorization, eg using AVX on x86 or NEON on ARM. And that works best if the vectorizer can work with indexes and clear bounds. So:

vec2 getBezierPoint( std::vector<vec2> points, float t ) {
    auto const maxi = points.size()-1;
    for(int i = 0; i != maxi; ++i) 
    {
        auto const maxj = maxi-i;
        for (int j = 0; j < maxj; ++j)
            points[j] += t * ( points[j+1] - points[j] );
    }
    return points[0];
}

However, note that the main optimization problem here is that you only get one point at a time. You typically want the whole curve (from t=0.0 to t=1.0) and then this is doing quite a bit of redundant work - all those loop bounds are identical for all t values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM