[关闭]
@iStarLee 2019-08-12T20:22:44.000000Z 字数 2270 阅读 1445

costmap_2d —— bresenham快速画直线算法

navigation


Reference

1 bresenham快速画直线算法

  Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。

1.1 计算机是如何画直线的?

简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。

image_1di2clroe6qc1fge1ivj13p11fia9.png-71.9kB

1.2 画直线的算法分析

考虑最简单的情况,
image_1di2progn6bjtl2j4r1cta2kc1t.png-5.4kB

算法流程如下
image_1di2otvgi1c0c1u8n1i5tuhattk1g.png-8.4kB

核心理解点是
image_1di2pvhk6bmvosvl9m1go918ds2a.png-2.9kB

考虑第二种情况,
image_1di2q198l1tkc1662ecu7vb26k2n.png-5.6kB
算法流程如下
image_1di2osj6sb1glemsgr1ht41ia13.png-8.6kB
核心理解点是
image_1di2q2nkc1bfs1vc7k2c1l6l3gb34.png-4.5kB

事实上要根据起始点终点画一条直线(按照带箭头的理解)一共有八种情况
image_1di2q50kc1npqd6b1d8i1i21ihc3h.png-14.6kB

我们通过一个简单的处理将八种情况都统一到上面的两种情况来处理,思路是:

1.3 一般化的完整算法(涵盖八种情况的处理)

  1. function draw_line(x0,x1,y0,y1)
  2. steep = abs(y1-y0)>abs(x1-x0) //判断是否是大斜率情况
  3. if steep then //处理大斜率情况,交换x,y坐标
  4. swap(x0,y0)
  5. swap(x1,y1)
  6. if x0>x1 then //处理x递减的情况,交换起点和终点
  7. swap(x0,x1)
  8. swap(y0,y1)
  9. int deltx = x1-x0 //+
  10. int delty = abs(y1-y0) //+
  11. double error = 0 //误差+
  12. double delterr = deltay/deltx //斜率+
  13. int y = y0 //画线y坐标
  14. int ystep //应对 1.2 中介绍的两种情况
  15. if y0<y1 then
  16. ystep = 1
  17. else
  18. ystep = -1
  19. for x from x0 to x1 //画线x坐标
  20. if steep then
  21. plot(y,x)//大斜率
  22. else
  23. plot(x,y)
  24. error = error + delterr
  25. if error >=0.5 then //这个地方将上面的两种情况又统一成了一种情况,niubility啊!
  26. y = y + ystep
  27. error = error -1

接下来解释一下为什么可以将上面的两种情况统一
第二种情况的判断条件是,,其中 ,
写成


更新条件是

写成

所以

1.4 最佳化(所有的浮点计算全部转为整数运算)

image_1di2rn6qnou27bjuqaff617lu3u.png-9.2kB

  1. function line(x0, x1, y0, y1)
  2. boolean steep := abs(y1 - y0) > abs(x1 - x0)
  3. if steep then
  4. swap(x0, y0)
  5. swap(x1, y1)
  6. if x0 > x1 then
  7. swap(x0, x1)
  8. swap(y0, y1)
  9. int deltax := x1 - x0
  10. int deltay := abs(y1 - y0)
  11. int error := deltax / 2
  12. int ystep
  13. int y := y0
  14. if y0 < y1 then ystep := 1 else ystep := -1
  15. for x from x0 to x1
  16. if steep then plot(y,x) else plot(x,y)
  17. error := error - deltay
  18. if error < 0 then
  19. y := y + ystep
  20. error := error + deltax

理解这个算法转换的核心是将判断条件,写成


所以,写成

误差写成

2 应用

在珊格地图中,已知起止点(当前激光束测量数据)就可以使用bresenham算法得到两点之间的通过点,进而利用概率知识更新对应格子的概率值,得到珊格地图。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注