使用c ++在OpenGL中绘制bezier曲线的切线

时间:2017-06-12 17:54:40

标签: c++ opengl point bezier curve

所以我有一个有4个控制点的程序

std::vector<ControlPoint> cam_pos_points;
    cam_pos_points.push_back(ControlPoint(-0.79, 0.09, 0.2, 0));
    cam_pos_points.push_back(ControlPoint(-0.88, -0.71, 0.2, 1));
    cam_pos_points.push_back(ControlPoint(1.3, -0.8, 0.2, 2));
    cam_pos_points.push_back(ControlPoint(0.71, 0.76, 0.2, 3));

基本上,发生的事情是我设置了移动控制点的方法,当移动控制点时,保存新位置并根据新位置重新计算曲线。我绘制曲线的方式是使用这些方程:

for (double t = 0; t < 1; t += 0.1){
    float Px =(pow((1 - t), 3) * cam_pos_points[0].positionx()) + 
        ((pow((1 - t), 2) * t) * cam_pos_points[1].positionx()) + 
        (((1 - t) * pow(t, 2)) * cam_pos_points[2].positionx()) + 
        (pow(t, 3) * cam_pos_points[3].positionx());

    float Py =(pow((1 - t), 3) * cam_pos_points[0].positiony()) + 
        ((pow((1 - t), 2) * t) * cam_pos_points[1].positiony()) + 
        (((1 - t) * pow(t, 2)) * cam_pos_points[2].positiony()) + 
        (pow(t, 3) * cam_pos_points[3].positiony());
}

然后使用这两个浮点值,我将它们放入vec3并制作一堆点。然后,我通过将它们放入多线类中,通过声明曲线中的点,然后在每个点之间绘制一条直线,在所有这些点之间绘制一条线。最终结果将是一个贝塞尔曲线。

我现在遇到的问题是绘制贝塞尔曲线的切线。我的想法是,对于第一个控制点,就是说切线位于P1-P2线上。因此,在绘制切线后,当我移动切点时,我应该使用哪些方程来重新绘制曲线的形状?我已经找到了bezier曲线方程的导数,但我不知道如何处理它们:

float dx = (-3*(pow((1 - t), 2)) * cam_pos_points[0].positionx()) + 
             (((-2*(1 - t)) * t) * cam_pos_points[1].positionx()) + 
              (((1 - t) * (2*t)) * cam_pos_points[2].positionx()) + 
                  ((3*pow(t, 2)) * cam_pos_points[3].positionx());

float dy = (-3*(pow((1 - t), 2)) * cam_pos_points[0].positiony()) + 
             (((-2*(1 - t)) * t) * cam_pos_points[1].positiony()) + 
              (((1 - t) * (2*t)) * cam_pos_points[2].positiony()) + 
                  ((3*pow(t, 2)) * cam_pos_points[3].positiony());

3 个答案:

答案 0 :(得分:0)

您开始切线将从第一个控制点到第二个控制点,结束切线将从第四个控制点到第三个控制点。我建议你每次重绘时都要重新开始;也就是说,每当控制点移动时,将其视为一个全新的等式。

如果你的一条(或两条)切线为零长度,那么它们实际上不是切线本身,而是曲线将朝向相反的端点。

这就是为什么你可以使用没有切线的贝塞尔曲线来表示直线的原因。

答案 1 :(得分:0)

方程式错误。

正确的等式是

(1-t)^3 * p0 + 3*(1-t)^2*t * p1 + 3*(1-t)*t^2 * p2 + t^3 * p3. 

展开并区分以获得切线。

答案 2 :(得分:0)

看起来您想在Bezier曲线的起点和终点绘制切线矢量的切点,以便您可以允许用户通过移动切点来调整曲线的形状。如果是这种情况,您需要注意移动切点也会移动第2或第3个控制点。因此,正确的步骤是从移动的切点重新计算第2或第3个控制点,然后重绘曲线。

对于三次贝塞尔曲线,t = 0和1时的C&#39;(t)

  

C&#39;(0)= 3 *(P1-P0)
C&#39;(1)= 3 *(P3-P2)

假设起始切线的切点为T0,位于

  

T0 = P0 + s0 * C&#39;(0)= P0 + 3 * s0 *(P1-P0)

其中s0是一个恒定的比例因子,用于确保切点不会离控制点太远。当T0更改为T0 *时,可以将控制点P1更新为

  

P1 * =(T0 * -P0)/(3 * s0)+ P0。

当移动结束切线的切点时,对控制点P2进行类似的更新。然后,您可以重绘曲线。