將一條線段柵格化的最簡單的算法思路是根據其斜率,按X或Y方向步進取值:ios
除此以外還有一種算法是利用計算機圖形學中繪製直線的Bresenham算法,這種算法的效率很高,原理就是用遍歷的辦法規避乘法和除法,只用加減法就能完成線段的柵格化。算法
上述兩種算法有個問題就是都要通過一系列繁複的判斷,才能獲得比較嚴密的結果,因此我並無採用。我這裏採用的算法也是逐漸步進求值的辦法,只不過再也不沿着X或者Y方向求值,而是沿着射線方向步進。這裏的射線指的是從線段的起點開始,以1像素爲步進單位,步進到線段的終點。由於線段的方向性問題,步進獲得的點總會有重複的值,最後再進行去重操做便可。ui
算法過程簡述以下:spa
最終獲得的點即爲直線柵格化後的點。.net
具體的C++實現代碼以下:unix
#include <iostream> #include <vector> using namespace std; const double EPSILON = 0.000001; // 2D Point struct Vector2d { public: Vector2d() { } Vector2d(double dx, double dy) { x = dx; y = dy; } // 矢量賦值 void set(double dx, double dy) { x = dx; y = dy; } // 矢量相加 Vector2d operator + (const Vector2d& v) const { return Vector2d(x + v.x, y + v.y); } // 矢量相減 Vector2d operator - (const Vector2d& v) const { return Vector2d(x - v.x, y - v.y); } //矢量數乘 Vector2d Scalar(double c) const { return Vector2d(c*x, c*y); } // 矢量點積 double Dot(const Vector2d& v) const { return x * v.x + y * v.y; } //向量的模 double Mod() const { return sqrt(x * x + y * y); } bool Equel(const Vector2d& v) const { if (abs(x - v.x) < EPSILON && abs(y - v.y) < EPSILON) { return true; } return false; } double x, y; }; //柵格化一條線段 void RasterLine(std::pair<Vector2d, Vector2d> line, std::vector<Vector2d>& linePointList) { Vector2d vecLine = line.second - line.first; double lineLength = vecLine.Mod(); double step = 1.0; //根據距離逐步取 vector<Vector2d> tmpPointList; double curLength = 0; while (curLength < lineLength) { curLength = curLength + step; Vector2d P = line.first + vecLine.Scalar(curLength / lineLength); P.x = (int)(P.x + 0.5); P.y = (int)(P.y + 0.5); tmpPointList.push_back(P); } //與最後一個值比較,去重 linePointList.push_back(line.first); for (size_t i = 0; i < tmpPointList.size(); i++) { //與最後一個值比較,去重 if (!tmpPointList[i].Equel(linePointList[linePointList.size() - 1])) { linePointList.push_back(tmpPointList[i]); } } if (!linePointList[linePointList.size() - 1].Equel(line.second)) { linePointList.push_back(line.second); } } int main() { Vector2d O(30, 60); Vector2d E(88, 104); std::pair<Vector2d, Vector2d> line(O, E); vector<Vector2d> linePointList; RasterLine(line, linePointList); for (size_t i = 0; i < linePointList.size(); i++) { cout << linePointList[i].x << ',' << linePointList[i].y << '\t'; } }
其運行的結果以下:code
[1].矢量數據柵格化
[2].Bresenham算法htm