在路徑規划、游戲設計柵格法應用中,正六邊形網格不如矩形網格直接和常見,但是正六邊形具有自身的應用特點,更適用於一些特殊場景中,比如曠闊的海洋、區域或者太空。本文主要講述如何對正六邊形進行幾何學分析、網格化環境建模、坐標系轉換以及正六邊形間的關系求解等。六邊形的具體代碼實現可以參見github: https://github.com/wylloong/HexagonalGrids .
幾何學分析:正六邊形的邊長相等,內角都是120度,其它性質可以參見百度百科。在正六邊形網格化布局設計中,典型的正六邊形方向有水平方向(pointy topped,圖1)和垂直方向(flat topped,圖2)兩類,兩者性質類似。篇幅所限,本文主要討論pointy topped類型的正六邊形網格化布局。

圖 1. pointy topped

圖 2. flat topped
如圖3所示的正六邊形布局,針對pointy topped型的正六邊形,設其邊長為size,則六邊形的寬width=sqrt(3)/2*size,和相鄰六邊形的水平距離hori=sqrt(3)/2*size,六邊形的高是height=size*2,和相鄰六邊形的垂直距離是vert=1.5*size。

圖 3. pointy topped型的正六邊形幾何示意圖
坐標系選擇:假設實現六邊形網格化,那么六邊形位置關系的表達有很多方式,有Offset coordinates、Cube coordinates、Axial coordinates等。本文推薦使用Cube coordinates作為主要的展示方式,Axial coordinates作為網格存儲單位和顯示坐標系。
Offset coordinates:最常用的坐標系,以左上角為坐標系原點,以橫向為column軸,以縱向為roe軸,對行和列進行偏置。其中,針對flat topped型的正六邊形,具有奇和偶兩種表示方式,如下圖所示。

Cube coordinates:一種全新的看待正六邊形的方式,它把正六邊形看作具有三個軸,並且滿足x+y+z=0的性質,並且我們可以使用標准的方法實現坐標系的加減乘除和求距離。Cube坐標系的原理和其它性質可以參見文獻。

因為我們已經有針對方形網格和cube網格的計算方法,使用cube坐標系允許我們對六邊形采用這些算法。當這個算法要和其他坐標系交互時,我會把其他坐標系轉換為cube坐標系,然后計算結束后在轉換為其他坐標系。
Axial coordinates:該坐標系是由cube坐標系中三個軸中的兩個組成的。因為在cube坐標系有x+y+z=0的限制,所以第三個軸是多余的。Axial coordinates主要應用於地圖存儲和對用戶的顯示。
Axial coordinates相比offset grids的優點是坐標系更清楚,劣勢是當存儲一個長方形地圖時顯得有點怪異。
總結:Offset coordinates因為符合square grids通用的笛卡爾坐標系,是我們最容易想到的坐標系,但是因為兩軸中的一軸必須跟隨變化,是一件復雜的事情;Cube and axial systems隨着增長而變化並且具有相對簡單的計算方法,但是在存儲時具有一定的復雜度。

Coordinate conversion:我們通常在項目中使用axial or offset coordinates,但是很多算法使用cube坐標系更容易去表達,所以我們需要在坐標系之間轉換。
Axial coordinates和cube coordinates聯系緊密,所以轉換公式相對簡單。

Offset coordinates和cube coordinates轉換有點復雜。本文主要針對even-q offset和odd-q offset進行研究。

鄰近網格:cube coordinates容易求出相鄰的6個鄰近正六邊形網格,但是offset坐標系卻比較復雜。
Cube coordinates:在正六邊形上移動一個網格,涉及到改變cube坐標系中兩個軸,一個+1,另一個-1,所以共有六種可能性,每一種可能性對應於六邊形的一個方向。

Axial coordinates:如前所示,我們以cube為起點,由cube轉換為axil坐標系即可,如下圖所示。

Distance: 在cube坐標系中,每一個六邊形是一個在cube里面的3d空間。在六邊形中相鄰的六邊形距離是1,但是在cube grid里面距離是2,這會讓距離求解變得簡單和快速。
在square grid中,Manhattan distances are abs(dx) + abs(dy). In a cube grid, Manhattan distances are abs(dx) + abs(dy) + abs(dz).
所以,在cube坐標系中,距離可以表示為

在Axial coordinates,第三個坐標系是缺省的,所以通用的做法是先轉變為cube坐標系,再求距離。

在offset坐標系中,正如Axial coordinates坐標系,我們把offset轉變為cube坐標系再求取距離。

路徑規划:如果使用基於圖論的A*或者Dijkstra算法,在六邊形中尋找最短路徑和正方形網格並沒有太多不同。其中,不同的是鄰近網格位置獲取方法不同,需要用到前面的方法獲取臨近網格。
啟發函數:A*算法使用heuristic功能求出兩個位置的距離。可以使用距離公式求出距離,乘以移動代價。
參考文獻和資料:
2、Her I. Geometric transformations on the hexagonal grid[J]. IEEE Transactions on Image Processing A Publication of the IEEE Signal Processing Society, 1995, 4(9):1213-22.