Project1

标题: 求联结两点的方法 [打印本页]

作者: IamI    时间: 2010-9-12 17:39
标题: 求联结两点的方法
本帖最后由 IamI 于 2010-9-23 14:07 编辑

如题。最近比较懒,什么都不想弄……
求定义Sprite#lineto(x0,y0,x,y,color),以color色在该sprite的Bitmap上联结此两点。
要求:这条线是“致密的”。
x0,y0,x,y是Float。
每帧调用1次,不掉帧。
作者: 禾西    时间: 2010-9-12 17:39
本帖最后由 禾西 于 2010-9-13 02:29 编辑

  1. class Bitmap
  2.   #// Wu algorithm
  3.   #--------------------------------------------------------------------------
  4.   # ● 描绘直线   
  5.   #     x1,y1,x2,y2:  直线两端的坐标
  6.   #     color:    颜色
  7.   #--------------------------------------------------------------------------
  8.   def drawline(x1, y1, x2, y2, color)
  9.     x1 = x1.to_f
  10.     y1 = y1.to_f
  11.     x2 = x2.to_f
  12.     y2 = y2.to_f
  13.     draw_a_wuline(x1,y1,x2,y2,color)
  14.   end
  15.   def plot(x,y,c, ori_color)
  16.     color = ori_color.clone
  17.     color.alpha = 255 * c
  18.     set_pixel(x, y, color)
  19.   end
  20.   def ipart(x)
  21.     return x.floor
  22.   end
  23.   def fpart(x)
  24.     return (x - x.floor)
  25.   end
  26.   def rfpart(x)
  27.     return 1 - fpart(x)
  28.   end
  29.   def draw_a_wuline(x1,y1,x2,y2,color)
  30.     dx = x2 - x1 #horizontal distance
  31.     dy = y2 - y1 #perpendicular distance
  32.     if dx.abs < dy.abs
  33.       x1, x2 = x2, x1
  34.       y1, y2 = y2, y1
  35.       dx, dy = dy, dx
  36.     end
  37.     if x2 < x1
  38.       x1, x2 = x2, x1
  39.       y1, y2 = y2, y1
  40.     end
  41.     # find slope
  42.     gradient = dy/dx
  43.     # find initial endpoint
  44.     xend = x1.round
  45.     yend = y1 + gradient * (xend - x1) # y + k(xend - x)
  46.     xgap = rfpart(x1 + 0.5)
  47.     xpxl1 = xend  # this will be used in the main loop
  48.     ypxl1 = ipart(yend)
  49.     plot(xpxl1, ypxl1, rfpart(yend) * xgap, color)
  50.     plot(xpxl1, ypxl1 + 1, fpart(yend) * xgap, color)
  51.     intery = yend + gradient # first y-intersection for the main loop
  52.    
  53.     # find terminal endpoint
  54.     xend = x2.round
  55.     yend = y2 + gradient * (xend - x2)
  56.     xgap = fpart(x2 + 0.5)
  57.     xpxl2 = xend  # this will be used in the main loop
  58.     ypxl2 = ipart(yend)
  59.     plot(xpxl2, ypxl2, rfpart(yend) * xgap, color)
  60.     plot(xpxl2, ypxl2 + 1, fpart(yend) * xgap, color)
  61.    
  62.     # main loop
  63.     for x in (xpxl1 + 1) ... (xpxl2 - 1)
  64.       plot(x, ipart(intery), rfpart(intery), color)
  65.       plot(x, ipart(intery) + 1, fpart(intery), color)
  66.       intery = intery + gradient
  67.     end
  68.   end
  69. end
复制代码

作者: 紫苏    时间: 2010-9-12 22:00
本帖最后由 紫苏 于 2010-9-13 00:08 编辑

这种东西在 DLL 中处理比较好,之前弄过一个:
  1. void __stdcall DrawLine(register short x1, register short y1, register short x2, short y2, unsigned &clr, Bitmap &bitmap) {
  2.         register bool steep;
  3.         register char step;
  4.         register short dx, dy;
  5.         register int err;
  6.         seek(bitmap);
  7.         dx = abs(x2 - x1);
  8.         dy = abs(y2 - y1);
  9.         steep = dy > dx;
  10.         if(steep) {
  11.                 swap(x1, y1);
  12.                 swap(x2, y2);
  13.         }
  14.         if(x1 > x2) {
  15.                 swap(x1, x2);
  16.                 swap(y1, y2);
  17.         }
  18.         step = y1 < y2 ? 1 : -1;
  19.         if(steep) {
  20.                 err = dy/2;
  21.                 for(; x1 <= x2; ++x1) {
  22.                         plot(y1, x1, clr, bitmap);
  23.                         err -= dx;
  24.                         if(err < 0) {
  25.                                 y1 += step;
  26.                                 err += dy;
  27.                         }
  28.                 }
  29.         } else {
  30.                 err = dx/2;
  31.                 for(; x1 <= x2; ++x1) {
  32.                         plot(x1, y1, clr, bitmap);
  33.                         err -= dy;
  34.                         if(err < 0) {
  35.                                 y1 += step;
  36.                                 err += dx;
  37.                         }
  38.                 }
  39.         }
  40. }
复制代码
用的是目前公认最快的 Bresenham 直线算法

辅助函数,算 Bitmap 地址的那个(seek)是比较重要的:

  1. struct Bitmap {
  2.         short width;
  3.         short height;
  4.         unsigned id;
  5.         unsigned *bits;
  6. };

  7. void __stdcall seek(Bitmap &bitmap) {
  8.         unsigned *&bits = bitmap.bits;
  9.         if(0 == bits) {
  10.                 bits = (unsigned *)((bitmap.id << 1) + 16);
  11.                 bits = (unsigned *)(*bits + 8);
  12.                 bits = (unsigned *)(*bits + 16);
  13.                 bits = (unsigned *)*bits;
  14.         }
  15. }

  16. short __stdcall abs(short &x) {
  17.         return x < 0 ? -x : x;
  18. }

  19. void __stdcall swap(short &x, short &y) {
  20.         x ^= y;
  21.         y ^= x;
  22.         x ^= y;
  23. }
复制代码





欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1