GAMES101-Assignment4

一、问题总览

实现de Casteljau算法来绘制由4个控制点表示的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曲线上对应点的坐标。

二、参考答案

2.1 算法思想

De Casteljau 算法说明如下:

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

使用[0,1] 中的多个不同的t来执行上述算法

  • 例子如下
    在这里插入图片描述

    • b 0 b_0 b0, b 1 b_1 b1, b 2 b_2 b2为三个参考点;
      • b 0 b 1 b_0b_1 b0b1 上找一点 b 0 1 b_0^1 b01,使得 b 0 b 0 1 b_0b_0^1 b0b01 : b 0 1 b 1 b_0^1b_1 b01b1 = t : (1 - t)
      • b 1 1 b_1^1 b11 同理
    • b 0 1 b_0^1 b01 b 1 1 b_1^1 b11 作为新的参考点,找点 b 0 2 b_0^2 b02,使比例关系满足t : (1 - t)
    • b 0 2 b_0^2 b02 就是贝塞尔曲线上的一点,使用[0,1] 中的多个不同的t来执行上述算法

2.2 代码实现

2.2.1 Bezier函数的实现

  • t=0 -> t=1, 调用de Casteljau算法
//cv::Mat &window:表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数,RGB三通道,cv::Vec3b)
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(double t = 0.0; t < 1.0; t += 0.001){cv::Point2f point = recursive_bezier(control_points, t);// 绘制坐标(point.y, point.x)的颜色为绿色,[1]表示RGB中的Gwindow.at<cv::Vec3b>(point.y, point.x)[1] = 255;}
}

2.2.2 Recursive_bezier函数的实现

  • 实现de Casteljau 算法来返回Bézier曲线上对应点的坐标
//cv::Point2f  float类型的二维点坐标
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{// TODO: Implement de Casteljau's algorithmif(control_points.size() == 1) return control_points[0];std::vector<cv::Point2f> next_layer_control_points;for(int i = 0; i < control_points.size() - 1; i++){cv::Point2f p0 = control_points[i];cv::Point2f p1 = control_points[i+1];cv::Point2f p2 = p0 + t * (p1 - p0);next_layer_control_points.push_back(p2);}return recursive_bezier(next_layer_control_points, t);
}

2.2.3 实现对贝塞尔曲线的反走样(奖励分数)

  • 对于一个曲线上的点,不只把它对应于一个像
    素,需要根据到像素中心的距离来考虑与它相邻的像素的颜色
    在这里插入图片描述

    • P是贝塞尔曲线上t对应的一点,P0是周围四个像素区域的交点,像素框的中心点为其余四个黑点
    • 像素外框都是处于window矩阵整数部分(默认一个window单元格为一个像素),所以p所在的像素框的较近一竖边为min(floor(p.x), ceil(p.x)),横边min(floor(p.y), ceil(p.y))
      • 计算出p0坐标( min(floor(p.x), ceil(p.x)),min(floor(p.y), ceil(p.y)) )
    • 由于像素框大小为1 * 1,所以知道P0之后可以计算出周围四个像素中心点坐标
    • 根据像素中心点到P点的距离来分配颜色
      • 比如距离p点距离为dist,则该点所在像素的G通道 = 255 * (3 - dist)/3
        • 使用的是哈夫曼距离,p离像素中心点最大哈夫曼距离为3
