games 101 作业4

games 101 作业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 曲
    线

提升部分
实现对 Bézier 曲线的反走样。(对于一个曲线上的点,不只把它对应于一个像
素,你需要根据到像素中心的距离来考虑与它相邻的像素的颜色。)

题解

本次作业的难度适中,用递归的方式实现n次贝塞尔曲线。

根据算法说明以及贝塞尔函数的定义,实现如下算法:给定若干个点和t,返回这若干个控制点构成的贝塞尔曲线中t时刻的点。

cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{if (control_points.size() == 1)return control_points[0];std::vector<cv::Point2f> new_control_points;for (int i = 0; i < control_points.size() -1; i++){cv::Point2f p = t * control_points[i] + (1 - t) * control_points[i + 1];new_control_points.emplace_back(p);}return recursive_bezier(new_control_points,t);
}

然后t 从0到1,步进值可自定义,本代码中设置为0.001,也就是一条贝塞尔由1001个点组成,每个点的G通道设置为255,也就是线条颜色为绿色。

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 neighborXIndex[8] = { 0,1,0,-1,-1,1,-1,1};int neighborYIndex[8] = { 1,0,-1,0.1,1,-1,-1};for (double t = 0.0; t <= 1.0; t += 0.001){auto point = recursive_bezier(control_points,t);window.at<cv::Vec3b>(point.y, point.x)[1] = 255;}
}

提升:抗锯齿
根据点的位置到所在像素中心点距离,以及到相邻像素中心点的距离,计算相邻像素的颜色值。(可以是四邻或者八邻,下面以四邻距离说明)
在这里插入图片描述
假设当前像素Q点的颜色值为 c o l o r Q color_{Q} colorQ
则ABCD的颜色值分别为
c o l o r A = ∣ P Q ∣ / ∣ P A ∣ ∗ c o l o r Q color_{A}=|PQ|/|PA| * color_{Q} colorA=PQ∣/∣PAcolorQ
c o l o r B = ∣ P Q ∣ / ∣ P B ∣ ∗ c o l o r Q color_{B}=|PQ|/|PB| * color_{Q} colorB=PQ∣/∣PBcolorQ
c o l o r C = ∣ P Q ∣ / ∣ P C ∣ ∗ c o l o r Q color_{C}=|PQ|/|PC| * color_{Q} colorC=PQ∣/∣PCcolorQ
c o l o r D = ∣ P Q ∣ / ∣ P D ∣ ∗ c o l o r Q color_{D}=|PQ|/|PD| * color_{Q} colorD=PQ∣/∣PDcolorQ
代码如下:

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 neighborXIndex[4] = { 0,1,0,-1};int neighborYIndex[4] = { 1,0,-1,0};for (double t = 0.0; t <= 1.0; t += 0.001){auto point = recursive_bezier(control_points,t);window.at<cv::Vec3b>(point.y, point.x)[1] = 255;int x = point.x;int y = point.y;cv::Point2f p1(x + 0.5, y + 0.5);float d1 = std::sqrt(std::pow(point.x - p1.x, 2) + std::pow(point.y - p1.y, 2));for (int i = 0; i < 4; i++){cv::Point2f p(x+ neighborXIndex[i]*0.5,y+ neighborYIndex[i]*0.5);float d = std::sqrt(std::pow(point.x - p.x, 2) + std::pow(point.y - p.y, 2));window.at<cv::Vec3b>(y + neighborYIndex[i], x + neighborXIndex[i])[1] = d1 / d * 255;}}}

总结
贝塞尔函数的定义比较简单,n次贝塞尔的函数的定义公式如下:
B ( t ) = ∑ i = 0 n ( n i ) P i ( 1 − t ) n − i 1 t i B(t)=\sum_{i=0}^n\binom{n}{i} P_i(1-t)^{n-i_1} t^i B(t)=i=0n(in)Pi(1t)ni1ti
所以也可以不用递归,而是通过这个公式实现N次贝塞尔函数。
一条贝塞尔打断成两端贝塞尔,同时保持断点初过渡平滑,可以参考博文

作业答案

本次作业的答案放在的git仓库中:作业地址

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

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

相关文章

IntelliJ IDEA实用插件:轻松生成时序图和类图

IntelliJ IDEA生成时序图、类图 一、SequenceDiagram1.1 插件安装1.2 插件设置1.3 生成时序图 二、PlantUML Integration2.1 插件安装2.2 插件设置2.3 生成类图 在软件建模课程的学习中&#xff0c;大家学习过多种图形表示方法&#xff0c;这些图形主要用于软件产品设计。在传统…

解释Python中的多线程和多进程编程

在Python中&#xff0c;多线程&#xff08;Multithreading&#xff09;和多进程&#xff08;Multiprocessing&#xff09;是两种常见的并发编程技术&#xff0c;用于同时执行多个任务。然而&#xff0c;由于Python的全局解释器锁&#xff08;GIL&#xff0c;Global Interpreter…

C++实现定长内存池

项目介绍 本项目实现的是一个高并发的内存池&#xff0c;它的原型是Google的一个开源项目tcmalloc&#xff0c;tcmalloc全称Thread-Caching Malloc&#xff0c;即线程缓存的malloc&#xff0c;实现了高效的多线程内存管理&#xff0c;用于替换系统的内存分配相关函数malloc和fr…

文件压缩下载

