http://blog.sina.com.cn/s/blog_55a8a96d0100084k.html

  研究如何用一种颜色或图案来填充一个二维区域。一般来说,区域的封闭轮廓是简单的多边形。若轮廓线由曲线构成,则可将曲线转换成多条直线段顺连而成,此时,区域轮廓线仍然是一种多边形逼近。
  在计算机图形学中,多边形区域有两种重要的表示方法:顶点表示和点阵表示。所谓顶点表示,即是用多边形的顶点序列来表示多边形。这种表示直观、几何意义强、占内存少、易于进行几何变换,但由于它没有明确指出哪些像素在多边形内,故不能直接用于区域填充。所谓点阵表示,则是用位于多边形内的像素集合来刻画多边形。这种表示丢失了许多几何信息,但便于进行填充。
  根据区域的定义,可以采用不同的填充算法,其中最具代表性的是:适用于顶点表示的扫描线类算法和适应于点阵表示的种子填充算法。
  扫描线来源于光栅显示器的显示原理:对于屏幕上所有待显示像素的信息,将这些信息按从上到下、自左至右的方式显示。因此,扫描线多边形区域填充算法的基本原理是,待填充区域按y方向(x方向亦可)扫描线顺序扫描生成。具体实现时,首先按扫描线顺序,计算扫描线与多边形的相交区间;再用指定的颜色填充这些区间内的像素,即完成这一条扫描线的填充工作。区间的端点可以通过计算扫描线与多边形边界的交点获得。
  为了提高效率,在处理每一条扫描线时,仅对与它相交的多边形的边进行求交运算。我们把当前扫描线相交的边称为活性边(active edge),并把它们按扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。
  为了提高速度,假定当前扫描线与多边形某一条边的交点的x坐标为xi,则下一条扫描线与该点的交点不需要重新计算,而是通过增加一个增量⊿x来获得。对于直线ax+by+c=0,⊿x=-b/a为常数。
  另外使用增量法计算时,还需要知道一条边何时不再与下一条扫描线相交,以便及时把它从活性边表中删除出去。因此,活性边表结点的数据结构应保存如下内容:第1项保存当前扫描线与边的交点坐标x值;第2项保存从当前扫描线到下一条扫描线间x的增量⊿x;第3项保存该边所交的最高扫描线好ymax。
  为了方便活性边表的建立与更新,可为每一条扫描线建立一个边表(ET),存放在该扫描线第一次出现的边。也就是说,若某边的较低端点为ymin,则该边就放在扫描线ymin的边表中。
算法过程如下:

void FillPolygon(多边形 polygon,int color)
{
for (各条扫描线,标示为i)
{
初始化边表头指针ET[i];
把ymin=i的边放入ET[i];
}
y=最低扫描线号;
初始化活性边表AET为空;
for (各条扫描线i)
{
把边表ET[i]中的边结点用插入排序法插入AET表,使之按x坐标递增顺序排列;
遍历AET表,把配对交点区间上的像素(x,y)填色;
遍历AET表,把ymax=i的结点从AET表中删除,并把ymax>i结点的x值递增⊿x;
若允许多边形的边自相交,则用冒泡排序法对AET表重新排序;
}
}

  扫描线与多边形顶点相交时,必须正确的进行交点个数计算,否则,在进行填充时会出现错误。扫描线与多边形相交的边分处扫描线的两侧,则计一个交点;扫描线与多边形相交的边分处扫描线同侧,且yi<y(i-1),yi<y(i+1),则计2个交点,若yi>y(i-1),yi>y(i+1),则计0个交点;扫描线与多边形边界重合,则计1个交点。

代码如下:

