Bresenham 贝汉明算法

理解:给定两个点,画出两个点的连线经过的栅格。

求解思路:

1.

bresenham贝汉明算法_Bimme军的博客-CSDN博客

2.

若干计算机图形学算法实现_JulyThirteenth的博客-CSDN博客

// grid traversal
void gridTraversal(const dPoint &start, const dPoint &goal, const double resolution, std::vector<iPoint> &visited_grid)
`{`
    `iPoint s_grid = {static_cast<int>(std::floor(start.x / resolution)), static_cast<int>(std::floor(start.y / resolution))};`
    `iPoint g_grid = {static_cast<int>(std::floor(goal.x / resolution)), static_cast<int>(std::floor(goal.y / resolution))};`
    `dPoint vector = {goal.x - start.x, goal.y - start.y};`
    `double stepX = (vector.x > 0) ? 1 : -1;`
    `double stepY = (vector.y > 0) ? 1 : -1;`
    `double next_grid_boundary_x = (s_grid.x + stepX) * resolution;`
    `double next_grid_boundary_y = (s_grid.y + stepY) * resolution;`
    `double tMaxX = (vector.x != 0) ? (next_grid_boundary_x - start.x) / vector.x : DBL_MAX;`
    `double tMaxY = (vector.y != 0) ? (next_grid_boundary_y - start.y) / vector.y : DBL_MAX;`
    `double tDeltaX = (vector.x != 0) ? resolution / vector.x * stepX : DBL_MAX;`
    `double tDeltaY = (vector.y != 0) ? resolution / vector.y * stepY : DBL_MAX;`
    `iPoint diff = {0, 0};`
    `iPoint c_grid = {s_grid.x, s_grid.y};`
    `visited_grid.push_back(c_grid);`
    `bool negative = false;`
    `if (s_grid.x != g_grid.x && vector.x < 0)`
    `{`
        `diff.x--, negative = true;`
    `}`
    `if (s_grid.y != g_grid.y && vector.y < 0)`
    `{`
        `diff.y--, negative = true;`
    `}`
    `if (negative)`
    `{`
        `c_grid.x += diff.x;`
        `c_grid.y += diff.y;`
        `visited_grid.push_back(c_grid);`
    `}`
    `double tx = tMaxX;`
    `double ty = tMaxY;`
    `while (!(c_grid == g_grid))`
    `{`
        `if (tx < ty)`
        `{`
            `c_grid.x += stepX;`
            `tx += tDeltaX;`
        `}`
        `else`
        `{`
            `c_grid.y += stepY;`
            `ty += tDeltaY;`
        `}`
        `visited_grid.push_back(c_grid);`
    `}`
`}`

算法理解

我们首先找到当前栅格的下一个 x 和 y 方向的栅格 1 和 2 ;

计算下 1 和 2 距离开始节点的 x 向 和 y 向的距离 xd 和 yd 占起止点之间在 x y 向的距离的百分比 x% y%;

假如 x% < y% 那么下一个栅格就是 当前节点的 x 加 1 或者 -1 ;

注意更新 x% , 也就是 x% 变为了 新的当前节点到开始节点 x 向的距离占起止节点之间 x 向的距离的百分比了。

TARE 里面有类似的实现代码

int 栅格作为输入的代码:



//!bresenham 算法
//!https://www.guyuehome.com/41384

#include <iostream>
#include <stdio.h>
#include<string.h>
#define H 16     //触摸框宽度
#define W 16
using namespace std;
unsigned short Array[H][W];
 
void Bresenham(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short(*array)[W]){
 
	int dx = abs(x2 - x1);
 
	int dy = abs(y2 - y1);
 
	bool is_great_than_45_degree = false;
 
	if (dx <= dy)
	{
		// 大于45度
		// Y 方向上变化速率快于 X 方向上变化速率,选择在 Y 方向上迭代,在每次迭代中计算 X 轴上变化;
		is_great_than_45_degree = true;
	}
 
	int fx = (x2 - x1) > 0 ? 1 : -1;
	int fy = (y2 - y1) > 0 ? 1 : -1;
	
	if (dy == 0)//0°
		fy = 0;
	if (dx == 0)//90°
		fx = 0;
 
	int ix = x1;
	int iy = y1;
	int p1 = 2 * dy - dx; //小于等于45°
	int p2 = 2 * dx - dy; //大于45°
if (is_great_than_45_degree){
		while (iy != y2){
			//Array[num - iy - 1][ix] = 0;
			*(*(array + (H- iy - 1)) + ix) = 1;
			//p2>0
			if (p2 > 0){
				p2 += 2 * (dx - dy);
				ix += fx;
			}
			else{
				p2 += 2*dx;
			}
			iy += fy;
			//Array[num - iy - 1][ix] = 0;
			*(*(array + (H - iy - 1)) + ix) = 1;
		}
	}
	else{
		while (ix != x2){
			//Array[num - iy - 1][ix] = 0;
			*(*(array + (H - iy - 1)) + ix) = 1;
			//p1>0
			if (p1 > 0){
				p1 += 2 * (dy - dx);
				iy += fy;
			}
			else{
				p1 += 2 * dy;
			}
			ix += fx;
			//Array[num - iy - 1][ix] = 0;
			*(*(array + (H - iy - 1)) + ix) = 1;
		}
	}
}
 
 
 
int main(){
	memset(Array, 0, H*W);
	unsigned short (*arr)[W] = Array;
	Bresenham(2, 7, 5, 1, arr);
	for (int i = 0; i < H; ++i){
		for (int j = 0; j < W; ++j){
			cout << int(Array[i][j]) << " ";
		}
		cout << endl;
	}
	system("pause");
    return 0;
}

//!

https://www.guyuehome.com/41384 代码

//!

https://zhuanlan.zhihu.com/p/493330783 公式推导

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值