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

十二:曲线边界区域的扫描线填充
        由于曲线边界的区域用非线性方程描述,其扫描线填充比多边形扫描线填充需要更多的时间。我们可以使用10节中的 通用方法 ,但边界交点计算用曲线方程完成。并且其边界的斜率不断地改变,因而不能直接使用直线段边可以使用的增量方法。

        对于像圆和椭圆这样的简单曲线,可以像凸多边形一样直接应用扫描线填充。每一条与圆或椭圆相交的扫描线仅有两个边界交点。我们可以使用中点方法中的增量计算来确定沿圆或椭圆边界的这两个交点。然后,简单地在一个交点到另一个之间的水平像素段内进行填充。利用四分象限区间(对于圆为八分象限)的对称性可以减少边界计算量。


         对于曲线段的填充区域可以使用类似的方法来生成。例如,一个椭圆弧和一直线段为边界的区域(参见图4.25)可以使用曲线和直线过程的混合方法来填充。只要可以减少计算量,就应充分利用对称性和增量计算。
        填充其他曲线区域可能需要更多的时间。我们可以使用类似的增量方法并与数值方法合来确定扫描线交点,但那样的曲线边界通常用直线段逼近。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用VC++6.0实现的扫描线填充,裁剪算法及画线方法 CPen pen(PS_SOLID,1,fillcolor); //设置扫描线所用笔的属性 CPen *old=pDC->SelectObject(&pen); int j,k,s=0; int p[9]; //每根扫描线交点 int pmin=1000; int pmax=0; for(int i=0;i<inLength;i++)//建立边表 { edge[i].dx=(float)(inVertexArray[i+1].x-inVertexArray[i].x)/(inVertexArray[i+1].y-inVertexArray[i].y); edge[i].num=i; if(inVertexArray[i].y<=inVertexArray[i+1].y) { edge[i].ymin=inVertexArray[i].y; edge[i].ymax=inVertexArray[i+1].y; edge[i].xmin=(float)inVertexArray[i].x; edge[i].xmax=(float)inVertexArray[i+1].x; } else{ edge[i].ymin=inVertexArray[i+1].y; edge[i].ymax=inVertexArray[i].y; edge[i].xmax=(float)inVertexArray[i].x; edge[i].xmin=(float)inVertexArray[i+1].x; } } //求多边形的最大最小值 for(int m=1;m<inLength;m++) { for(int n=0;n<inLength-m;n++) { if (pmax<inVertexArray[n].y) pmax = inVertexArray[n].y; if (pmin>inVertexArray[n].y) pmin=inVertexArray[n].y; } } for(int r=1;r<inLength;r++) //边表edge排序 { for(int q=0;q<inLength-r;q++) { if(edge[q].ymin<edge[q+1].ymin) { newedge[0]=edge[q]; edge[q]=edge[q+1]; edge[q+1]=newedge[0]; } } } for(int scan=pmax;scan>pmin;scan--) //扫描线遵守'“上开下闭”的原则 { int b=0; k=s; for(j=k;j<inLength;j++) { if((scan>=edge[j].ymin)&&(scan<=edge[j].ymax))//判断扫描线与线段是否相交于顶点 { int preNum = edge[j].num; int nextNum = edge[j].num+1; if (preNum==0) preNum = inLength - 1; else preNum = preNum -1; if (nextNum == inLength) nextNum = 0; if(scan==edge[j].ymax) //位于下顶点时,根据相临点的位置决定取几个点 { if(inVertexArray[nextNum].y<edge[j].ymax) { b++; p[b]=(int)edge[j].xmax; } if(inVertexArray[preNum].y<edge[j].ymax) { b++; p[b]=(int)edge[j].xmax; } } if(scan==edge[j].ymin) //位于上顶点时,取两个点 { b++; p[b]=(int)edge[j].xmin; b++; p[b]=(int)edge[j].xmin; } if((scan>edge[j].ymin)&&(scan<edge[j].ymax)) { b++; p[b]=(int)(edge[j].xmax+edge[j].dx*(scan-edge[j].ymax)); } } if(scan<edge[j].ymin) //建立新的活性边表 s=j; } if(b>1) { int tmpp = p[1]; for (int u = 1;u<=b;u++) //对交点排序 { for (int m = 1;m<=b-u;m++) { if (p[m]<p[m+1]) { tmpp = p[m]; p[m] = p[m+1]; p[m+1] = tmpp; } } } for(int n=1;n<b;n=n+2) { pDC->MoveTo(p[n],scan); pDC->LineTo(p[n+1],scan); } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值