直线生成算法——Bresenham画线法
2015-11-25 21:58
519 查看
我们将平面划分成十个部分,从第一象限的x轴开始做逆时针旋转,每隔45度角为一部分,由此类推到第八部分。Y轴正向为第九部分,负向为第十部分。
当直线的斜率k∈[0,1],Bresenham画线算法的基本原理是通过各行各列像素中心构造一张虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。如果在x方向增加一个单位长度,在y方向是否增加一个单位根据计算的误差项d来决定。d为所画直线与网格垂直线的交点到本网格水平底线的距离。
当d>=1时,将其减去1,使其保持在一个单位之内,因此误差项d的界定为0.5.判断条件为:d>=0.5取右上方像素,反之取正右方像素。
同理于斜率在[1,+∞]和负数的情况,当斜率的绝对值大于1时,如果在y轴方向增加一个单位长度,在x方向是否增加一个单位根据计算的误差项d来决定。
程序实现时,依旧划分为8+2个共10个区域,但是这次引入对换方法实现,由于8个区域内存在4对4的斜率相同的情况,即,八个两两中心对称的区域斜率相同,只是始末点不同。同时因为直线的无向性,所以我们以y轴为届,x轴正向的情况通过公式导出,x轴负向的通过其中心对称区域的点互换数值实现直线画图。同时依旧使用if和switch语句实现。
当直线的斜率k∈[0,1],Bresenham画线算法的基本原理是通过各行各列像素中心构造一张虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。如果在x方向增加一个单位长度,在y方向是否增加一个单位根据计算的误差项d来决定。d为所画直线与网格垂直线的交点到本网格水平底线的距离。
当d>=1时,将其减去1,使其保持在一个单位之内,因此误差项d的界定为0.5.判断条件为:d>=0.5取右上方像素,反之取正右方像素。
同理于斜率在[1,+∞]和负数的情况,当斜率的绝对值大于1时,如果在y轴方向增加一个单位长度,在x方向是否增加一个单位根据计算的误差项d来决定。
程序实现时,依旧划分为8+2个共10个区域,但是这次引入对换方法实现,由于8个区域内存在4对4的斜率相同的情况,即,八个两两中心对称的区域斜率相同,只是始末点不同。同时因为直线的无向性,所以我们以y轴为届,x轴正向的情况通过公式导出,x轴负向的通过其中心对称区域的点互换数值实现直线画图。同时依旧使用if和switch语句实现。
OnBresenhamline() { *pDC = GetDC(); tempx = 0;
<span style="white-space:pre"> </span>tempy = 0; if (x0 > x1) { tempx = x0; x0 = x1; x1 = tempx; tempy = y0; y0 = y1; y1 = tempy; } dx = x1 - x0; dy = y1 - y0; ex = -dx; ey = -dy; x = x0; y = y0; state = 0; Dx = abs(dx); Dy = abs(dy); //状态分析 if (dx > 0) { if (dy < 0) { if (Dx >= Dy) state = 1; else state = 2; } else { if (Dx >= Dy) state = 8; else state = 7; } } else if (dx < 0) { if (dy < 0) { if (Dx <= Dy) state = 3; else state = 4; } else { if (Dx <= Dy) state = 6; else state = 5; } } else if (dy < 0) state = 9; else state = 10; switch (state) { case 1: case 5: for (i = 0; i <= dx; i++) { pDC->SetPixel(x, y, color); x++; ex += (-2) * dy; if (ex >= 0) { y--; ex = ex - 2 * dx; } } break; case 2: case 6: for (i = 0; i <= (-dy); i++) { pDC->SetPixel(x, y, color); y--; ey += 2 * dx; if (ey >= 0) { x++; ey = ey + 2 * dy; } } break; case 3: case 7: for (i = 0; i <= dy; i++) { pDC->SetPixel(x, y, color); y++; ey += 2 * dx; if (ey >= 0) { x++; ey = ey - 2 * dy; } } break; case 4: case 8: for (i = 0; i <= dx; i++) { pDC->SetPixel(x, y, color); x++; ex += 2 * dy; if (ex >= 0) { y++; ex = ex - 2 * dx; } } break; case 9: while (y >= y1) { y--; pDC->SetPixel(x, y, color); } break; case 10: while (y <= y1) { y++; pDC->SetPixel(x, y, color); } break; default: break; } ReleaseDC(pDC); }
相关文章推荐
- 关于tableview不能全部显示cell的问题?
- onkeydown在火狐和IE的用法
- BlotDB数据库例子
- Operating System-Thread(1)What and Why Thread &&进程和线程的对比
- matrix
- Combination Sum
- JSON之生成JSON字符串和解析
- IOS学习——UIView Animation与CATransition
- 学习日志(1)
- Swift中的Reference Type和 Values Type
- Swift -5 面向对象基础(中)
- ubuntu如何完全卸载Java
- 直线生成算法——中点画线法(Middpoint)
- Struts2_Constant标签认识以及查文件源码和api文档[6]
- Socket 通信原理机制
- Android Studio打包.so文件教程
- 几个主流的Java连接池整理 (转) (2012-01-04 23:48:02)转载▼
- 快速上手php:使用PhpStrom部署项目
- ServletContext对象
- 115.Oracle数据库SQL开发之 PLSQL编程——循环