工具类FileUtil import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream;/*** 文件工具类** author: 张…

Java面向对象知识总结+思维导图

&#x1f516;面向对象 &#x1f4d6; Java作为面向对象的编程语言&#xff0c;我们首先必须要了解类和对象的概念&#xff0c;本章的所有内容和知识都是围绕类和对象展开的&#xff01; ▐ 思维导图1 ▐ 类和对象的概念 • 简单来说&#xff0c;类就是对具有相同特征的一类事…

一篇文章学明白go语言,你想知道是那篇文章吗?

一篇文章彻底搞明白go语言&#xff0c; 你没有看错就是一篇文章可以让你彻底搞明白go语言&#xff0c;这篇文章就是go语言官方的 The Go Programming Language Specification &#xff0c; 你把这个搞明白&#xff0c;go语言也就明白了。 文章地址https://go.dev/ref/spec 这篇…

spring自定义初始化的加载顺序

构造函数>PostConstruct > afterPropertiesSet > init-method

MySQL——表内容的CURD操作

MySQL表内容的CURD ​ 与表内容相关的操作共有四种类型&#xff1a;Create(创建)&#xff0c;Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete(删除)&#xff1b; 一、Create 1.1单行插入多行插入全列插入/指定列插入 #全列插入&#xff0c;忽略列属性&#xff…

【Spring】认识 IoC 容器和 Servlet 容器

认识 IoC 容器和 Servlet 容器 1.认识容器1.1 IoC 容器1.2 loC 的实现方法1.2.1 依赖注入1.2.2 依赖查找 1.3 认识 Servlet 容器 2.用 IoC 管理 Bean2.1 创建一个 Bean2.2 编写 User 的配置类2.3 编写测试类 3.用 Servlet 处理请求3.1 注册 Servlet 类3.2 开启 Servlet 支持 1.…

力扣:1738. 找出第 K 大的异或坐标值

1738. 找出第 K 大的异或坐标值 给你一个二维矩阵 matrix 和一个整数 k &#xff0c;矩阵大小为 m x n 由非负整数组成。 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 < i < a < m 且 0 < j < b < n 的元素 matrix[i][j]&#xff08;下标从 0 开始计数&…

线程间通信和进程间通信

线程间通信 #include <iostream> #include <thread> #include <queue> #include <mutex> #include <condition_variable> #include <chrono>// 全局变量 std::queue<int> data_queue; std::mutex mtx; std::condition_variable cv_…

启动小程序F12窗口管理器

如何使用小程序F12任务窗口管理器教学流程 一、引言 小程序的开发者们&#xff0c;是否希望有一款工具能帮助你们更好地管理任务窗口&#xff1f; 二、前置准备 观看视频教程 访问B站视频链接&#xff1a;https://www.bilibili.com/video/BV1aa4y197UU/?spm_id_from333.9…

晶圆厂的PE转客户工程师前景怎么样?

知识星球&#xff08;星球名&#xff1a; 芯片制造与封测技术社区&#xff0c;星球号&#xff1a; 63559049&#xff09;里的学员问&#xff1a; 目前在晶圆厂做PE&#xff0c;倒班oncall压力太大把身体搞坏了&#xff0c;现在有一个design house的CE客户工程师的offer&…

java网络:过滤器修改请求头

目录 一、gateway的全局过滤器 二、web的OncePerRequestFilter以及常见过滤器Filter 三、过滤器排序 一、gateway的全局过滤器 Component Slf4j public class GatewayAuthFilter implements GlobalFilter, Ordered {Overridepublic Mono<Void> filter(ServerWebExchan…

跨境选品师不是神话:普通人也能轻松掌握,开启全球贸易新篇章!

随着互联网技术的飞速发展&#xff0c;跨境电商行业已成为全球经济的新增长点。在这个背景下&#xff0c;一个新兴的职业——跨境选品师&#xff0c;逐渐走进了人们的视野。那么&#xff0c;跨境选品师究竟是做什么的?普通人又该如何成为优秀的跨境选品师呢? 一、跨境选品师的…

ABAQUS应用07-实现拉伸和压缩刚度不同的弹簧建模

文章目录 0、背景描述1、步骤 0、背景描述 到目前为止&#xff0c;本文的内容我还没有具体实践过&#xff0c;但是个人认为后期是会用到的。比如说&#xff0c;对于风电机组地基转动刚度的设置&#xff0c;土体就是一种拉压刚度并不相同的材料。所以现在先记录下来&#xff0c…

Python——字典删除键值的方法

del dict[key] # 删除dict字典里的键值

如何用Java实现SpringCloud Alibaba Sentinel的熔断功能?

在Java中使用Spring Cloud Alibaba Sentinel实现熔断功能的步骤如下&#xff1a; 添加依赖 在项目的pom.xml文件中添加Spring Cloud Alibaba Sentinel的依赖&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud…

Java进阶学习笔记24——Object类

Object类: Object类是Java中所有类的祖宗类&#xff0c;因此&#xff0c;Java中所有类的对象都可以直接使用Object类中提供的一些方法。 所有类都是Object类的子孙类。 API文档&#xff1a; Object类的成员方法&#xff1a; Object类的常见方法&#xff1a; Student类&…

Arthas反编译与重新加载class

一、背景 因为其他研发部门同事给的产品jar包存在一个问题&#xff0c;就是http底层的超时时间默认为60s&#xff0c;但是最近调用外部接口同步数据&#xff0c;这个数据量太大导致超时超过60s&#xff0c;每次同步都不成功。但是客户目前对此情况特别不满意&#xff0c;需要紧…