【计算机图形学】实验二 用扫描线算法实现多边形填充

🕺作者: 主页

我的专栏
C语言从0到1
探秘C++
数据结构从0到1
探秘Linux

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢支持!!!

文章目录

  • 实验二、用扫描线算法实现多边形填充
    • 一、实验目的及要求
    • 二、实验设备
    • 三、实验原理
    • 四、实验方法与步骤
    • 五、实验结果
    • 六、结论

实验二、用扫描线算法实现多边形填充

一、实验目的及要求

本实验旨在掌握扫描线算法的原理和实现方法,通过编写程序实现多边形的填充。

二、实验设备

  • Microsoft Visual Studio 2022

三、实验原理

扫描线算法是一种用于填充多边形的算法,其基本思想是将多边形分解成若干个梯形区域,然后对每个梯形区域进行填充。在填充时,扫描线从上往下扫描,逐个像素点地判断当前点是否位于多边形内部,并根据需要进行颜色填充。

四、实验方法与步骤

  1. 算法思想

扫描线填充算法是一种计算机图形学中用于实现多边形填充的算法。它基于对多边形的扫描线进行处理,将多边形分割成一系列水平线段,并确定每条线段覆盖的像素点是否在多边形内部,从而实现多边形的填充。

  1. 算法步骤
  • 定义多边形数据结构,存储多边形的顶点信息。
  • 根据多边形的顶点信息,计算出多边形每条边的斜率和截距等信息,并存储在一个表格中。
  • 从多边形最高点开始,以每行像素点为单位,向下扫描直到最低点。
  • 对于每个扫描线,遍历保存边信息的表格,计算出当前扫描线和各条边的交点,将这些交点按照x坐标大小排序并两两配对。
  • 对每一对交点之间的像素点进行填充。
  • 重复以上步骤,直到扫描线扫描完成。
  1. 代码
// 多边形数据结构
struct Polygon {int numVertices; // 多边形顶点数int vertices[100][2]; // 多边形顶点坐标
};// 边数据结构
struct Edge {double x; // 边与扫描线的交点x坐标double slope; // 边斜率倒数int ymax; // 边在扫描线之上的端点y坐标
};// 填充多边形
void FillPolygon(Polygon poly) {// 计算多边形顶点中的最大和最小y坐标int maxY = INT_MIN, minY = INT_MAX;for (int i = 0; i < poly.numVertices; i++) {if (poly.vertices[i][1] > maxY) {maxY = poly.vertices[i][1];}if (poly.vertices[i][1] < minY) {minY = poly.vertices[i][1];}}// 创建边表,存储所有的边信息vector<Edge> edgeTable;for (int i = 0; i < poly.numVertices; i++) {Edge e;// 获取当前边和下一个顶点的坐标int x1 = poly.vertices[i][0], y1 = poly.vertices[i][1];int x2 = poly.vertices[(i + 1) % poly.numVertices][0], y2 = poly.vertices[(i + 1) % poly.numVertices][1];// 如果y1 == y2,说明该边不需要加入边表if (y1 == y2) {continue;}// 如果y2 < y1,则交换两个顶点的坐标if (y2 < y1) {swap(x1, x2);swap(y1, y2);}// 计算出边与扫描线的交点x坐标和斜率倒数e.x = x1;e.slope = (double)(x2 - x1) / (y2 - y1);e.ymax = y2 - 1;// 将边加入边表中edgeTable.push_back(e);}// 对边表按照交点x坐标排序sort(edgeTable.begin(), edgeTable.end(), [](const Edge& a, const Edge& b) { return a.x < b.x; });// 创建活动边表,存储所有与当前扫描线有交点的边信息vector<Edge> activeEdgeTable;// 从多边形最高点开始,逐行扫描for (int y = maxY; y >= minY; y--) {// 将与当前扫描线有交点的边加入活动边表中for (int i = 0; i < edgeTable.size(); i++) {if (edgeTable[i].ymax >= y) {activeEdgeTable.push_back(edgeTable[i]);}}// 按照交点x坐标排序sort(activeEdgeTable.begin(), activeEdgeTable.end(), [](const Edge& a, const Edge& b) { return a.x < b.x; });// 填充扫描线int x1 = INT_MAX, x2 = INT_MIN;for (int i = 0; i < activeEdgeTable.size(); i += 2) {x1 = (int)ceil(activeEdgeTable[i].x);x2 = (int)floor(activeEdgeTable[i + 1].x);// 如果是偶数条边,则说明有完整的矩形区域需要填充if (i + 1 < activeEdgeTable.size()) {for (int x = x1; x <= x2; x++) {SetPixel(x, y);}}}// 更新活动边表for (int i = 0; i < activeEdgeTable.size(); i++) {activeEdgeTable[i].x += activeEdgeTable[i].slope;activeEdgeTable[i].ymax--;}// 从活动边表中移除不再与扫描线相交的边activeEdgeTable.erase(remove_if(activeEdgeTable.begin(), activeEdgeTable.end(), [](const Edge& a) { return a.ymax <= 0; }), activeEdgeTable.end());}
}

