头歌实践教学平台:CG2-v2.0-三角形填充

news/2024/9/24 14:23:10/

第1关:扫描线填充法

一. 任务描述

1. 本关任务

了解和掌握扫描线填充法,实现对三角形区域进行填充,具体要求如下: (1) 补全triangle函数; (2) 将main函数中的三角形顶点坐标和triangle函数参数补充完整。

2. 输入

(1) 三角形的三个顶点的坐标:
t0 = {125,50}, t1 = {300,200}, t2 ={200,350};
(2) 三角形区域为蓝色。

3. 输出

程序运行结果为一个蓝色三角形区域,如下图所示:

实验图片

二. 相关知识

1. 绘制点函数

image.set(x, y, color)函数用来绘制点,其中参数x,y为点的坐标,color为点的颜色。

2. 扫描线填充方法

如果想绘制一个三角形,最简单的方法是,对于三角形边界上每个点的y坐标,我们找到对应的左右两边界的X坐标y_left(A)和y_right(B) 从三角形的最低顶点开始,沿着你的方法一直到顶部,用扫描线法填充它。
为了简单起见,让我们将三角形分成上部和下部分:

实验图片

对于一个特定的y,如果我们想找到它的左右点A和B,思路是这样的:
首先排序,保证 t0 ≤ t1 ≤ t2; 整个三角形的y坐标高度为 t2.y - t0.y; 对于下半部分,y每增加1点(有可能t0 == t1)我们就用插值来求出对应的点A和点B。 扫描线算法的部分示意代码如下,其中Vec2i是定义一个点的x和y坐标的结构体,参数t0, t1, t2对应三角形的三个顶点坐标:

 
  1. void triangle(Vec2i t0, Vec2i t1, Vec2i t2) {
  2. // sort the vertices, t0, t1, t2 lower−to−upper
  3. if (t0.y>t1.y) std::swap(t0, t1);
  4. if (t0.y>t2.y) std::swap(t0, t2);
  5. if (t1.y>t2.y) std::swap(t1, t2);
  6. int total_height = t2.y-t0.y;
  7. //lower parts
  8. for (int y=t0.y; y<=t1.y; y++) {
  9. int segment_height = t1.y-t0.y+1; //be careful with divisions by zero
  10. float alpha = (float)(y-t0.y)/total_height; //edge t0t2
  11. float beta = (float)(y-t0.y)/segment_height; //edge t0t1
  12. Vec2i A,B;
  13. A.y=B.y=y;
  14. A.x = t0.x + (t2.x-t0.x)*alpha;
  15. B.x = t0.x + (t1.x-t0.x)*beta;
  16. if (A.x>B.x) std::swap(A.x, B.x);
  17. for (int x=A.x; x<=B.x; x++) {
  18. image.set(x, y, color);
  19. }
  20. }
  21. //upper parts
  22. for (int y = t1.y; y <= t2.y; y++){
  23. ... //Please refer to the above code to program
  24. ...
  25. }
  26. }

三. 操作说明

(1) 按要求补全代码; (2) 点击窗口右下角"测评"按钮,等待测评结果,如果通过后可进行下一关任务。


开始你的任务吧,祝你成功!

四、实验代码

