bresenham畫線算法的最簡潔實現
具體的bresenham算法可以參考https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html,這裏介紹的是一種基於該算法的實現方式。爲什麼說是最簡潔的實現的看下面的代碼實現就知道了,短短不到三十行代碼便可以實現全座標系任意斜率直線的繪製。
這裏採用了虛擬軸的概念,因而使得可以屏蔽斜率的概念可以使得所有的直線繪製都轉化爲第一象限斜率小於1情況下的直線繪製。因此所有的判定條件只有一個e+dy-0.5dx
std::vector<Point> bresenham(Point start_point, Point end_point) {
std::vector <Point> res;
Point pos = start_point;
int direction_x = end_point.x - start_point.x;
int direction_y = end_point.y - start_point.y;
int delta_x = fabs(direction_x);
int delta_y = fabs(direction_y);
int max_xy = ((delta_x > delta_y) ? delta_x : delta_y);
int decision_param_x = - (max_xy / 2);
int decision_param_y = decision_param_x;
res.push_back(start_point);
for(int i = 0; i < max_xy; ++i) {
//處理x
decision_param_x += delta_x;
if(decision_param_x > 0) {
direction_x > 0 ? pos.x++ : pos.x--;
decision_param_x -= max_xy;
}
//處理y
decision_param_y += delta_y;
if(decision_param_y > 0) {
direction_y > 0 ? pos.y++ : pos.y--;
decision_param_y -= max_xy;
}
res.push_back(pos);
}
return res;
}
以上便是該算法實現的全部內容,可以很容易移植到不同的測試環境中測試。下圖是在windows平臺終端下的測試結果。
以下爲完整的測試代碼:
#include <iostream>
#include <windows.h>
#include <vector>
#include <cmath>
typedef struct
{
int x;
int y;
}Point;
Point start_point = {15, 15};
Point end_point = {8, 0};
std::vector<Point> bresenham(Point start_point, Point end_point) {
std::vector <Point> res;
Point pos = start_point;
int direction_x = end_point.x - start_point.x;
int direction_y = end_point.y - start_point.y;
int delta_x = fabs(direction_x);
int delta_y = fabs(direction_y);
int max_xy = ((delta_x > delta_y) ? delta_x : delta_y);
int decision_param_x = - (max_xy / 2);
int decision_param_y = decision_param_x;
res.push_back(start_point);
for(int i = 0; i < max_xy; ++i) {
//處理x
decision_param_x += delta_x;
if(decision_param_x > 0) {
direction_x > 0 ? pos.x++ : pos.x--;
decision_param_x -= max_xy;
}
//處理y
decision_param_y += delta_y;
if(decision_param_y > 0) {
direction_y > 0 ? pos.y++ : pos.y--;
decision_param_y -= max_xy;
}
res.push_back(pos);
}
return res;
}
void gotoXY(int x, int y)
{
COORD cd;
cd.X = x;
cd.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cd);
}
int main(void)
{
std::vector<Point> point_set = bresenham(start_point, end_point);
system("cls");
for(int i = 0; i < point_set.size(); ++i)
{
gotoXY(point_set[i].x, point_set[i].y);
std::cout << "*" ;
}
gotoXY(0,30);
}