Кривая Безье в современном C ++ - PullRequest
0 голосов
/ 09 ноября 2018

Может ли кто-нибудь обновить это до современного C ++, чтобы я мог лучше понять, что происходит?

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

Я пытался заменить указатель на points на std::vector, чтобы убрать необходимость ручного выделения памяти.

Я также пытался использовать for (auto& foo : foos), но я просто не могу следовать логике этой математики.

Кроме того, я понимаю, что это значительно улучшило бы его оптимизацию путем обновления до современного C ++.

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

"Кроме того, я понимаю, что это значительно улучшило бы его оптимизацию путем обновления до современного C ++"

На самом деле код выглядит так, как будто лучшая оптимизация - это векторизация, например используя AVX на x86 или NEON на ARM. И это лучше всего работает, если векторизатор может работать с индексами и четкими границами. Итак:

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];
}

Однако обратите внимание, что основная проблема оптимизации заключается в том, что вы получаете только одно очко за раз. Как правило, вам нужна вся кривая (от t = 0.0 до t = 1.0), а затем выполняется довольно много лишней работы - все эти границы цикла идентичны для всех значений t.

0 голосов
/ 09 ноября 2018
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 и point должны быть очевидны.

Вот 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()); }

или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...