平时, 用惯了API、CDC和封装好的内部函数,关于画线,画圆这些东西都是信手拈来…
最近学习计算机图形学,不得不深入内部研究一下底层算法…
在这里贴几个代码分享一下!
(这里只给出MFC的OnDraw函数)
一、画线的三个算法:
1。DDA(数值微分)法:
void CDDALineView::OnDraw(CDC* pDC)
{
CDDALineDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int x,x0(200),y0(200),x1(500),y1(500);
float dx,dy,y,k;
dx=x1-x0;
dy=y1-y0;
k=dy/dx;
y=y0;
for(x=x0;x<=x1;x++)
{
pDC->SetPixel(x,(int)(y+0.5),RGB(255,0,0));
y+=k;
}
}
2.中点画线算法
void CMidpointLineView::OnDraw(CDC* pDC)
{
CMidpointLineDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int a,b,d1,d2,d,x,y;
int x0(200),x1(500),y0(200),y1(500);
a=y0-y1;
b=x1-x0;
d=2*a+b;
d1=2*a;
d2=2*(a+b);
x=x0;
y=y0;
pDC->SetPixel(x,y,RGB(0,255,0));
while(x<x1)
{
if(d<0)
{
x++;
y++;
d+=d2;
}
else
{
x++;
d+=d1;
}
pDC->SetPixel(x,y,RGB(0,255,0));
}
}
3。Bresenham算法:
void CBresenhamline2View::OnDraw(CDC* pDC)
{
CBresenhamline2Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int x0(200),y0(200),x1(500),y1(500);
int x,y,dx,dy;
dx=x1-x0;
dy=y1-y0;
int e=-dx;
x=x0;
y=y0;
for(int i=0;i<=dx;i++)
{
pDC->SetPixel(x,y,RGB(0,0,255));
x=x+1;
e=e+2*dy;
if(e>=0)
{
y++;
e=e-2*dx;
}
}
}
二、中点画圆算法:
void CMidPointCircleView::OnDraw(CDC* pDC)
{
CMidPointCircleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int r=100; //半径
int m(300),n(250); //圆心坐标
int x,y;
float d;
x=0;
y=0+r;
d=1.25-r;
//中点画圆算法
pDC->SetPixel(m+x,n+y,RGB(255,0,0));
pDC->SetPixel(m+y,n+x,RGB(255,0,0));
pDC->SetPixel(m-x,n+y,RGB(255,0,0));
pDC->SetPixel(m+y,n-x,RGB(255,0,0));
pDC->SetPixel(m+x,n-y,RGB(255,0,0));
pDC->SetPixel(m-y,n+x,RGB(255,0,0));
pDC->SetPixel(m-x,n-y,RGB(255,0,0));
pDC->SetPixel(m-y,n-x,RGB(255,0,0));
while(x<=y)
{
if(d<0)
d+=2*x+3;
else
{
d+=2*(x-y)+5;
y--;
}
x++;
pDC->SetPixel(m+x,n+y,RGB(255,0,0));
pDC->SetPixel(m+y,n+x,RGB(255,0,0));
pDC->SetPixel(m-x,n+y,RGB(255,0,0));
pDC->SetPixel(m+y,n-x,RGB(255,0,0));
pDC->SetPixel(m+x,n-y,RGB(255,0,0));
pDC->SetPixel(m-y,n+x,RGB(255,0,0));
pDC->SetPixel(m-x,n-y,RGB(255,0,0));
pDC->SetPixel(m-y,n-x,RGB(255,0,0));
}
}
椭圆弧生成算法
基本同圆弧算法,只是方程变得复杂F(x,y)=(bx)^2+(ay)^2-(ab)^2.
对称性:4分对称,画第一象限
分段依据:斜率为一点
上段圆弧:
下段圆弧:
【椭圆中点算法流程图】