一种平面六边形网格坐标系统的C++实现


一、源代码

1. hexagonal_grid.h

 1 #ifndef _HEXAGONAL_GRID_HEADER
 2 #define _HEXAGONAL_GRID_HEADER
 3 
 4 class class_hexagonal_grid
 5 {
 6 public:
 7     class_hexagonal_grid() = delete;
 8     ~class_hexagonal_grid();
 9     class_hexagonal_grid(const class_hexagonal_grid &) = delete;
10     class_hexagonal_grid & operator=(const class_hexagonal_grid &) = delete;
11     explicit class_hexagonal_grid(unsigned);
12 
13 public:
14     unsigned property_number() const;
15 
16     // parameter: direction number
17     // return >= 0: target neighbor grid's number
18     // return = -1: neighbor does not exist
19     int property_neighbor_num(unsigned) const;
20     class_hexagonal_grid * property_neighbor_pointer(unsigned) const;
21     unsigned property_position_x() const;
22     unsigned property_position_y() const;
23 
24     // parameter 1: direction number
25     // parameter 2: neighbor-grid's pointer
26     void function_set_neighbor(unsigned, class_hexagonal_grid * const);
27 
28     // parameter 1: position x
29     // parameter 2: position y
30     void function_set_position(unsigned, unsigned);
31 
32 private:
33     unsigned _uint_num;
34     class_hexagonal_grid * _pointer_array_neighbors[6];
35     unsigned _uint_position_x;
36     unsigned _uint_position_y;
37 };
38 
39 #endif // !_HEXAGONAL_GRID_HEADER

2. hexagonal_grid.cpp

 1 #include "hexagonal_grid.h"
 2 
 3 class_hexagonal_grid::~class_hexagonal_grid()
 4 {
 5 }
 6 
 7 class_hexagonal_grid::class_hexagonal_grid(unsigned uint_num) :
 8     _uint_num(uint_num),
 9     _pointer_array_neighbors{ nullptr },
10     _uint_position_x(0),
11     _uint_position_y(0)
12 {
13 }
14 
15 unsigned class_hexagonal_grid::property_number() const
16 {
17     return _uint_num;
18 }
19 
20 int class_hexagonal_grid::property_neighbor_num(unsigned uint_direc) const
21 {
22     uint_direc %= 6;
23     if (nullptr == _pointer_array_neighbors[uint_direc])
24     {
25         return -1;
26     }
27     return (signed)(_pointer_array_neighbors[uint_direc]->property_number());
28 }
29 
30 class_hexagonal_grid * class_hexagonal_grid::property_neighbor_pointer(unsigned uint_direc) const
31 {
32     uint_direc %= 6;
33     return _pointer_array_neighbors[uint_direc];
34 }
35 
36 unsigned class_hexagonal_grid::property_position_x() const
37 {
38     return _uint_position_x;
39 }
40 
41 unsigned class_hexagonal_grid::property_position_y() const
42 {
43     return _uint_position_y;
44 }
45 
46 void class_hexagonal_grid::function_set_neighbor(unsigned uint_direction, class_hexagonal_grid * const pointer_neighbor_grid)
47 {
48     if (nullptr != pointer_neighbor_grid)
49     {
50         pointer_neighbor_grid->_pointer_array_neighbors[(uint_direction + 3) % 6] = this;
51     }
52     _pointer_array_neighbors[uint_direction % 6] = pointer_neighbor_grid;
53 }
54 
55 void class_hexagonal_grid::function_set_position(unsigned uint_x, unsigned uint_y)
56 {
57     _uint_position_x = uint_x;
58     _uint_position_y = uint_y;
59 }

