/// private v" />
当前位置:文档之家› 区域填充算法运行代码

区域填充算法运行代码

///<summary>///扫描线填充算法填充触发事件///</summary>///<param name="sender"></param>///<param name="e"></param>private void scanLineFillingToolStripMenuItem_Click(object sender, EventArgs e) {slf.ScanLinePolygonFill(P,g,XiangSu);}private void label2_Click(object sender, EventArgs e){}private void四联通填充ToolStripMenuItem_Click(object sender, EventArgs e){tempp.X = tempP[3].X + XiangSu;//选取第4个点内侧(随机猜测)tempp.Y = tempP[3].Y + XiangSu;checkBox.Enabled = false;//让绘制过程中不能改变选择do_check();//也要检查一遍,不然会出现错误FloodSeedFill(tempp);checkBox.Enabled = true;//恢复}///<summary>///初始化新边表///算法通过遍历所有的顶点获得边的信息,然后根据与此边有关的前后两个顶点的情况///确定此边的ymax是否需要-1修正。

ps和pe分别是当前处理边的起点和终点,pss是起///点的前一个相邻点,pee是终点的后一个相邻点,pss和pee用于辅助判断ps和pe两个///点是否是左顶点或右顶点,然后根据判断结果对此边的ymax进行-1修正,算法实现非///常简单,注意与扫描线平行的边是不处理的,因为水平边直接在HorizonEdgeFill()///函数中填充了。

///</summary>private void InitScanLineNewEdgeTable(List<EDGE>[] NET, List<Point> Q, int ymin, int ymax){List<int> temp = new List<int>();EDGE e;for (int i = 0; i < Q.Count; i++){Point ps = Q[i];Point pe = Q[(i + 1) % Q.Count];Point pss = Q[(i - 1 + Q.Count) % Q.Count];Point pee = Q[(i + 2) % Q.Count];if (pe.Y != ps.Y)//不处理平行线{e = new EDGE();e.dx = (double)(pe.X - ps.X) / (double)(pe.Y - ps.Y) * XiangSu;if (pe.Y > ps.Y){e.xi = ps.X;if (pee.Y >= pe.Y)e.ymax = pe.Y - XiangSu;elsee.ymax = pe.Y;NET[ps.Y - ymin].Add(e);//加入对应的NET里temp.Add(ps.Y - ymin);}else{e.xi = pe.X;if (pss.Y >= ps.Y)e.ymax = ps.Y - XiangSu;elsee.ymax = ps.Y;NET[pe.Y - ymin].Add(e);//加入对应的NET里temp.Add(pe.Y - ymin);}}}for (int i = 0; i < temp.Count; i++){My_Sort(ref NET[temp[i]]);}}private void My_Sort(ref List<EDGE> list){EDGE d = new EDGE();for (int i = 0; i < list.Count-1; i++){for(int j = i + 1; j < list.Count; j++)//瞎!for (int j = i+1; i < list.Count; i++){if (list[j] < list[i]){d = list[j];list[j] = list[i];list[i] = d;}}}}///<summary>///水平边直接画线填充///</summary>///<param name="Q"></param>private void HorizonEdgeFill(List<Point> Q){}///<summary>///扫描线填充处理过程///开始对每条扫描线进行处理,对每条扫描线的处理有四个操作///</summary>///<param name="NET"></param>///<param name="ymin"></param>///<param name="ymax"></param>private void ProcessScanLineFill(List<EDGE>[] NET, int ymin, int ymax){List<EDGE> AET=new List<EDGE>();//扫描线for (int y = ymin; y < ymax; y+=XiangSu){#region显示运算信息InsertNetListToAet(NET[y-ymin], ref AET);#endregionFillAetScanLine(ref AET, y);RemoveNonActiveEdgeFromAet(ref AET, y);//删除非活动边UpdateAndResortAet(ref AET);//更新活动边表中每项的xi值,并根据xi重新排序}}///<summary>///负责将扫描线对应的所有新边插入到aet中,插入操作到保证AET///还是有序表,插入排序的思想///</summary>///<param name="list"></param>///<param name="AET"></param>private void InsertNetListToAet(List<EDGE> list, ref List<EDGE> AET){if (list.Count == 0) return;if (AET.Count == 0){AET = list;return;}//刚开始这里写成if()AET=list;return;一直出错!下次一定要规范!!!List<EDGE> temp = new List<EDGE>();int i = 0, j = 0;while (i < list.Count && j < AET.Count){if (list[i] == AET[j]){i++;temp.Add(AET[j]);j++;continue;}if (list[i] < AET[j]){temp.Add(list[i]);i++;continue;}if (list[i] > AET[j]){temp.Add(AET[j]);j++;continue;}}while (i < list.Count){temp.Add(list[i]);i++;}while (j < AET.Count){temp.Add(AET[j]);j++;}AET = temp;//for (int i = 0; i < list.Count; i++)//{// AET.Add(list[i]);//}//My_Sort(ref AET);}///<summary>/// FillAetScanLine()函数执行具体的填充动作,///它将aet中的边交点成对取出组成填充区间,///然后根据“左闭右开”的原则对每个区间填充///</summary>///<param name="AET"></param>///<param name="y"></param>private void FillAetScanLine(ref List<EDGE> AET, int y){if (AET.Count < 2) return;y = y / XiangSu * XiangSu;for (int i = 0; i < AET.Count; i += 2){int from = ((int)AET[i].xi + XiangSu) / XiangSu * XiangSu;int to = ((int)(AET[i + 1].xi + XiangSu / 2)) / XiangSu * XiangSu;while (from < to){Rectangle rect = new Rectangle(from - XiangSu / 2, y - XiangSu / 2, XiangSu, XiangSu);g.FillEllipse(blue, rect);from += XiangSu;}}}///<summary>///负责将对下一条扫描线来说已经不是“活动边”的边从aet中删除,///删除的条件就是当前扫描线y与边的ymax相等,如果有多条边满///足这个条件,则一并全部删除///</summary>///<param name="AET"></param>///<param name="y"></param>private int line = 0;private void RemoveNonActiveEdgeFromAet(ref List<EDGE> AET, int y){line = y;AET.RemoveAll(IsEdgeOutOfActive);}private bool IsEdgeOutOfActive(EDGE obj){return line == obj.ymax;}///<summary>///更新边表中每项的xi值,就是根据扫描线的连贯性用dx对其进行修正,///并且根据xi从小到大的原则对更新后的aet表重新排序///</summary>///<param name="AET"></param>private void UpdateAndResortAet(ref List<EDGE> AET){AET.ForEach(UpdateAetEdgeInfo);//更新xiMy_Sort(ref AET);}private void UpdateAetEdgeInfo(EDGE e){e.xi += e.dx;}}}。

相关主题