中点bresenham算法画线

要求:
使用中点bresenham算法绘制任意斜率的直线。可用鼠标左键绘制直线(左键按下点为起点,弹起点为终点)

  1. 新建MFC项目
  2. 画线需要鼠标响应,所以在view类中添加OnLButtonUp和OnLButtonDown来进行鼠标消息的处理
    方法:鼠标右击视图类(如CmyMouseView),选择“add windows message handler…”,弹出事件处理函数列表窗口
    中点bresenham算法画线_第1张图片
    从左边事件消息列表中选择“WM_LBUTTONDOWN”,然后单击“Add and Edit”按钮,即加入鼠标左键按下事件函数,并要求编辑事件处理程序。

  3. 编辑OnLButtonUp和OnLButtonDown函数

void CMyView::OnLButtonDown(UINT nFlags, CPoint point) 
{
       CView::OnLButtonDown(nFlags,point);  
       po=point;  //鼠标按下的那个点为起点,赋值给p0               
}
void CMyView::OnLButtonUpOnLButtonUp(UINT nFlags, CPoint point) 
{

        p1=point;   //鼠标抬起的点为终点
        CDC *pDC=this->GetDC();
        COLORREF clr=RGB(0,0,0);  
        DrawLine(pDC,p0,p1,clr);
    }
    CView::OnLButtonUp(nFlags, point);
}
  1. 在view 类中新建一个DrawLine(CDC *pDC, CPoint p0, CPoint p1, COLORREF clr)函数CPoint类型的p0,p1变量来实现中点bresenham算法
void CMyView::DrawLine(CDC *pDC, CPoint p0, CPoint p1, COLORREF clr)
{

    CPoint p,t;

    if(fabs(p0.x-p1.x)<1e-6){
        if(p0.y>p1.y){
            t=p0;
            p0=p1;
            p1=t;
        }
        for(p=p0;p.y
            pDC->SetPixelV(Round(p.x),Round(p.y),clr);
        }

    }
    else{
        double k,d;
        k=(p1.y-p0.y)/(p1.x-p0.x);

        if(k>1.0)
        {
            if(p0.y>p1.y)
            {
                t=p0;
                p0=p1;
                p1=t;
            }
            d=1-0.5*k;
            for(p=p0;p.y
            {
                pDC->SetPixelV(Round(p.x),Round(p.y),clr);
                if(d>=0)
                {
                    p.x++;
                    d+=1-k;
                }
                else
                    d+=1;   
            }
        }
        if(0.0<=k && k<=1.0)
        {
            if(p0.x>p1.x){
                t=p0;
                p0=p1;
                p1=t;
            }
            d=0.5-k;
            for(p=p0;p.x
            {
                pDC->SetPixelV(Round(p.x),Round(p.y),clr);

                if(d<0)
                {
                    p.y++;
                    d+=1-k;
                }
                else
                    d-=k;
            }
        }

        if(k>=-1.0 && k<0.0)
        {
            if(p0.x>p1.x)
            {
                t=p0;
                p0=p1;
                p1=t;
            }
            d=-0.5-k;

            for(p=p0;p.x
            {
                pDC->SetPixelV(Round(p.x),Round(p.y),clr);
                if(d>0)
                {
                    p.y--;
                    d-=1+k;
                }
                else
                    d-=k;

            }
        }

        if(k<-1.0)
        {
            if(p0.y.y)
            {
                t=p0;
                p0=p1;
                p1=t;
            }
            d=-1-0.5*k;
            for(p=p0;p.y
            {
                pDC->SetPixelV(Round(p.x),Round(p.y),clr);
                if(d<0)
                {
                    p.x++;
                    d-=1+k;
                }
                else
                    d-=1;
            }
        }
    }
    p0=p1;
}

有几个注意点:
Round函数需要自己实现,但原本函数实现应该是

double round(double val)
{
    return (val> 0.0) ? floor(val+ 0.5) : ceil(val- 0.5);
}

这样的,但是SetPixelV(Round(p.x),Round(p.y),clr)中前两个参数都是int类型,而round()返回值是double
因此在开始加#define Round(d) int(floor(d+0.5)) 宏定义即可

你可能感兴趣的:(c++,计算机图形学)