3. hexagonal_network.h

 1 #ifndef _HEXAGONAL_NETWORK_HEADER
 2 #define _HEXAGONAL_NETWORK_HEADER
 3 
 4 #include "hexagonal_grid.h"
 5 
 6 #include <vector>
 7 
 8 class class_hexagonal_network
 9 {
10 public:
11     class_hexagonal_network() = delete;
12     ~class_hexagonal_network();
13     class_hexagonal_network(const class_hexagonal_network &);
14     class_hexagonal_network & operator=(const class_hexagonal_network &);
15     explicit class_hexagonal_network(unsigned);
16 
17 public:
18     static unsigned function_calculate_max_grid_count_from_layer(unsigned);
19 
20 public:
21     unsigned property_layer() const;
22     unsigned property_size() const;
23 
24 public:
25     // parameter 1: source grid number
26     // parameter 2: direction number
27     // return >= 0: target neighbor grid number
28     // return = -1: neighbor does not exist
29     // return = -2: source does not exist
30     int function_get_neighbor_number(unsigned, unsigned) const;
31     // parameter 1: source grid number
32     // parameter 2: horizontal position
33     // parameter 3: vertical position
34     // return = 0: operation succeeded
35     // return = -1: source does not exist
36     int function_get_grid_position(unsigned, unsigned &, unsigned &) const;
37 
38 private:
39     unsigned _uint_layer;
40     std::vector<class_hexagonal_grid *> _vector_hexagonal_grids;
41 
42 private:
43     void _function_generate_grids(unsigned);
44     void _function_set_grids_position();
45 };
46 
47 #endif // !_HEXAGONAL_NETWORK_HEADER

