games101 作业4

games101 作业4

  • 任务说明
    Bézier 曲线是一种用于计算机图形学的参数曲线。在本次作业中,你需要实现 de Casteljau 算法来绘制由 4 个控制点表示的 Bézier 曲线 (当你正确实现该算法时,你可以支持绘制由更多点来控制的 Bézier 曲线)。你需要修改的函数在提供的 main.cpp 文件中。
    • bezier:该函数实现绘制 Bézier 曲线的功能。它使用一个控制点序列和一个OpenCV::Mat 对象作为输入,没有返回值。它会使 t 在 0 到 1 的范围内进行迭代,并在每次迭代中使 t 增加一个微小值。对于每个需要计算的 t,将调用另一个函数 recursive_bezier,然后该函数将返回在 Bézier 曲线上 t处的点。最后,将返回的点绘制在 OpenCV ::Mat 对象上。
    • recursive_bezier:该函数使用一个控制点序列和一个浮点数 t 作为输入,实现 de Casteljau 算法来返回 Bézier 曲线上对应点的坐标。

  • 算法说明
    De Casteljau 算法说明如下:

    1. 考虑一个 p0 , p1 , … pn 为控制点序列的 Bézier 曲线。首先,将相邻的点连接起来以形成线段。
    2. 用 t : (1 − t) 的比例细分每个线段,并找到该分割点。
    3. 得到的分割点作为新的控制点序列,新序列的长度会减少一。
    4. 如果序列只包含一个点,则返回该点并终止。否则,使用新的控制点序列并转到步骤 1。使用 [0,1] 中的多个不同的 t 来执行上述算法,你就能得到相应的 Bézier 曲线。

代码

首先是recursive_bezier函数

cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{
    // TODO: Implement de Casteljau's algorithm
    /*
    //如果序列只包含一个点,则该点返回并中止
    if(control_points.size() ==0){
        return control_points[0];
    }

    //先得到四个控制点的位置
    cv::Point2f p0 = control_points[0];
    cv::Point2f p1 = control_points[1];
    cv::Point2f p2 = control_points[2];
    cv::Point2f p3 = control_points[3];

    //然后得到四个控制点连成的三条线段的三个分割点
    cv::Point2f p10 = (1 - t) * p0 + t * p1;
    cv::Point2f p11 = (1 - t) * p1 + t * p2;
    cv::Point2f p12 = (1 - t) * p2 + t * p3;

    //得到三个分割点连成的两条线段的两个分割点
    cv::Point2f p20 = (1 - t) * p10 + t * p11;
    cv::Point2f p21 = (1 - t) * p11 + t * p12;

    //得到两个分割点连成的一条线段的一个分割点
    cv::Point2f p30 = (1 - t) * p20 + t * p21;
    */

    //从上面的逐步分析可以直接推倒并简化成递归形式,具体算法如下:
   if(control_points.size() == 1){
       return control_points[0];
   }

    std::vector<cv::Point2f> myPoint;

    for (int i = 0; i < control_points.size() - 1;i++){
        myPoint.push_back((1 - t) * control_points[i] + t * control_points[i+1]);
    }
        //最后返回最后一条线段上的分割点
    return recursive_bezier(myPoint, t);
}

然后是bezier函数:

void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window) 
{
    // TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's
    // recursive Bezier algorithm.
    for (float i = 0; i < 1;i+=0.0001){
        cv::Point2f point = recursive_bezier(control_points, i);
        
        //因为PDF中要求将贝塞尔曲线绘制成绿色的,所以将RGB中的G通道设置成255
        window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
    }
}

注意,在调用我们自己写的bezier函数的时候需要,将main函数中的naive_bezier函数那行注释掉,加上我们自己的beizer函数调用。
调用naive_bezier函数的效果图如下:
请添加图片描述

调用beizer函数的效果图如下:
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值