Bresenham算法
- 算法用途:高效的进行直线或圆的栅格化
问题建模
-
给定起始点和终点,且满足,斜率为
-
使选择的像素,满足到直线的垂直误差最小。
-
设当前的像素点为,下一个候选点为:
- 右邻居
- 右上邻居
-
定义垂直距离偏差:
-
选择依据:比较d_{upper},选择较小一方为对应的点。
-
设定用于决策的变量:
后面括号括起来的部分为常量。
-
为了消除浮点预算,构建递推关系,构建过程如下:
递推的关系长这样:
- 当时,,则
- 当时,,则
-
递推的初始值:
算法流程
根据上述建模过程,有如下流程:
- 计算
- 比较,取大的那个为增长方向。以为增长方向为例。
- 从出发,初始误差设为。
每当, 。若,则,。 - 重复1,2,3,直到到达
代码实现
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
struct Point
{
int x;
int y;
};
vector<Point> BresenhamFilling(const Point& p1, const Point&p2)
{
vector<Point> points;
int dx = p2.x - p1.x;
int dy = p2.y - p1.y;
int ux = dx > 0 ? 1 : -1;
int uy = dy > 0 ? 1 : -1;
dx = abs(dx);
dy = abs(dy);
int x = p1.x;
int y = p1.y;
if (dx > dy) // 以x为增量
{
int e = -dx;
for (int i = 0; i < dx; ++i)
{
x += ux;
e += 2 * dy;
if (e >= 0)
{
y += uy;
e -= 2 * dx;
}
if (x != p2.x && y != p2.y)
{
points.push_back({x, y});
}
}
}
else // 以y为增量
{
int e = -dy;
for (int i = 0; i < dy; i++)
{
y += uy;
e += 2 * dx;
if (e >= 0)
{
x += ux;
e -= 2 * dy;
}
if (x != p2.x || y != p2.y)
{
points.push_back({x, y});
}
}
}
return points;
}