计算机图形学之画线(DDA、Bresenham、中点画线) 针对各种斜率

      为什么写这篇文章?

       博主开始也是到处参考研究了很多代码,发现要考虑任意斜率的话,很多代码都是用if语句来分别讨论的,其实其中有很多重复的代码部分,我觉得不代码不简洁,就到处查询参考思考才总结出一些比较简洁的代码,希望大家喜欢,也期待大家有更好的方法分享。

     其中的代码我是用JavaScript写的,但其中原理是相通的,基本改改语法就都能用。

      进入正文:

  • 数值微分法DDA:  其中看x的斜率来确定增加的方向,DrawPixel(x,y,color)为画点个人函数。
 function DDA(x0, y0, x1, y1, color) {
      var dx, dy, m, k;
      var incX, incY, x, y;
      dx = x1 - x0; dy = y1 - y0;
      //正则表达式:其中?前条件为true则m=Math.abs(dx) ,反之m=Math.abs(dy)
      m = (Math.abs(dx) > Math.abs(dy)) ? Math.abs(dx) : Math.abs(dy);//Math.abs取绝对值

      incX = dx / m;
      incY = dy / m;
      x = x0; y = y0;
      for (k = 1; k < m; k++) {
          x += incX;
          y += incY;
          DrawPixel(Math.floor(x + 0.5), Math.floor(y + 0.5), color);//Math.floor向下取整
      }
}
  • Bresenham画线算法:以dx来决定每次增加还是减少,这样就把k<0的情况考虑进去,当 |k|>1时,就交换两点的XY坐标,再进行绘制,需要注意的是调用绘制点的函数时,要记得同时调换XY坐标。
function Bresenham(x0, y0, x1, y1, color) {
   var x, y, dx, dy, e, m;
   dx = x1 - x0; dy = y1 - y0;
   var flag = Math.abs(dx) - Math.abs(dy);//判断斜率是否大于1
   if (flag < 0) {//斜率大于1则交换XY坐标
       m = y0; y0 = x0; x0 = m;
       m = y1; y1 = x1; x1 = m;
   }

   dx = x1 - x0; dy = y1 - y0;
   e = 2 * Math.abs(dy) - Math.abs(dx);
   x = x0; y = y0;
   incX = (dx > 0) ? 1 : -1; //每次增加步长,避免<0的情况
   incY = dy / Math.abs(dy);//同上的另一种表达方式

   for (var i = 0; i < (Math.abs(dx)-1) ; i++) {
       x += incX;
       if (e < 0)
           e += 2 * Math.abs(dy);
       else {
           y += incY;
           e = e + 2 * (Math.abs(dy) - Math.abs(dx));
       }

       if (flag < 0)//斜率大于1则交换XY坐标
           DrawPixel(y, x, color);
       else
          DrawPixel(x, y, color);
    }
}
  • 中点画线法:考虑方式大致同Bresenham算法
 function MiddlePiont(x0, y0, x1, y1, color) {
    var dx, dy, d1, d2, d, x, y, m;
    dy = y0 - y1; dx = x1 - x0;
    var flag = Math.abs(dx) - Math.abs(dy);//判断斜率是否大于1
    if (flag < 0) {//斜率大于1则交换XY坐标
        m = y0; y0 = x0; x0 = m;
        m = y1; y1 = x1; x1 = m;
    }

    dy = y0 - y1; dx = x1 - x0;
    d = 2 * dy + Math.abs(dx);
    d1 = 2 * dy; d2 = 2 * (Math.abs(dx) + dy);
    x = x0; y = y0;
    var incX = (dx > 0) ? 1 : -1;//每次增加步长,避免<0的情况
    var incY = (dy > 0) ? -1 : 1;
             
    for (var i = 0; i < Math.abs(dx) ; i++) {
         x += incX;
         if (d < 0) { 
             y += incY; d += d2; }
         else
             d += d1;

         if (flag < 0)//斜率大于1则交换XY坐标
             DrawPixel(y, x, color);
         else
             DrawPixel(x, y, color);
     }}

 

你可能感兴趣的:(Web)