五、实验结果

  1. 扫描填充算法运行结果

image.png

六、结论

本实验是通过扫描线算法来实现多边形的填充。首先定义了多边形和边的数据结构,并且根据多边形的顶点信息计算出每条边的斜率和截距等信息,存储在一个表格中。然后从多边形最高点开始,以每行像素点为单位,向下扫描直到最低点。对于每个扫描线,遍历保存边信息的表格,计算出当前扫描线和各条边的交点,将这些交点按照x坐标大小排序并两两配对,然后对每一对交点之间的像素点进行填充。最后重复以上步骤,直到扫描线扫描完成。这种算法的优势在于可以处理任意形状的多边形,而不仅限于凸多边形。算法的时间复杂度为O(nlogn),其中n为多边形的边数。本次实验的结果是成功实现了多边形的填充。

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

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

相关文章

9.SELinux

目录 1. 概述 1.1. 概念 1.2. 作用&#xff1a; 1.3. SELinux与传统的权限区别 2. SELinux工作原理 2.1. 名词解释 2.1.1. 主体&#xff08;Subject&#xff09; 2.1.2. 目标&#xff08;Object&#xff09; 2.1.3. 策略&#xff08;Policy&#xff09; 2.1.4. 安全上…

详解Redis哨兵模式下,主节点掉线而重新选取主节点的流程

⭐最核心的结论&#xff1a;所谓选举的过程不是直接选出新的主节点&#xff0c;而是先在哨兵节点中选出 leader &#xff0c;再由 leader 负责后续主节点的指定。 假定当前环境&#xff1a; 三个哨兵(sentenal1, sentenal2, sentenal3)一个主节点(redis-master)两个从节点(red…

接口测试框架对比

公司计划系统的开展接口自动化测试&#xff0c;需要我这边调研一下主流的接口测试框架给后端测试&#xff08;主要测试接口&#xff09;的同事介绍一下每个框架的特定和使用方式。后端同事根据他们接口的特点提出一下需求&#xff0c;看哪个框架更适合我们。 需求 1、接口编写…

端到端实现高精地图重建(TopoNet解读和横评)

论文出处 [2304.05277] Graph-based Topology Reasoning for Driving Scenes (arxiv.org)https://arxiv.org/abs/2304.05277 TopoNet TopoNet的目标是从车辆上安装的多视角摄像头获取图像&#xff0c;感知实体并推理出驾驶场景的拓扑关系&#xff0c;实现端到端预测&#xf…

【自动化测试】----Java的单元测试工具Junit5

目录 支持Java的最低版本为8在pom.xml添加依赖Junit提供的注解功能 断言 Assertion类提供的一些方法测试用例执行顺序 &#xff08;为了预防测试用例执行顺序错误&#xff09;参数化 &#xff08;假设登陆操作&#xff0c;用户名和密码很多&#xff0c;尽可能通过一个测试用例…

Java多线程--JDK5.0新增线程创建方式

文章目录 一、新增方式1&#xff1a;实现Callable接口&#xff08;1&#xff09;介绍&#xff08;2&#xff09;案例&#xff08;3&#xff09;总结对比 二、新增方式2&#xff1a;使用线程池&#xff08;1&#xff09;问题与解决思路1、现有问题2、解决思路3、好处 &#xff0…

Swift Vapor 教程(查询数据、插入数据)

上一篇简单写了 怎么创建 Swift Vapor 项目以及在开发过程中使用到的软件。 这一篇写一个怎么在创建的项目中创建一个简单的查询数据和插入数据。 注&#xff1a;数据库配置比较重要 先将本地的Docker启动起来&#xff0c;用Docker管理数据库 将项目自己创建的Todo相关的都删掉…

以小猪o2o生活通v17.1为例简要分析SWOOLE加密破解,swoole_loader加密破解swoole加密逆向后的代码修复流程(个人见解高手掠过)

