【图形学】边标志算法or边界标志算法(无错误版)

一直都想写这篇文章,由于我本身作实验的时候困扰了好久,网上貌似没看到彻底正确的代码,或许是我没有找到。这个的算法原本很简单,因此我这里并不叙述边界标志算法通常性的算法思想了,我只讨论实践中遇到的问题,因此看这篇文章以前,你最好已经明白边界标志算法的大体流程了。接下来就讨论一下:因为咱们要用到前面的算法画直线,以及原本在计算机上画图,就是一个近似的问题,因此这个算法实践时会遇到一些问题,其实就两个问题:c++

1.画多边形的边界时,必需要用斜率大于1的算法,不然会出错。缘由:你想一下,咱们是用扫描线去扫的,它是从y=1慢慢变大,每次遇到边界就flag取反,那么若是直线算法是很精确的讨论了斜率大于1和斜率小于1的状况时,在斜率小于1的时候就会出错。由于小于1的时候是x每次增长1,y有可能不变的,由于这是一个近似的过程,因此原本理论上一条扫描线上只有一个点的,实际上却在那一条扫描线上出现了好几个点,这样咱们取反就可能会出错。因此画边界时,必定要注意。算法

2.极值点要单独讨论。在说这个问题的解决方案时,我先说下我是怎么标记边界的,首先是我要画出要填色的多边形边界,而后呢,这时背景色和边界色确定就不同了!因此呢,就能够经过获取当前点的颜色来判断是不是边界。接下来,就讨论极值点的问题,咱们知道遇到极值点,虽然是边界,可是呢,flag不取反的,因此呢,咱们画好边界之后,将极值点涂为背景色就好了,这样就能够沿用之前的算法。函数

 

理解以上2点,基本上就没什么错误了,程序以下(估计你不能直接使用下面代码,由于我只贴出了主要部分,理解以上两点,你确定能写出来的!):spa

 

//主程序code

void CPadPolyView::OnDraw(CDC* pDC)
{
 CPadPolyDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
 COLORREF color=RGB(0,0,0);
 COLORREF clr,set=RGB(255,0,0);
 int flag=-1;
  //先把直线画了
 for(int i=0;i<m_lc.m_dot.c;i=i+2)
 {
  DrawBresenham(p[i][0],p[i+1][0],p[i][1],p[i+1][1],color,pDC);
 }
  DrawExtreamPoint(pDC);
  //获得全部点
  for(i=ymin;i<=ymax;i++)
  {
   flag=-1;
   for(int j=xmin;j<=xmax;j++)
   {
    clr=pDC->GetPixel(j,i);
    if(flag==1)
    {
     pDC->SetPixel(j,i,set);rem

    }   
    if(clr==color)
    {
     flag=-flag;
    }
    
  }
 }
}float

 

//因此的边界都用斜率大于1的直线算法程序

void CPadPolyView::DrawBresenham(int x1,int x2,int y1,int y2,COLORREF color,CDC* pDC)
{
  int flag=0;
  float k;
   k=(float)(x2-x1)/(float)(y2-y1);
   flag=1;
  float y=y1;
  float x=x1;
 int m_y1,m_y2;
 if(y1==y2)
 {
  int xmax=x2;
  x=x1;
  if(x1>x2)
  {
   x=x2;
   xmax=x1;
  }
  for(int i=x;i<xmax;i++)
  {
   pDC->SetPixel(i,y1,color);
  }
 }
 else
 {
   if(y1>y2)
   {
    m_y1=y2;
    m_y2=y1;
    x=x2;
   }
   else
   {
    m_y1=y1;
    m_y2=y2;
    x=x1;
   }
   for(int i=m_y1;i<m_y2;i++)
   {
    pDC->SetPixel(int(x+0.5),i,color);
    x=x+k;
   }
 }
}计算机

 

//将极值点涂为背景色解决方案

void CPadPolyView::DrawExtreamPoint(CDC* pDC)
{
 int temp=m_lc.m_dot.ec;
 COLORREF color=RGB(255,255,255);
 for(int i=0;i<temp;i++)
 {
  pDC->SetPixel(ep[i][0],ep[i][1],color);
 }
}

 

//计算极值点的函数

void CDot::GetExtremePoint() {  ec=0;  int x,y,tempy,temp;  int flag=1;  CString str;  for(int i=0;i<c;i++)  {   x=p[i][0];   y=p[i][1];   tempy=p[i+flag][1];//第一条边的y   flag=-flag;   for(int j=i+1;j<c;j++)   {    if((p[j][0]==x)&&(p[j][1]==y))    {      temp=j%2;      if(temp==0)      {       temp=1;      }      else      {       temp=-1;      }      if(p[j+temp][1]>y)//其中一个点大于y      {       if(tempy>y)//都大于y,不算,是极值点       {        ep[ec][0]=x;        ep[ec][1]=y;        ec++;       }      }      else if(p[j+temp][1]<y)      {       if(tempy<y)       {        ep[ec][0]=x;        ep[ec][1]=y;        ec++;       }      }    }   }  } }