MFC bresenham直線算法與MidPoint畫圓的總結

首先看一下效果圖!!

vs2017做的,我覺得跟vc6上做都是一樣的。




在MFC的view.h頭文件和view.cpp 裏新建自己的函數,


void CMFC1View::Bresenhamline(int x0, int y0, int x1, int y1, int color)
{
 CDC *p;
 p = GetDC();
 int x, y, dx, dy, e;
 dx = x1 - x0;
 dy = y1 - y0;
 e = -dx;
 x = x0;
 y = y0;


 if ((dx >= 0 && dy >= 0) || (dx <= 0 && dy <= 0))    //如果k大於0
 {
  if ((dx<0) || (dx == 0 && dy<0))                       //dx小於0說明終點x
  {
   dx = -dx;//
   x = x1;//
   dy = -dy;
   y = y1;
  }
  if (dy<dx)                             //第一種情況,k-(0,1)//////////////
  {
   e = -dx;
   for (int i = 0;i<dx;i++)
   {
    p->SetPixel(x, y, color);
    x++;
    e = e + dy + dy;
    if (e >= 0)
    {
     y++;
     e = e - dx - dx;
    }
   }
  }
  else                                     //第二種情況,k-(1,max)
  {
   e = -dy;
   for (int i = 0;i<dy;i++)
   {
    p->SetPixel(x, y, color);
    y++;
    e = e + dx + dx;
    if (e >= 0)
    {
     x++;
     e = e - dy - dy;
    }
   }
  }
 }
 else                                            //如果k小於0
 {
  int tempx, tempy;    //保存x和y的絕對值
  if (dx<0)                //dx小於0說明終點x
  {
   tempx = -dx;
   tempy = dy;
  }
  if (dy<0)
  {
   tempx = dx;
   tempy = -dy;
  }
  if (tempx>tempy)                                //第三種情況,k-(-1,0)
  {
   if (dx<0)                       //dx小於0說明終點x
   {
    dx = -dx;
    x = x1;
    dy = -dy;
    y = y1;
   }
   e = -dx;
   for (int i = 0;i<dx;i++)
   {
    p->SetPixel(x, y, color);
    x++;
    e = e - dy - dy;
    if (e >= 0)
    {
     y--;
     e = e - dx - dx;
    }
   }
  }
  else                                     //第四種情況,k-(-1,min)
  {
   if (dy<0)//dx小於0說明終點x
   {
    dx = -dx;
    x = x1;
    dy = -dy;
    y = y1;
   }
   e = -dy;
   for (int i = 0;i<dy;i++)
   {
    p->SetPixel(x, y, color);
    y++;
    e = e - dx - dx;
    if (e >= 0)
    {
     x--;
     e = e - dy - dy;
    }
   }
  }
 }
}





在view.cpp裏重載鼠標的左鍵按下和彈起兩個函數,在view.h 定義公有的cpoint x1,x2;


void CMFC1View::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息處理程序代碼和/或調用默認值
 x1 = point;
 CView::OnLButtonDown(nFlags, point);
}

void CMFC1View::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息處理程序代碼和/或調用默認值
 x2 = point;
 Bresenhamline(x1.x,x1.y,x2.x,x2.y,255);//直接調用函數,不會重繪製,
 CView::OnLButtonUp(nFlags, point);
}



然後在鼠標彈起的函數裏調用就行,也可以先調用invalidate()函數,invalidate()函數會自動調用ondraw()函數,區別是一個是ondraw()裏調的後面的會覆蓋前面的,直接調用的不會覆蓋原來的畫出來的直線或者圓。哪個都行,看你的需要。








void CMFC1View::OnDraw(CDC* pDC)
{
 CMFC1Doc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if(m_nshape==1)
 Bresenhamline(x1.x, x1.y, x2.x, x2.y, 255);//ondraw()裏調用會覆蓋前面畫的圖
 if (m_nshape == 2)
 {
  radius = (x2.y - x1.y)*(x2.y - x1.y) + (x2.x - x1.x)*(x2.x - x1.x);
  radius = sqrt(radius);
  MidPointCircle(x1.x, x1.y, radius, 255);
 }
  
 // TODO: 在此處爲本機數據添加繪製代碼
}


以上是直線的輸出兩種方法哪個都行。
--------------------------------------------------------------------------


直線的函數是可以直接調用的,但是圓的函數涉及到,求半徑的問題,所以我在頭文件的公有數據裏定義了radius,方便直接調用,



圓的view.h  和view.cpp裏定義兩個函數。


int  CMFC1View::DrawPoint(int x0, int y0, int x, int y, int color)
{
 CDC *PDc = GetDC();
 PDc->SetPixel(x + x0, y + y0, 255);
 PDc->SetPixel(-x + x0, y + y0, 255);
 PDc->SetPixel(-x + x0, -y + y0, 255);
 PDc->SetPixel(x + x0, -y + y0, 255);
 PDc->SetPixel(y + x0, x + y0, 255);
 PDc->SetPixel(-y + x0, x + y0, 255);
 PDc->SetPixel(-y + x0, -x + y0, 255);
 PDc->SetPixel(y + x0, -x + y0, 255);
 return (0);
}
void CMFC1View::MidPointCircle(int x0, int y0, int radus, int color)
{
 int x, y, d;
 x = 0;y = radus;d = int(1.25 - radus);
 while (y >= x)
 {
  DrawPoint(x0, y0, x, y, color);
  if (d<0)
  {
   d = d + 2 * x + 3;x++;
  }
  else
  {
   d = d + 2 * (x - y) + 5;x++;y--;
  }
 }
}


圓的兩個函數,一個是定義八分之一的圓,另一個函數負責畫出對稱點,


radius=sqrt((x2.y-x1.y)*(x2.y-x1.y)+(x2.x-x1.x)*(x2.x-x1.x));
記得加上#include<cmath>



再把圓心和半徑傳進去進行,
invalidate()這個函數會自動調用ondraw() 函數,
如果不涉及到菜單項就不用invalidate() 調用ondraw()函數,而是 直接在你需要的地方調用該函數就行。


希望對你有幫助,




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章