现在用Php加密五花八门除了组件就是混淆&#xff0c;在组件里面响当当的还属swoole&#xff0c;SWOOLEC是不错的国产加密&#xff0c;值得推荐官方宣称是永远无法破解的加密算法&#xff0c;针对swoole compiler的代码修复我谈谈我的看法&#xff0c;以小猪o2o生活通&#xff0…

PyTorch 2.2 中文官方教程(十九)

使用 RPC 进行分布式管道并行 原文&#xff1a;pytorch.org/tutorials/intermediate/dist_pipeline_parallel_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Shen Li 注意 在github中查看并编辑本教程。 先决条件&#xff1a; PyTorc…

04-Java建造者模式 ( Builder Pattern )

建造者模式 摘要实现范例 建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象 一个Builder 类会一步一步构造最终的对象&#xff0c;该 Builder 类是独立于其他对象的 建造者模式属于创建型模式&#xff0c;它提供了一种创建对…

深度学习手写字符识别:训练模型

说明 本篇博客主要是跟着B站中国计量大学杨老师的视频实战深度学习手写字符识别。 第一个深度学习实例手写字符识别 深度学习环境配置 可以参考下篇博客&#xff0c;网上也有很多教程&#xff0c;很容易搭建好深度学习的环境。 Windows11搭建GPU版本PyTorch环境详细过程 数…

vcruntime140.dll最新的修复方法,一键修复vcruntime140.dll的手段

在这篇文章中&#xff0c;我们将深入探讨并详细介绍各种修复vcruntime140.dll文件缺失或损坏问题的方法。鉴于此类问题广泛存在并影响了众多用户&#xff0c;本文目的是向大家展示不同的修复策略&#xff0c;希望能够帮助每个人解决这些棘手的技术难题。下面一起来看看vcruntim…

【RT-DETR有效改进】UNetv2提出的一种SDI多层次特征融合模块(细节高效涨点)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本问给大家带来的改进机制是UNetv2提出的一种多层次特征融合模块(SDI)其是一种用于替换Concat操作的模块,SDI模块的主要思想是通过整合编码器生成的层级特征图来增强图像中的语义信息和细节信息。包括皮肤…

黑豹程序员-ElementPlus选择图标器

ElementPlus组件提供了很多图标svg 如何在你的系统中&#xff0c;用户可以使用呢&#xff1f; 这就是图标器&#xff0c;去调用ElementPlus的icon组件库&#xff0c;展示到页面&#xff0c;用户选择&#xff0c;返回选择的组件名称。 效果 代码 <template><el-inpu…

机器学习 - 梯度下降

场景 上一章学习了代价函数&#xff0c;在机器学习中&#xff0c;代价模型是用于衡量模型预测值与真实值之间的差异的函数。它是优化算法的核心&#xff0c;目标是通过调整模型的参数来最小化代价模型的值&#xff0c;从而使模型的预测结果更接近真实值。常见的代价模型是均方…

【Boost】:searcher的建立(四)

searcher的建立 一.初始化二.搜索功能三.完整源代码 sercher主要分为两部分&#xff1a;初始化和查找。 一.初始化 初始化分为两步&#xff1a;1.创建Index对象&#xff1b;2.建立索引 二.搜索功能 搜索分为四个步骤 分词&#xff1b;触发&#xff1a;根据分词找到对应的文档…

架构设计特训

一、考点分布 软件架构风格&#xff08;※※※※&#xff09;层次型软件架构风格&#xff08;※※※※&#xff09;面向服务的软件架构风格&#xff08;※※※※&#xff09;云原生架构风格&#xff08;※※※※&#xff09;质量属性与架构评估&#xff08;※※※※※&#xff…

Transformer实战-系列教程1:Transformer算法解读1

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 Transformer实战-系列教程1&#xff1a;Transformer算法解读1 Transformer实战-系列教程2&#xff1a;Transformer算法解读2 现在最火的AI内容&#xff0c;chatGPT、视觉大模…

Golang切片与数组

在Go语言中&#xff0c;切片&#xff08;Slice&#xff09;和数组&#xff08;Array&#xff09;是两个核心的数据结构&#xff0c;它们在内存管理、灵活性以及性能方面有着显著的区别。接下来将解析Golang中的切片与数组&#xff0c;通过清晰的概念解释、案例代码和实际应用场…

小林Coding_操作系统_读书笔记

一、硬件结构 1. CPU是如何执行的 冯诺依曼模型&#xff1a;中央处理器&#xff08;CPU&#xff09;、内存、输入设备、输出设备、总线 CPU中&#xff1a;寄存器&#xff08;程序计数器、通用暂存器、指令暂存器&#xff09;&#xff0c;控制单元&#xff08;控制CPU工作&am…