为什么我的bezier曲线实现有偏差?

时间:2014-12-12 12:55:51

标签: c++ bezier

我想用C ++渲染贝塞尔曲线,所以我自己开始实现它。目前,它不一定非常有效。我的代码以某种方式产生接近结果,但这些曲线不准确。 (dvec2是两个double值的向量。)

list<dvec2> bezier(list<dvec2> const &points, int resolution)
{
    list<dvec2> samples;
    double step = 1.0 / resolution;
    for (double time = 0.0; time <= 1.0; time += step) {
        list<dvec2> sliders = points;
        while (sliders.size() > 1)
            sliders = slide(sliders, time);
        samples.push_back(sliders.front());
    }
    return samples;
}

list<dvec2> slide(list<dvec2> const &points, double time)
{
    list<dvec2> result;
    auto current = points.begin();
    dvec2 last = *current;
    for (++current; current != points.end(); ++current)
        result.push_back(last * time + *current * (1.0 - time));
    return result;
}

目前,我通过插入第一个和第二个来创建n-1个点,第二个用第三个插值,依此类推,基于时间t。然后,我通过相同的算法再次减少这个新的点集,直到我留下一个我可以绘制的点。我认为这种方法应该有效。

在渲染图像上,您可以在多条渲染曲线上看到算法结果。

rendering looks similar to bezier curves

例如,在图像的左下角,我认为两条相对的曲线应该是对称的。我的方向偏向于偏见。此外,那些完全封闭的曲线应至少在t = 0.5的中心画一个点。是什么造成的?

1 个答案:

答案 0 :(得分:4)

你的方法应该有效。您进行了一些疏忽:在slide()内,您不会在循环中更新last

尝试:

for (++current; current != points.end(); ++current) {
    result.push_back(last * time + *current * (1.0 - time));
    last = *current; // <--
}

请注意,通过获取这些产品的总和,可以给出对贝塞尔曲线的不同解释:

  

(资料来源:wikipedia

     

某些术语与这些参数曲线相关联。我们有

     

\mathbf{B}(t) = \sum_{i=0}^n b_{i, n}(t)\mathbf{P}_i,\quad t \in [0, 1]

     

其中多项式

     

b_{i,n}(t) = {n\choose i} t^i (1 - t)^{n - i},\quad i = 0, \ldots, n

     

被称为度 n 的Bernstein基多项式。

在这里,您需要(预先计算的)二项式系数,并且通过使用std::pow函数,您最终得到一个循环而不是两个嵌套的循环(考虑 n 受限于在实践中不断,使预计算成为可能)。