double get_dist(cv::Point2f point1, cv::Point2f point2){//计算两点的哈夫曼距离return fabs(point1.x - point2.x) + fabs(point1.y - point2.y);
}//cv::Mat &window:表示屏幕矩阵;矩阵内元素为CV_8UC3类型(无符号8位整数,RGB三通道,cv::Vec3b)
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(double t = 0.0; t < 1.0; t += 0.001){cv::Point2f point = recursive_bezier(control_points, t);cv::Point2f point0( std::min(floor(point.x), ceil(point.x)), std::min(floor(point.y), ceil(point.y)) );double dist;std::vector<double> bias{0.5, -0.5};for(int i = 0; i < 4; i++){cv::Point2f centerPoint(point0.x + bias[i % 2], point0.y + bias[i % 2]);//计算中心点dist = get_dist(point, centerPoint);window.at<cv::Vec3b>(centerPoint.y, centerPoint.x)[1] = 255 * (3 - dist) / 3;} }
}

三、编译

如往常一样

$ mkdir build
$ cd build
$ cmake ..
$ make$ ./BezierCurve  

通过点击屏幕来设置控制点


附件

作业4连接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/608868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python采集微博评论做词云图

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境使用: Python 3.10 Pycharm 第三方模块使用: import requests >>> pip install requests import wordcloud >>> pip install wordclou…

扩展学习|数据融合助推商务智能与分析

文献来源&#xff1a;[1]李爱华,续维佳,石勇.基于数据融合的商务智能与分析架构研究[J].计算机科学,2022,49(12):185-194. 一、信息融合 &#xff08;一&#xff09;信息融合定义演变 早期信息融合的定义指出&#xff0c;其主要任务是综合分析若干传感器观测到的信息[9,…

请求参数乱码问题

POST请求方式解决乱码问题 在web.xml里面设置编码过滤器 <filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置过滤器中的属性值 -…

Python面试题(基础篇)

题目001: 在Python中如何实现单例模式。 点评&#xff1a;单例模式是指让一个类只能创建出唯一的实例&#xff0c;这个题目在面试中出现的频率极高&#xff0c;因为它考察的不仅仅是单例模式&#xff0c;更是对Python语言到底掌握到何种程度&#xff0c;建议大家用装饰器和元类…

微信小程序canvas画布实现矩形元素自由缩放、移动功能

获取画布信息并绘制背景 .whml <canvas class="canvas" type="2d" id="myCanvas" bindtouchstart="get_rect_touch_position" bindtouchmove="move_or_scale" bind:tap="finish_edit_check"/> .wxss .c…

【案例实战】业务稳定性运行之全链路混合压测

1.全链路压测开展步骤 &#xff08;1&#xff09;什么是全链路压测 全链路压测是指基于真实业务场景&#xff0c;通过模拟海量的用户请求&#xff0c;对整个后台服务进行压力测试&#xff0c;从而评估整个系统的性能水平。 对应用程序的整个技术栈进行完整的压力和性能测试&a…

DataFrame相关的API

目录 DataFrame的操作方案 SQL相关的API 创建一个视图/表 DSL相关的API DSL的传递方式 SQL的函数库 Spark SQL的综合应用 直接基于DataFrame来处理 SQL方式 DSL方式 基于RDD转换DataFrame的方式 DataFrame的操作方案 操作DataFrame一般有两种操作方案:一种为DSL方式,一种…

关于24年信息系统项目管理师论文如何提升?

信息系统项目管理师论文满分是75分&#xff0c;45分及以上为及格&#xff0c;论文评分可分为优良、及格与不及格3个档次。 评分的分数可分为&#xff1a; &#xff08;1&#xff09;60分至75分优良&#xff08;相当于百分制80分至100分&#xff09;。 &#xff08;2&#xf…

<设计模式> 七大原则

设计模式七大原则 开放封闭原则&#xff1a;对扩展开放&#xff0c;对修改关闭。这意味着在设计模式中&#xff0c;我们应该尽可能地将代码的扩展和修改分开处理&#xff0c;对于可以通过扩展来实现的功能&#xff0c;我们应该选择扩展代码&#xff0c;而对于必须修改现有代码…

数模学习day09-cftool使用

老版本的MATLAB可以在命令行使用cftool打开&#xff0c;2017a的版本可以直接找到。 x和y在你的工作区中需要已经存在&#xff0c;然后打开该工具箱就可以看见。 选择X和Y xy选择好之后就自动画好了拟合曲线。 Results分析 画好之后结果就呈现在这里了 这里的p1就是拟合系数&…

用React给XXL-JOB开发一个新皮肤(一):环境搭建和项目初始化

目录 一. 简述二. Fork 项目三. 搭建开发环境四. 初始化皮肤项目五. 添加相关依赖六. 预览 一. 简述 大名鼎鼎的 xxl-job 任务调度中心我们应该都使用过&#xff0c;项目地址&#xff1a;xxl-job。它是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单…

【代码随想录】刷题笔记Day48

前言 早上练车去了&#xff08;好久没有8点前醒了&#xff09;&#xff0c;练科目二两小时下来脚根可真酸啊&#xff0c;希望下周一把过。练完顺带去Apple西湖免费换新了耳机&#xff0c;羊毛爽&#xff01; 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09;…

JS逆向之无限debugger对抗

文章目录 JS中实现debugger的方法无限Debugger示例Demo1Demo2Demo3Demo4总结 无限Debugger实战 JS中实现debugger的方法 首先&#xff0c;我们要知道&#xff0c;在浏览器实现debugger的方法有哪些 debugger关键词 &#xff0c;相当于C内联汇编的int3&#xff0c;在代码中嵌入…

网工内推 | 运维工程师,国企、上市公司,RHCE认证优先

01 广东机场白云信息科技股份有限公司 招聘岗位&#xff1a;基础架构运维工程师&#xff08;中级&#xff09; 职责描述&#xff1a; 1、参与公司业务系统的监控、巡检、维护、故障定位、原因分析&#xff1b; 2、负责业务系统的上线、升级割接工作&#xff1b; 3、负责服务器…

Unity 踩坑记录 AnyState 切换动画执行两次

AnySate 切换动画 Can Transition To Self 将这个勾选去掉&#xff01;&#xff01;&#xff01;

C++ STL常用函数总结

一些总结&#xff0c;有错误欢迎指正&#xff01;&#xff01;&#xff01; 1 vector #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <vector>using namespace std;int main () {//vectorvector&l…

Python学习之路-Hello Python

Python学习之路-Hello Python Python解释器 简介 前面说到Python是解释型语言&#xff0c;Python解释器的作用就是用于"翻译"Python程序。Python规定了一个Python语法规则&#xff0c;根据该规则可编写Python解释器。 常见的Python解释器 CPython&#xff1a;官方…

文件或目录损坏的磁盘修复方法

文件或目录损坏是一种常见的计算机问题&#xff0c;可能由多种原因导致&#xff0c;如磁盘故障、病毒或恶意软件攻击、文件系统错误等。这些损坏可能导致数据丢失或无法访问文件&#xff0c;因此及时修复至关重要。本文将深入探讨文件或目录损坏的原因&#xff0c;并提供相应的…

试用统信服务器操作系统UOS 20

作者&#xff1a;田逸&#xff08;formyz&#xff09; 试用统信Linux操作系统UOS&#xff0c;想了解一下用已有的Linux经验能否轻松驾驭它。以便在某些场景下&#xff0c;可以多一种选择。本次试验在Proxmox VE 8&#xff08;以下简称PVE 8&#xff09;平台下进行&#xff0c;采…

唠一唠Java线程池

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天来聊聊Java线程池&#xff0c;如果没有线程池&#xff0c;每个线程都需要手动创建和销毁线程&#xff0c;那将是多么低效和耗资源啊&#xff01; 线程池的核心作用就是复用已创建的线程&#xff0c;减少…