GAMES101-计算机图形学-作业4

本文介绍了如何使用deCasteljau算法在OpenCV中实现Bézier曲线的绘制,包括递归贝塞尔函数的实现和控制点数量的灵活调整。通过实例演示了如何修改`bezier`和`recursive_bezier`函数来适应不同控制点数。
摘要由CSDN通过智能技术生成

要求:
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 曲线上对应点的坐标。
我这里自己写的是可以适用于任意个控制点数的方案,修改控制点数就在main里面的while循环里if (control_points.size() == 4) 和mouse_handler函数里的 if (event == cv::EVENT_LBUTTONDOWN && control_points.size() < 4) 里改一下数字就好。(这次的作业好简单

int fact(int n) {   //算阶乘
    return (n == 0 || n == 1) ? 1 : n * fact(n - 1);
}

cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{
    // TODO: Implement de Casteljau's algorithm
    int n = control_points.size();
    cv::Point2f point_t(0, 0);
    for (int i = 0; i < n; i++) {
        float num = fact(n - 1) / fact(i) / fact(n - 1 - i) * pow(t, i) * pow(1 - t, n - 1 - i);
        point_t += num * control_points[i];
    }
    return point_t;

}

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.
    int n = control_points.size();
    bool isAnitialiasing = true;
    for (double t = 0.0; t <= 1.0; t += 0.001) {
        if (!isAnitialiasing) { //不用反走样的版本,简单粗暴
            cv::Point2f point = recursive_bezier(control_points, t);
            window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
        }
        else {  //反走样
            // 对周边取四个像素点都进行距离的计算和插值
            auto dist = [&](float x, float y, float px, float py) {
                return sqrt(pow(x - px, 2) + pow(y - py, 2));
            };
            cv::Point2f point = recursive_bezier(control_points, t);
            float x_min = floor(point.x) + 0.5;
            float y_min = floor(point.y) + 0.5;
            float x_max = ceil(point.x) + 0.5;
            float y_max = ceil(point.y) + 0.5;

            float distanceCur = dist(point.x, point.y, x_min, y_min);
            if (distanceCur < 1 && window.at<cv::Vec3b>(x_min, y_min)[1] < distanceCur * 255)
                window.at<cv::Vec3b>(y_min, x_min)[1] = distanceCur * 255;

            distanceCur = dist(point.x, point.y, x_min, y_max);
            if (distanceCur < 1 && window.at<cv::Vec3b>(x_min, y_max)[1] < distanceCur * 255)
                window.at<cv::Vec3b>(y_max, x_min)[1] = distanceCur * 255;

            distanceCur = dist(point.x, point.y, x_max, y_min);
            if (distanceCur < 1 && window.at<cv::Vec3b>(x_max, y_min)[1] < distanceCur * 255)
                window.at<cv::Vec3b>(y_min, x_max)[1] = distanceCur * 255;

            distanceCur = dist(point.x, point.y, x_max, y_max);
            if (distanceCur < 1 && window.at<cv::Vec3b>(x_max, y_max)[1] < distanceCur * 255)
                window.at<cv::Vec3b>(y_max, x_max)[1] = distanceCur * 255;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值