目录

基本思想

有序边表思想

代码实现


基本思想

从图形的y最小值到y最大值依次进行y上的遍历,遍历的每个y=c这条直线称为扫描线。对于每条扫描线,多边形会和这条直线存在若干交点。这些交点中的之间的线段中某些是在多边形的内部,某些是在多边形的外部,且这种内外之分往往是间隔出现的。那么我们就将这些交点两两配对(保证配对两点之间的线段在多边形内部),然后对交点之间的部分进行绘制即可。易得水平线对于这个过程是没有什么意义的,所以在下面的所有分析中,水平线应当忽略不予考虑。

有序边表思想

这种算法的情况下,我们对于每一条扫描线都需要和所有的直线求交,这个过程计算较为复杂,且存在很多不必要的计算(例如上图中的3、4、5、6、7、8号直线和0号扫描线的求交运算就是不必要的)。那么对计算的简化就可以从增量计算以及非必要计算的减少两个方面去进行。可以通过有效边表算法达到上述两个方面的简化。
        这种算法的情况下,我们对于每一条扫描线都需要和所有的直线求交,这个过程计算较为复杂,且存在很多不必要的计算(例如上图中的3、4、5、6、7、8号直线和0号扫描线的求交运算就是不必要的)。那么对计算的简化就可以从增量计算以及非必要计算的减少两个方面去进行。可以通过有效边表算法达到上述两个方面的简化。
        首先,利用边表存储多边形所有边的有效信息。边表(NET)是一个存储每一扫描线处进行入考虑范围的变得信息的链表,大小等于扫描线范围大小。对于其中的每一项,存储下端点在标号+多边形y最小值的每一条边的信息,这些信息包含下端点x值,y增加1x增加的步长值m以及边上端点的ymax值。      
        基于以上静态边表,我们去遍历每一扫描线,进行动态的有效边表(AET)的维护。所谓有效边是指与当前扫描线有交点的边。对于每一扫描线,我们首先判断通过ymax参数当前边表中的边是否还有效,无效则从边表中删除,有效则完成x从与i-1号扫面线交点横坐标到与i号扫描线交点横坐标的转化,即x+=m。然后对于所有在NET[i]上挂着的所有从y最小值+i起始的边加入AET表,然后对AET表进行基于x值得排序。接下来进行AET表中x值的两两配对,对配对x之间的线段进行填充颜色的绘制即可。
        特别的,对于y方向上的极小值端点,由于x值会作为两台哦不同的边进入有效边表两次,所以不会产生配对上的错误。

代码实现

Edge类的内容(边表项):

class Edge
{
public: double x;   //当前x坐标int ymax;   //最上端y坐标double m;   //斜率倒数
};

NET的产生:

//静态边表NET的产生
std::vector<std::vector<Edge>>* setNET(const vetor<pair<int,int>>& pnts)
{int ymin = 0x3f3f3f3f, ymax = 0;int n = pnts.size();for (int i = 0; i < n; i++){if (pnts[i].second < ymin) ymin = pnts[i].second;if (pnts[i].second > ymax) ymax = pnts[i].second;}std::vector<std::vector<Edge>>& v = *new std::vector<std::vector<Edge>>(ymax - ymin + 1);for (int i = 1; i <= n; i++){double dx, dy;dx = pnts[i % n].first - pnts[i - 1].first;dy = pnts[i % n].second - pnts[i - 1].second;if (dy == 0) continue;Edge e;e.m = dx / dy;if (dy > 0){e.ymax = pnts[i % n].second - ymin;e.x = pnts[i - 1].first;v[pnts[i - 1].second - ymin].push_back(e);}else{e.ymax = pnts[i - 1].second - ymin;e.x = pnts[i % n].first;v[pnts[i % n].second - ymin].push_back(e);}}return &v;
}

AET的变化以及填充过程

bool EdgePointcmp(Edge a, Edge b)
{return a.x < b.x;
}void ScanLinePolygonFill(const vector<pair<int, int>>& pnts, unsigned long fillcolor)
{CClientDC dc(mView); //如果hDC为0时使用std::vector<std::vector<Edge>>NET = *setNET(pnts);int n = pnts.size();int ymin = 0x3f3f3f3f;for (int i = 0; i < n; i++)if (pnts[i].second < ymin) ymin = pnts[i].second;std::vector<Edge> AET;for (int i = 0; i < NET.size() - 1; i++){for (int j = 0; j < AET.size(); j++){if (AET[j].ymax <= i) AET.erase(AET.begin() + j--);else AET[j].x += AET[j].m;}AET.insert(AET.end(), NET[i].begin(), NET[i].end());std::sort(AET.begin(), AET.end(), EdgePointcmp);for (int k = 0; k < AET.size() - 1; k += 2){CPen pen(PS_SOLID, 1, fillcolor);CPen* pOldPen = dc.SelectObject(&pen);dc.MoveTo(AET[k].x + 2, ymin + i);dc.LineTo(AET[k + 1].x, ymin + i);dc.SelectObject(pOldPen);}}
}