4. hexagonal_network.cpp

  1 #include "hexagonal_network.h"
  2 
  3 class_hexagonal_network::~class_hexagonal_network()
  4 {
  5     for (auto it_grid = _vector_hexagonal_grids.begin(); it_grid != _vector_hexagonal_grids.end(); it_grid++)
  6     {
  7         delete *it_grid;
  8     }
  9 }
 10 
 11 class_hexagonal_network::class_hexagonal_network(const class_hexagonal_network & another_network):
 12     _uint_layer(another_network._uint_layer),
 13     _vector_hexagonal_grids(std::vector<class_hexagonal_grid *>(another_network._vector_hexagonal_grids.size()))
 14 {
 15     _function_generate_grids(_uint_layer);
 16     _function_set_grids_position();
 17 }
 18 
 19 class_hexagonal_network & class_hexagonal_network::operator=(const class_hexagonal_network & another_network)
 20 {
 21     if (this != & another_network)
 22     {
 23         _function_generate_grids(another_network.property_layer());
 24         _function_set_grids_position();
 25     }
 26     return  * this;
 27 }
 28 
 29 class_hexagonal_network::class_hexagonal_network(unsigned uint_layer):
 30     _uint_layer(uint_layer),
 31     _vector_hexagonal_grids(std::vector<class_hexagonal_grid *>(function_calculate_max_grid_count_from_layer(uint_layer)))
 32 {
 33     _function_generate_grids(uint_layer);
 34     _function_set_grids_position();
 35 }
 36 
 37 unsigned class_hexagonal_network::function_calculate_max_grid_count_from_layer(unsigned uint_layer)
 38 {
 39     switch (uint_layer)
 40     {
 41     case 0:
 42         return 0;
 43     default:
 44         return 3 * uint_layer * (uint_layer - 1) + 1;
 45     }
 46 }
 47 
 48 unsigned class_hexagonal_network::property_layer() const
 49 {
 50     return _uint_layer;
 51 }
 52 
 53 unsigned class_hexagonal_network::property_size() const
 54 {
 55     return function_calculate_max_grid_count_from_layer(_uint_layer);
 56 }
 57 
 58 int class_hexagonal_network::function_get_neighbor_number(unsigned uint_sou_num, unsigned uint_direc) const
 59 {
 60     if (uint_sou_num >= _vector_hexagonal_grids.size())
 61     {
 62         return -2;
 63     }
 64     return _vector_hexagonal_grids[uint_sou_num]->property_neighbor_num(uint_direc);
 65 }
 66 
 67 int class_hexagonal_network::function_get_grid_position(unsigned uint_sou_num, unsigned & x, unsigned & y) const
 68 {
 69     if (uint_sou_num >= _vector_hexagonal_grids.size())
 70     {
 71         return -1;
 72     }
 73     x = _vector_hexagonal_grids[uint_sou_num]->property_position_x();
 74     y = _vector_hexagonal_grids[uint_sou_num]->property_position_y();
 75     return 0;
 76 }
 77 
 78 void class_hexagonal_network::_function_generate_grids(unsigned uint_layer)
 79 {
 80     switch (uint_layer)
 81     {
 82     case 0:
 83         return;
 84     }
 85 
 86     // 1. allocate memory
 87     for (unsigned i_grid = 0; i_grid < _vector_hexagonal_grids.size(); i_grid++)
 88     {
 89         _vector_hexagonal_grids[i_grid] = new class_hexagonal_grid(i_grid);
 90     }
 91     switch (uint_layer)
 92     {
 93     case 1:
 94         return;
 95     }
 96 
 97     // 2. connect within 2 layer
 98     for (unsigned i_direc = 0; i_direc < 6; i_direc++)
 99     {
100         (*_vector_hexagonal_grids.begin())->function_set_neighbor(i_direc, _vector_hexagonal_grids[i_direc + 1]);
101         _vector_hexagonal_grids[i_direc + 1]->function_set_neighbor(i_direc + 2, _vector_hexagonal_grids[(i_direc + 1) % 6 + 1]);
102     }
103     switch (uint_layer)
104     {
105     case 2:
106         return;
107     }
108 
109     // 3. connect with outer layer grids in counter-clockwise
110     
111     // current vertex grid number
112     int cvgn;
113     // outer vertex grid number
114     int ovgn;
115     for (unsigned i_layer = 1; i_layer < uint_layer - 1; i_layer++)
116     {
117         for (unsigned i_direc = 0; i_direc < 6; i_direc++)
118         {
119             // vertex grids add one
120             cvgn = function_calculate_max_grid_count_from_layer(i_layer) + i_direc * i_layer;
121             ovgn = function_calculate_max_grid_count_from_layer(i_layer + 1) + i_direc * (i_layer + 1);
122             _vector_hexagonal_grids[cvgn]->function_set_neighbor(i_direc, _vector_hexagonal_grids[ovgn]);
123             // all grids in counter-clockwise
124             for (unsigned i_subse = 0; i_subse < i_layer; i_subse++)
125             {
126                 _vector_hexagonal_grids[cvgn + i_subse]->function_set_neighbor(i_direc + 1, _vector_hexagonal_grids[ovgn + i_subse + 1]);
127             }
128         }
129     }
130 
131     // 4. connect with current layer grids && inner layer grids in counter-clockwise
132     
133     // inner layer start
134     int ils;
135     // current layer start
136     int cls;
137     // outer layer start
138     int ols;
139     // inner vertex grid number
140     int ivgn;
141     for (unsigned i_layer = 2; i_layer < uint_layer; i_layer++)
142     {
143         for (unsigned i_direc = 0; i_direc < 5; i_direc++)
144         {
145             ivgn = function_calculate_max_grid_count_from_layer(i_layer - 1) + i_direc * (i_layer - 1);
146             cvgn = function_calculate_max_grid_count_from_layer(i_layer) + i_direc * i_layer;
147             _vector_hexagonal_grids[cvgn]->function_set_neighbor(i_direc + 2, _vector_hexagonal_grids[cvgn + 1]);
148             for (unsigned i_subse = 1; i_subse < i_layer; i_subse++)
149             {
150                 _vector_hexagonal_grids[cvgn + i_subse]->function_set_neighbor(i_direc + 2, _vector_hexagonal_grids[cvgn + i_subse + 1]);
151                 _vector_hexagonal_grids[cvgn + i_subse]->function_set_neighbor(i_direc + 3, _vector_hexagonal_grids[ivgn + i_subse]);
152             }
153         }
154         // sector 6
155         ivgn = function_calculate_max_grid_count_from_layer(i_layer - 1) + 5 * (i_layer - 1);
156         cvgn = function_calculate_max_grid_count_from_layer(i_layer) + 5 * i_layer;
157         _vector_hexagonal_grids[cvgn]->function_set_neighbor(1, _vector_hexagonal_grids[cvgn + 1]);
158         for (unsigned i_subse = 1; i_subse < i_layer - 1; i_subse++)
159         {
160             _vector_hexagonal_grids[cvgn + i_subse]->function_set_neighbor(1, _vector_hexagonal_grids[cvgn + i_subse + 1]);
161             _vector_hexagonal_grids[cvgn + i_subse]->function_set_neighbor(2, _vector_hexagonal_grids[ivgn + i_subse]);
162         }
163         // last one
164         ils = function_calculate_max_grid_count_from_layer(i_layer - 1);
165         cls = function_calculate_max_grid_count_from_layer(i_layer);
166         ols = function_calculate_max_grid_count_from_layer(i_layer + 1);
167         _vector_hexagonal_grids[ols - 1]->function_set_neighbor(1, _vector_hexagonal_grids[cls]);
168         _vector_hexagonal_grids[ols - 1]->function_set_neighbor(2, _vector_hexagonal_grids[ils]);
169     }
170 }
171 
172 void class_hexagonal_network::_function_set_grids_position()
173 {
174     switch (_uint_layer)
175     {
176     case 0:
177         return;
178     }
179 
180     // move to center left
181 
182     class_hexagonal_grid * p_grid = _vector_hexagonal_grids[0];
183     while (p_grid->property_neighbor_pointer(3) != nullptr)
184     {
185         p_grid = p_grid->property_neighbor_pointer(3);
186     }
187     p_grid->function_set_position(0, _uint_layer - 1);
188     switch (_uint_layer)
189     {
190     case 1:
191         return;
192     }
193 
194     // up && down
195 
196     unsigned x_start = 0, x = 0, y_up = _uint_layer - 1, y_down = y_up;
197     class_hexagonal_grid * p_grid_up_head = p_grid;
198     class_hexagonal_grid * p_grid_up = nullptr;
199     class_hexagonal_grid * p_grid_down_head = p_grid;
200     class_hexagonal_grid * p_grid_down = nullptr;
201     while (p_grid_up_head->property_neighbor_pointer(1) != nullptr)
202     {
203         p_grid_up_head = p_grid_up_head->property_neighbor_pointer(1);
204         p_grid_down_head = p_grid_down_head->property_neighbor_pointer(5);
205         y_up--;
206         y_down++;
207         x_start++;
208         x = x_start;
209         p_grid_up = p_grid_up_head;
210         p_grid_down = p_grid_down_head;
211         while (p_grid_up != nullptr)
212         {
213             p_grid_up->function_set_position(x, y_up);
214             p_grid_down->function_set_position(x, y_down);
215             p_grid_up = p_grid_up->property_neighbor_pointer(0);
216             p_grid_down = p_grid_down->property_neighbor_pointer(0);
217             x += 2;
218         }
219     }
220 
221     // center
222     x = 0;
223     while (p_grid->property_neighbor_pointer(0) != nullptr)
224     {
225         p_grid = p_grid->property_neighbor_pointer(0);
226         x += 2;
227         p_grid->function_set_position(x, _uint_layer - 1);
228     }
229 }

