缓慢画点功能实现的两个方法

=============================================================================================
20130806_第二次修改                         ccb_warlock
=============================================================================================

测试平台:VC++6.0
操作系统:64位win7


    暑假的课程设计老师再使用MFC画点时提到了一点,让我们课后思考则样能使得画线时是一个一个点连续缓慢的画出来。我觉得这个技术点在我之后的数据结构里做构建树的程序里很有用(即能直观的看出先画哪些点,后画哪些点),于是我开始思考并测试我认为可行的办法。由于我的技术能力所限,现在有两个办法去实现这个功能,如果将来还有别的方法再进行本文的修改。




方法1:(思路:通过占用资源的方式)
     
    该方法也是我最先涌入脑子的一个思路,因为想到画点需要消耗CPU等硬件的资源(虽然现在GPU的出现已经使图像处理的速度大大加快,可是程序内部实现点亮像素点的工作还是相对消耗资源的),通过一定的操作减慢程序走的速度。而这个操作我也首先想到通过多次循环画无用点使得每画一个有用点画的时间增加(换句话说就是当画了一个有用点后,程序在画下一个有用点之前画N个无用点)。由于这些无用点不是我们需要的,所以将这些点画的坐标与前一个有用点坐标一致我们认为是合理的。将该循环语句加在需要的位置,通过不断运行测试来确定哨兵位合理的值。

    提醒在组建前仔细检查相关sentry的赋值有没有过大,因为如果sentry赋予的值过大,在做循环时很可能会出现程序的未响应,甚至是该程序卡死(可以将这个情况视为危害不大的死循环)。

增加的循环源码部分:
while(sentry)
{
  pDC->SetPixel(x,y,color);//此处的x,y根据情况修改
  sentry--;
}


画线源码部分:
//中点画线函数
void CTest01Dlg::MidpointLine(CDC *pDC, int x0, int y0, int x1, int y1, COLORREF color)
{
  int a,b,delta1,delta2,d,x,y;
  int sentry;
  //传入端点坐标x值相等
  if (x0 == x1)
  {
    if (y0 < y1)
    {
      for (int i=y0;i<=y1;i++)
      {
        pDC->SetPixel(x0+5,i,color);

        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x0+5,i,color);
          sentry--;
        }
      }
    }
    else
    {
      for (int i=y1;i<=y0;i++)
      {
        pDC->SetPixel(x0+5,i,color);

        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x0+5,i,color);
          sentry--;
        }
       }
    }
    return;
  }
  //斜率判断,斜率绝对值大于1,则m为false,否则为true
  BOOL m = (fabs(y1-y0)<=fabs(x1-x0));
  //如果传入的x0大于x1,将坐标值互换
  if (x0>x1)
  {
    d=x0+5;x0=x1+5;x1=d;
    d=y0+3;y0=y1+3;y1=d;
  }
  a = y0 - y1;
  b = x1 - x0;
  x = x0+5;
  y = y0+3;
  pDC->SetPixel(x,y,color);
  //斜率绝对值小于等于1
  if (m)
  {
  //第一种情况,y值递增
    if (y0 <= y1)
    {
      d = 2 * a +b;
      delta1 = 2 * a;
      delta2 = 2 * (a + b);
      while (x < x1)
      {
        if (d < 0)
        {x++;y++;d+=delta2;}
        else
        {x++;d+=delta1;}
        pDC->SetPixel(x,y,color);

        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x,y,color);
          sentry--;
        }
      }
    }
    //第三种情况,y值递减
    else
    {
      d = 2 * a -b;
      delta1 = 2 * a;
      delta2 = 2 * (a - b);
      while (x < x1)
      {
        if (d < 0)
        {x++;d+=delta1;}
        else
        {x++;y--;d+=delta2;}
        pDC->SetPixel(x,y,color);

        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x,y,color);
          sentry--;
        }
      }
    }
  }
  //斜率绝对值大于1
  else
  {
  //第二种情况,y值递增
    if (y0 <= y1)
    {
      d =  a + 2 * b;
      delta1 = 2 * b;
      delta2 = 2 * (a + b);
      while (y < y1)
      {
        if (d < 0)
        {y++;d+=delta1;}
        else
        {y++;x++;d+=delta2;}
        pDC->SetPixel(x,y,color);

        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x,y,color);
          sentry--;
        }
      }
    }
    //第四种情况,y值递减
    else
    {
      d =  a - 2 * b;
      delta1 = -2 * b;
      delta2 = 2 * (a - b);
      while (y > y1)
      {
        if (d < 0)
        {y--;x++;d+=delta2;}
        else
        {y--;d+=delta1;}
        pDC->SetPixel(x,y,color);
 
        sentry=500;
        while(sentry)
        {
          pDC->SetPixel(x,y,color);
          sentry--;
        }
      }
    }
  }
}