计算机图形学--扫描线填充算法相关推荐

  1. 图形学扫描线填充算法

    在上图形学课的时候,学习了扫描线填充算法.不过在完成实验的时候在真正理解了该算法,在此记录一下,如果有表达上的错误,欢迎指正! 扫描线填充算法通过在与图形相交的第(1,2).(3,4)... 边之间划 ...

  2. c语言图形学扫描线填充算法,《计算机图形学》OpenGL实现扫描线填充算法

    顾名思义啊,就是在OpenGL中用扫描填充算法画一个稍微复杂的图形: #include #include #include #include #define COLOR_NEW 1.0,0.0,0.0 ...

  3. 多边形区域填充算法--扫描线填充算法(有序边表法)

    来源:https://blog.csdn.net/u013044116/article/details/49737585 二.扫描线算法(Scan-Line Filling) 扫描线算法适合对矢量图形 ...

  4. 计算机图形学之光线跟踪算法的研究与实现2017年我的优秀毕业论文

    计算机图形学之光线跟踪算法的研究与实现2017年我的优秀毕业论文 版权所有使用者请联系我 刘创 QQ:903188593 2.2.2 Phong光照模型 事实上对于漫反射的物体表面,使用Lambert ...

  5. 计算机图形学直线算法程序,计算机图形学直线生成算法实现.doc

    计算机图形学直线生成算法实现.doc (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 实验二直线生成算法实现班级08信计学号80姓名 ...

  6. 计算机图形学曲线算法代码,计算机图形学自由曲线绘制算法.doc

    计算机图形学自由曲线绘制算法 宁夏师范学院数学与计算机科学学院 <>实验报告 实验序号: 实验项目名称: 学 号姓 名专业.班实验地点指导教师时 间.实验内容与步骤 1 //TestVie ...

  7. 计算机图形学 ———— 扫描线多边形填充算法 (讲解)

    一.基本原理            扫描线多边形区域填充算法是按扫描线顺序(由下到上),计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作.                 ...

  8. 计算机图形学 -- 光栅图形学扫描线填充多边形[转]

    http://blog.sina.com.cn/s/blog_55a8a96d0100084k.html 研究如何用一种颜色或图案来填充一个二维区域.一般来说,区域的封闭轮廓是简单的多边形.若轮廓线由 ...

  9. 计算机图形学多边形填充代码_零基础学计算机图形学太难?或许你缺的只是一本好书...

    雷锋网 AI 科技评论按,计算机图形学是一个有趣的话题--如何利用算法和一些几何数据制作玩具总动员?这不仅对于普通的电影迷来说是一个神秘的话题,而且对于那些还没有接触过它的世界级工程师来说也非常有吸引 ...

最新文章

  1. 解读基于多传感器融合的卡尔曼滤波算法
  2. yii mysql 事务处理_Yii2中事务的使用实例代码详解
  3. 检查Java中的字符串是空还是空[重复]
  4. padding valid same区别——就是是否补齐0的问题
  5. SQL Server 表分区注意事项(转载)
  6. python编程和c语言编程的区别-C语言 python Java 等主要流行编程语言优劣对比
  7. SQL Server日期格式的转换
  8. 世界机器人大会进入最后一天,最受市民关注的是它!
  9. 详解@EnableEurekaServer和@EnableDiscoveryClient 或 @EnableEurekaClient注解
  10. HTML转义字符 Unicode和CSS伪类介绍
  11. 拼接符 防注入正则校验_Apache Kylin 命令注入漏洞调试分析(CVE-2020-1956)
  12. 拳王寻你项目公社:普通人怎么创业,普通人的创业法宝,容易上手的兼职副业项目
  13. C#模板引擎NVelocity实战项目演练
  14. Redis--安装与配置(Linux与Windows)
  15. (Oracle、SqlServer、Access)数据库开发代码生成工具SharpCode2.0
  16. 拓端tecdat|R语言进行相关矩阵分析及其网络可视化
  17. 中英文字体对照 ueditor添加字体
  18. php小型购物网站,PHP实现一个多功能购物网站
  19. 使用 Telnet 手动接收邮件 (基于 macOS 系统)
  20. 如何编写无法维护的代码,让自己稳拿铁饭碗

热门文章

  1. Linux 部署 nginx(下载、安装、启动)
  2. CDMA与OFDMA的比较
  3. 解决UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuation byte
  4. 一个更好的可视化微服务架构的方式
  5. 苹果数据泄漏:内鬼频出,这是库克的错吗?
  6. 《高质量程序设计指南——C/C++语言》之开篇记
  7. 前端jquery实现图片点击放大缩小
  8. 桂林山水甲天下,阳朔山水甲桂林
  9. 【Arduino学习笔记】使用L298N电机驱动模块驱动直流电机
  10. Delphi报表开发ReportMachine的小计和总计的计算