Кривая Безье в современном C++

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

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

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

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

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

Странный вопрос. Я бы оставил ссылку на исходный вопрос, но разместите здесь код с конкретным запросом о том, с чем у вас проблемы. Это почти похоже на вопрос типа «мой код не работает, что не так? <Код>» (который не по теме), но я знаю, что это не так. Если бы это была ссылка на код сайта, не относящегося к StackExchange, она была бы отклонена и, возможно, закрыта.

Steve 09.11.2018 07:30

@ Стив, я понимаю твою точку зрения. Я не думаю, что это не по теме, но я согласен с тем, что, по крайней мере, текущий пример наилучшего усилия был бы хорош. Я думаю, что мы увидим больше этих вопросов по мере развития C++ 17 (а вскоре и C++ 20).

jonspaceharper 09.11.2018 11:15

@JonHarper: Связанный код не просто плох по стандартам C++ 17. Это даже не хороший код на C++ 98.

MSalters 09.11.2018 12:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
1 125
2

Ответы 2

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

или что-то в этом роде.

Хотя это работает, это несколько неэффективно. Он повторно генерирует indexes_of(tmp). Этот стиль также затрудняет оптимизатору создание кода SIMD (например, AVX или NEON).

MSalters 09.11.2018 12:33

@msal индексы tmp - это числа 0 и размер-1. Всего 2 числа.

Yakk - Adam Nevraumont 09.11.2018 13:16

Конечно, но size продолжает меняться из-за того, что .resize во внешнем цикле.

MSalters 09.11.2018 13:20

«Кроме того, я понимаю, что это улучшит его оптимизацию за счет обновления до современного 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.

Другие вопросы по теме