#include "pngimage.h"
#include<stdio.h>
#include <iostream>struct Vec2i
{int x, y;
};void triangle(Vec2i t0, Vec2i t1, Vec2i t2, PNGImage&  image, PNGColor color) {// Please add your code here/********** Begin ********///根据三个顶点y坐标大小,保证t0.y <= t1.y <= t2.y,这样确定好分为上下部分//根据图可以知道为右三角形 if (t0.y>t1.y) std::swap(t0, t1);if (t0.y>t2.y) std::swap(t0, t2); if (t1.y>t2.y) std::swap(t1, t2); int tH = t2.y-t0.y;//总共的高度为最高点y坐标减最低点y坐标 for (int y=t0.y; y<=t1.y; y++)//下部分扫描 { int xsH = t1.y-t0.y+1;//下部分高度    float a = (float)(y-t0.y)/tH;//a为从t0.y到当前行之间的比例,y不断变化下移//b为从t0.y到当前行之间的比例       float b  = (float)(y-t0.y)/xsH;    Vec2i A,B;A.y=B.y=y;A.x = t0.x + (t2.x-t0.x)*a,B.x = t0.x + (t1.x-t0.x)*b;// 计算A点的横坐标//计算B点的横坐标if (A.x>B.x) std::swap(A.x, B.x);//确保B点在A点右边,即B点横坐标大于A点横坐标 for (int x=A.x; x<=B.x; x++) { image.set(x, y, color);//指定位置的指定颜色函数  } } 
for (int y=t1.y; y<=t2.y; y++)//上部分扫描 
{ int ssH = t2.y-t1.y+1;//上部分高度    float a = (float)(y-t0.y)/tH;//a为从t0.y到当前行之间的比例,y不断变化下移      float b  = (float)(y-t1.y)/ssH;//b为从t1.y到当前行之间的比例    Vec2i A,B;A.y=B.y=y;A.x = t0.x + (t2.x-t0.x)*a,B.x = t1.x + (t2.x-t1.x)*b;// 计算A点的横坐标//计算B点的横坐标 if (A.x>B.x) std::swap(A.x, B.x);//确保B点在A点右边,即B点横坐标大于A点横坐标 for (int x=A.x; x<=B.x; x++) { image.set(x, y, color);//指定位置的指定颜色函数  } } /********** End **********/
}int main(int argc, char** argv) {PNGColor white = PNGColor(255, 255, 255, 255);PNGColor black = PNGColor(0, 0, 0, 255);PNGColor red = PNGColor(255, 0, 0, 255);PNGColor blue = PNGColor(0, 255, 255, 255);int width = 400;int height = 400;PNGImage image(width, height, PNGImage::RGBA); //Error when RGB because lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size() in encodeimage.init(black);// Please add your code here/********** Begin ********/Vec2i t0 = {125 , 50}, t1 = { 300,200 }, t2 = {200 ,350 };triangle(t0,t1,t2,image,PNGColor(0,255,255,255));/********** End **********/image.flip_vertically(); // i want to have the origin at the left bottom corner of the imageimage.write_png_file("../img_step3/test.png");return 0;
}


http://www.ppmy.cn/news/1456356.html

相关文章

DDR5内存新标准问世,体验前所未有的数据传输速度

DDR 5&#xff0c;新标准发布 JEDEC 发布了 JESD79-5C DDR5 SDRAM 标准&#xff0c;带来了关键更新&#xff0c;包括&#xff1a;* 增强可靠性和安全性* 优化高性能服务器和新兴技术&#xff08;如 AI 和机器学习&#xff09;的性能* 标准可从 JEDEC 网站下载 JESD79-5C 引入每…

视频剪辑神器:批量高效处理,轻松锐化视频让影片焕然一新!

视频已经成为我们记录生活、分享故事、展示才华的重要形式。然而&#xff0c;面对大量的视频文件&#xff0c;如何批量高效剪辑并提升视频质量&#xff0c;成为了许多人的难题。现在&#xff0c;我们为您带来一款视频剪辑神器&#xff0c;让您轻松处理视频&#xff0c;让您的影…

Oracle Database 23ai Free RPM Installation On Oracle Linux 8 (OL8)

Oracle刚刚发布了最新的Oracle database 23ai版本测试安装包&#xff0c;有兴趣的小伙伴可以安装体验一下。 关于安装的介质可以去如下地址下载&#xff1a; Oracle linux 8.9 Oracle Linux ISOs | Oracle, Software. Hardware. Complete. Oracle database 23ai安装包 Get Star…

深入解析C#中的async和await关键字

文章目录 一、异步编程的基本概念及其在C#中的实现二、async关键字的定义及其用法三、await关键字的定义及其用法示例代码&#xff1a;使用async和await编写一个简单的异步程序 四、async和await的优点注意事项 五、C#下async和await中常见问题汇总1. 异步方法中的await调用2. …

ZCC5503 18V 1A 6uA低静态功耗 同步降压控制器

1. 概要 ZCC5503R 是一款基准电压源、振荡电路、 比较器 PWM/PFM 控制器构成的 CMOS 降压电路调整器&#xff0c;利用 PWM/PFM 自动切换控制电路达到可调占空比&#xff0c;具有全输入电压范围&#xff08;3~18V &#xff09;内的低纹波、高效率及大电流输出等特点. 2. 产…

白酒:白酒香型的国际化推广与市场接受度分析

云仓酒庄的豪迈白酒一直有在白酒香型的国际化推广。随着中国白酒市场的不断扩大和国际化的趋势&#xff0c;了解白酒香型的国际接受度和推广策略对于酒厂和整个行业都具有重要意义。 首先&#xff0c;国际化推广需要深入了解国际市场的需求和消费者偏好。不同国家和地区的消费者…

秋招后端开发面试题 - MySQL基础

目录 MySQL基础前言面试题MySQL 基础篇Mysql 的基础架构&#xff1f;MySQL 的长连接和短连接长连接引起的异常重启问题&#xff1f;说一下 MySQL 执行一条查询语句的内部执行过程&#xff1f;MySQL 查询缓存的功能有何优缺点&#xff1f;MySQL 的常用引擎都有哪些&#xff1f;I…

GO日志打印添加goroutineid

今天想给日志添加一个前缀&#xff0c;以区分不同goroutine的日志&#xff0c;方便做并发问题的排查&#xff0c;做日志跟踪。 为了解决goroutineid&#xff0c;网上各出奇招&#xff0c;有的使用runtime包未公开的方法获取&#xff1a; func Goid() int {defer func() {if e…