二、使用方法

1. 创建网格类对象

必须使用指定的单参数构造函数 explicit class_hexagonal_network(unsigned) 去创建一个六边形网格类的对象,参数为圈层数,见下图:

规则六边形网格的尺寸可由圈层数决定,其圈层数和网格数目可分别由 unsigned property_layer() const; unsigned property_size() const 两函数得到。

2. 获取临格索引

 每个格子都有一个索引(编号),通过 int function_get_neighbor_number(unsigned, unsigned) const 函数可以得到特定索引格子任意方向临格的索引,其排列规则如下图所示:

函数 function_get_neighbor_number 的第一个参数是指定格子的索引,其取值应在网格总数范围内(不包括总数),否则将返回 -2;第二个参数是方向,共六个方向如下图:

如果取到边界的格子,目标方向可能无临格,这时函数返回 -1。正常情况下,函数会返回目标临格的索引。

3. 获取坐标

网格类对象可用 int function_get_grid_position(unsigned, unsigned &, unsigned &) const 函数来获取格点的横纵坐标信息。第一个参数是格点索引,如果不在总数范围内函数将返回 -1;

第二个参数和第三个参数分别为该格点的横纵坐标值。正常执行完毕返回 0。坐标约定见下图:


三、功能测试

1. 测试代码

 1 #include <iostream>
 2 #include <string>
 3 
 4 #include "hexagonal_network.h"
 5 
 6 int main(int argc, char* argv[]) {
 7     class_hexagonal_network nw(4);
 8     unsigned x, y;
 9     for (unsigned i_grid = 0; i_grid < nw.property_size(); i_grid++)
10     {
11         nw.function_get_grid_position(i_grid, x, y);
12         std::cout << "grid " << i_grid << " at (" << x << ", " << y << "), neighbors: ";
13         for (unsigned i_direc = 0; i_direc < 6; i_direc++)
14         {
15             std::cout << nw.function_get_neighbor_number(i_grid, i_direc) << " ";
16         }
17         std::cout << std::endl;
18     }
19 
20     std::string str_pause;
21     std::getline(std::cin, str_pause);
22     return 0;
23 }