void FillPolygon(LPPOINT lpPoints,int nCount, CDC *pDC, int nColor) { // 检查参数合法性 ASSERT_VALID(pDC); ASSERT(lpPoints);//点 ASSERT(nCount>2);//点的数目 ASSERT(nColor>=0); // 边结构数据类型 typedef struct Edge{ int ymax; // 边的最大y坐标 double x; // 与当前扫描线的交点x坐标 double dx; // 边所在直线斜率的倒数,增量 struct Edge * pNext; // 指向下一条边 }Edge, * LPEdge; int i,j,k; int y0,y1; // 扫描线的最大和最小y坐标 LPEdge pAET; // 活化边表头指针 LPEdge * pET; // 边表头指针 pAET=new Edge; // 初始化表头指针,第一个结点不用 pAET->pNext=NULL; // 获取y方向扫描线边界,要求保证y0<y1 y0=y1=lpPoints[0].y; for(i=1;i<nCount;i++) { if(lpPoints[i].y<y0) y0=lpPoints[i].y; else if(lpPoints[i].y>y1) y1=lpPoints[i].y; } if(y0>=y1) return; // 这种情况下不需要填充,结束 // 初始化边表,第一个结点不用,这样可以保证pET[i]非空 pET=new LPEdge[y1-y0+1]; for(i=0;i<=y1-y0;i++) // 扫描线在[y0,y1]范围内,仅对这部分建立边表,pET[0]对应扫描线y0 { pET[i]= new Edge; pET[i]->pNext=NULL; } for(i=0;i<nCount;i++) { j=(i+1)%nCount; // 组成边的下一点,之所以这么写是因为最后一个点与第一个点相连 if(lpPoints[i].y != lpPoints[j].y)// 如果该边不是水平的则加入边表,同时保证增量的有意义 { LPEdge peg; // 指向该边的指针 LPEdge ppeg; // 指向边指针的指针 // 构造边 peg =new Edge; k=(lpPoints[i].y>lpPoints[j].y)?i:j; peg->ymax=lpPoints[k].y; // 该边最大y坐标 k=(k==j)?i:j; peg->x=(double)lpPoints[k].x; // 该边与扫描线焦点x坐标 peg->dx=(double)(lpPoints[i].x-lpPoints[j].x)/(lpPoints[i].y-lpPoints[j].y);// 该边斜率的倒数 peg->pNext=NULL; // 插入边 ppeg=pET[lpPoints[k].y-y0]; while(ppeg->pNext) ppeg=ppeg->pNext; ppeg->pNext=peg; }// end if }// end for i // 扫描 for(i=y0;i<=y1;i++) { LPEdge peg0=pET[i-y0]->pNext; LPEdge peg1=pET[i-y0]; if(peg0)// 有新边加入 { while(peg1->pNext) peg1=peg1->pNext; peg1->pNext=pAET->pNext; pAET->pNext=peg0; } // 按照x递增排序pAET peg0=pAET; while(peg0->pNext) { LPEdge pegmax=peg0; LPEdge peg1=peg0; LPEdge pegi=NULL; while(peg1->pNext) { if(peg1->pNext->x>pegmax->pNext->x) pegmax=peg1; peg1=peg1->pNext; } pegi=pegmax->pNext; pegmax->pNext=pegi->pNext; pegi->pNext=pAET->pNext; pAET->pNext=pegi; if(peg0 == pAET) peg0=pegi; } // 遍历活边表,画线 peg0=pAET; while(peg0->pNext!=NULL && peg0->pNext->pNext!=NULL) { // 画一条线段从(peg0->pNext->x,i)到(peg0->pNext->pNext->x,i) pDC->MoveTo((int)peg0->pNext->x,i); pDC->LineTo((int)peg0->pNext->pNext->x,i); peg0=peg0->pNext->pNext; } // 把ymax=i的节点从活边表删除并把每个节点的x值递增dx peg0=pAET; while(peg0->pNext) { if(peg0->pNext->ymax < i+2) { peg1=peg0->pNext; peg0->pNext=peg0->pNext->pNext; //删除 delete peg1; continue; } peg0->pNext->x+=peg0->pNext->dx; //把每个节点的x值递增dx peg0=peg0->pNext; } } // 删除边表 for(i=0;i<y1-y0;i++) if(pET[i]) delete pET[i]; if(pAET) delete pAET; if(pET) delete[] pET; }

转载于:https://www.cnblogs.com/begincsdn/archive/2012/08/08/2627727.html

计算机图形学 -- 光栅图形学扫描线填充多边形[转]相关推荐

  1. 扫描线填充多边形算法详解与代码

    扫描线填充多边形算法详解与代码 首先给出已知信息:多边形结构体里面包含三个信息:顶点个数,顶点和颜色 class MyPolygon {public:int m_VerticeNumber;CPoin ...

  2. 计算机图形学E5——OpenGL 扫描线填充

    其他计算机图形学实验见 链接 #include<iostream> #include<gl/glut.h> #include<algorithm> #include ...

  3. 计算机图形学--扫描线填充算法

    目录 基本思想 有序边表思想 代码实现 基本思想 从图形的y最小值到y最大值依次进行y上的遍历,遍历的每个y=c这条直线称为扫描线.对于每条扫描线,多边形会和这条直线存在若干交点.这些交点中的之间的线 ...

  4. 计算机图形学(三)_图元的属性_12_ 曲线边界区域的扫描线填充

    十二:曲线边界区域的扫描线填充         由于曲线边界的区域用非线性方程描述,其扫描线填充比多边形扫描线填充需要更多的时间.我们可以使用10节中的 通用方法 ,但边界交点计算用曲线方程完成.并且 ...

  5. 计算机图形学 第四章 光栅图形学

    第四章 光栅图形学 计算机图形学 第四章 光栅图形学的相关内容,包括:直线段的扫描转换算法.圆弧的扫描转换算法.多边形区域填充.字符的生成.裁剪.反走样 等 Def 光栅显示器:一个像素矩阵(因此,要 ...

  6. 【XJTUSE计算机图形学】第二章 光栅图形学(1)

    文章目录 [XJTUSE计算机图形学]第二章 光栅图形学(1) 1.基本概念 2.直线段的扫描转换算法 数值微分(DDA)法 增量算法 中点画线法[重点] Bresenham算法[重点 很有可能会考] ...

  7. 计算机图形学实验二交互式绘制多边形

    一.实验目的 掌握双缓冲绘图技术. (2)掌握人机交互技术. (3)掌握填充动态多边形的有效边表算法. 二.实验步骤 (1)在VS2017环境下创建MFC应用程序工程(单文档) (2)添加命令消息处理 ...

  8. 图形学基础笔记II:多边形光栅化算法和显卡三角形光栅算法

    为什么三角形就够了 实际对于 3D 来说肯定全是基于三角形的 geometry - OpenGL: Is it more efficient to use GL_QUADS or GL_TRIANGL ...

  9. c语言 连通域算法 递归,VC++ 6.0编写计算机图形学中的种子填充算法,想用递归的八向连通域,求助!...

    VC++ 6.0编写计算机图形学中的种子填充算法,想用递归的八向连通域,求助!0 填充函数代码如下: void CComputerGraphicsView::PolygonFill2()//区域填充函 ...

最新文章

  1. 在注意力中重新思考Softmax:分解非线性,这个线性transformer变体实现多项SOTA
  2. 远观近看阿里云ET平台 如何开启AI落地新风潮
  3. 使用antd报less的错误
  4. 消息中间件—RocketMQ的RPC通信(二
  5. 对比云备份:企业做出最佳选择
  6. Nginx与Serssion一致性问题
  7. 技术中台构建思路及进展_半年中台实践思考:落地中台,贵在其神,活用其形...
  8. 教你一行代码解决 Git报错 fatal refusing to merge unrelated histories
  9. MATLAB利用ode求解二阶微分方程
  10. Docker——Dockerfile构建镜像
  11. app用户注册、登录原理、注册页面
  12. 一个完整的研发体系应该包括的内容
  13. 中文模糊查找(C语言)+ 链表操作
  14. Factory Method
  15. Suspicious size this will make the view invisible, probably intended for layout_width
  16. Android内核开发 Goldfish Linux Kernel编译及安卓虚拟机测试
  17. 根据PPC反汇编代码分析堆栈内容
  18. mega raid linux,在lsi megaraid sas 8204elp 装linux系统(未完待续)
  19. 全国产品经理认证NPDP哪里比较不错?
  20. kinect体感互动解决方案:体感炫舞

热门文章

  1. 什么?内存不够了?进来教你malloc空间
  2. c++如何制作背景音乐
  3. Zemax光学设计(十二) —— 激光扫描物镜设计
  4. CG快报 2011.11.22
  5. python 股票竞价数据_GitHub - TruthHun/auction-stock: 集合竞价选股(股票),基于收盘价与前收盘价的选股策略...
  6. 对抗样本生成方法论文阅读笔记
  7. 小米2s android7.0秋大,老炮儿?小米2s升级MIUI 7流畅一逼!
  8. MySQL分配内存多少合适_mysql 如何分配内存
  9. 利用GPS定位[android]
  10. 机动车c1科三考试语言灯光,科目三灯光模拟考试内容、口诀、图解、技巧