特别注明:一开始测试时,该方法没有实现我所需要的功能,因为我将哨兵位sentry的赋值与函数最前面的定义(int a,b,delta1,delta2,d,x,y;)放在了一起,结果导致在画某一条线的循环时使得仅仅只在画完第一个有用点后进行循环画无用点的操作(换句话说就是在画这条线的第一点后调用了一次画无用点的while循环,之后由于sentry被置为了0,while循环不被调用),所以前面测试时一直没有缓慢画点的效果。
经过后来查看源码,我发现了错误的地方,并在调用该while循环前,对增加对sentry的赋值以保证接下来的循环能正常进行。再次组建运行测试程序的,缓慢画点的功能终于实现了。




方法2:(思路:通过暂停程序运行的方式)
    
    根据这个思路,我们可以使用系统自带的sleep函数来实现这个功能。
    (windows中Sleep函数的“S”大写,具体内容见本博客《关于sleep函数的一些问题和资料》)。


    sleep函数的功能让系统暂停这个应用的运行(使用CPU),所以通常用于延时应用。我个人觉得这个函数功能比方法1通过占用资源(使用CPU)来的好,毕竟一台计算机的资源是有限的。


增加的sleep函数部分:
Sleep(5);

画线源码部分:
//中点画线函数
void CTest01Dlg::MidpointLine(CDC *pDC, int x0, int y0, int x1, int y1, COLORREF color)
{
  int a,b,delta1,delta2,d,x,y;
  int sentry;
  //传入端点坐标x值相等
  if (x0 == x1)
  {
    if (y0 < y1)
    {
      for (int i=y0;i<=y1;i++)
      {
        pDC->SetPixel(x0+5,i,color);

        Sleep(5);
      }
    }
    else
    {
      for (int i=y1;i<=y0;i++)
      {
        pDC->SetPixel(x0+5,i,color);

        Sleep(5);
      }
    }
    return;
  }
  //斜率判断,斜率绝对值大于1,则m为false,否则为true
  BOOL m = (fabs(y1-y0)<=fabs(x1-x0));
  //如果传入的x0大于x1,将坐标值互换
  if (x0>x1)
  {
    d=x0+5;x0=x1+5;x1=d;
    d=y0+3;y0=y1+3;y1=d;
  }
  a = y0 - y1;
  b = x1 - x0;
  x = x0+5;
  y = y0+3;
  pDC->SetPixel(x,y,color);
  //斜率绝对值小于等于1
  if (m)
  {
  //第一种情况,y值递增
    if (y0 <= y1)
    {
      d = 2 * a +b;
      delta1 = 2 * a;
      delta2 = 2 * (a + b);
      while (x < x1)
      {
        if (d < 0)
        {x++;y++;d+=delta2;}
        else
        {x++;d+=delta1;}
        pDC->SetPixel(x,y,color);

        Sleep(5);
      }
    }
    //第三种情况,y值递减
    else
    {
      d = 2 * a -b;
      delta1 = 2 * a;
      delta2 = 2 * (a - b);
      while (x < x1)
      {
        if (d < 0)
        {x++;d+=delta1;}
        else
        {x++;y--;d+=delta2;}
        pDC->SetPixel(x,y,color);

        Sleep(5);
      }
    }
  }
  //斜率绝对值大于1
  else
  {
  //第二种情况,y值递增
    if (y0 <= y1)
    {
      d =  a + 2 * b;
      delta1 = 2 * b;
      delta2 = 2 * (a + b);
      while (y < y1)
      {
        if (d < 0)
        {y++;d+=delta1;}
        else
        {y++;x++;d+=delta2;}
        pDC->SetPixel(x,y,color);

        Sleep(5);
      }
    }
    //第四种情况,y值递减
    else
    {
      d =  a - 2 * b;
      delta1 = -2 * b;
      delta2 = 2 * (a - b);
      while (y > y1)
      {
        if (d < 0)
        {y--;x++;d+=delta2;}
        else
        {y--;d+=delta1;}
        pDC->SetPixel(x,y,color);
 
        Sleep(5);
      }
    }
  }
}





即使有一天在技术上我已经是个能手,请记住自己应有的责任和保持一个真诚交流、始终渴望追求技术的心。                                                                     ----------ccb_warlock
原文地址:https://www.cnblogs.com/straycats/p/5248733.html