2. 输出结果

grid 0 at (6, 3), neighbors: 1 2 3 4 5 6
grid 1 at (8, 3), neighbors: 7 8 2 0 6 18
grid 2 at (7, 2), neighbors: 8 9 10 3 0 1
grid 3 at (5, 2), neighbors: 2 10 11 12 4 0
grid 4 at (4, 3), neighbors: 0 3 12 13 14 5
grid 5 at (5, 4), neighbors: 6 0 4 14 15 16
grid 6 at (7, 4), neighbors: 18 1 0 5 16 17
grid 7 at (10, 3), neighbors: 19 20 8 1 18 36
grid 8 at (9, 2), neighbors: 20 21 9 2 1 7
grid 9 at (8, 1), neighbors: 21 22 23 10 2 8
grid 10 at (6, 1), neighbors: 9 23 24 11 3 2
grid 11 at (4, 1), neighbors: 10 24 25 26 12 3
grid 12 at (3, 2), neighbors: 3 11 26 27 13 4
grid 13 at (2, 3), neighbors: 4 12 27 28 29 14
grid 14 at (3, 4), neighbors: 5 4 13 29 30 15
grid 15 at (4, 5), neighbors: 16 5 14 30 31 32
grid 16 at (6, 5), neighbors: 17 6 5 15 32 33
grid 17 at (8, 5), neighbors: 35 18 6 16 33 34
grid 18 at (9, 4), neighbors: 36 7 1 6 17 35
grid 19 at (12, 3), neighbors: -1 -1 20 7 36 -1
grid 20 at (11, 2), neighbors: -1 -1 21 8 7 19
grid 21 at (10, 1), neighbors: -1 -1 22 9 8 20
grid 22 at (9, 0), neighbors: -1 -1 -1 23 9 21
grid 23 at (7, 0), neighbors: 22 -1 -1 24 10 9
grid 24 at (5, 0), neighbors: 23 -1 -1 25 11 10
grid 25 at (3, 0), neighbors: 24 -1 -1 -1 26 11
grid 26 at (2, 1), neighbors: 11 25 -1 -1 27 12
grid 27 at (1, 2), neighbors: 12 26 -1 -1 28 13
grid 28 at (0, 3), neighbors: 13 27 -1 -1 -1 29
grid 29 at (1, 4), neighbors: 14 13 28 -1 -1 30
grid 30 at (2, 5), neighbors: 15 14 29 -1 -1 31
grid 31 at (3, 6), neighbors: 32 15 30 -1 -1 -1
grid 32 at (5, 6), neighbors: 33 16 15 31 -1 -1
grid 33 at (7, 6), neighbors: 34 17 16 32 -1 -1
grid 34 at (9, 6), neighbors: -1 35 17 33 -1 -1
grid 35 at (10, 5), neighbors: -1 36 18 17 34 -1
grid 36 at (11, 4), neighbors: -1 19 7 18 35 -1

 

posted @ 2024-11-05 21:31  永恒月华  阅读(126)  评论(0)    收藏  举报