31 #include "util/math/fife_math.h"
32 #include "util/log/logger.h"
37 static Logger _log(LM_HEXGRID);
39 static const double HEX_WIDTH = 1;
40 static const double HEX_TO_EDGE = HEX_WIDTH / 2;
41 static const double HEX_TO_CORNER = 0.5 / Mathd::Cos(Mathd::pi() / 6);
42 static const double HEX_EDGE_HALF = HEX_TO_CORNER * Mathd::Sin(Mathd::pi() / 6);
43 static const double VERTICAL_MULTIP = sqrt(HEX_WIDTH*HEX_WIDTH - HEX_TO_EDGE*HEX_TO_EDGE);
44 static const double VERTICAL_MULTIP_INV = 1 / VERTICAL_MULTIP;
46 HexGrid::HexGrid(
bool allow_diagonals): CellGrid(allow_diagonals) {
47 FL_DBG(_log,
"Constructing new HexGrid");
48 FL_DBG(_log, LMsg(
"HEX_WIDTH ") << HEX_WIDTH);
49 FL_DBG(_log, LMsg(
"HEX_TO_EDGE ") << HEX_TO_EDGE);
50 FL_DBG(_log, LMsg(
"HEX_TO_CORNER ") << HEX_TO_CORNER);
51 FL_DBG(_log, LMsg(
"HEX_EDGE_HALF ") << HEX_EDGE_HALF);
52 FL_DBG(_log, LMsg(
"VERTICAL_MULTIP ") << VERTICAL_MULTIP);
55 CellGrid* HexGrid::clone() {
56 return new HexGrid(
this);
62 bool HexGrid::isAccessible(
const ModelCoordinate& curpos,
const ModelCoordinate& target) {
63 if (curpos == target) {
69 if((curpos.x == target.x) && (curpos.y - 1 == target.y)) {
73 if((curpos.x + 1 == target.x) && (curpos.y - 1 == target.y)) {
77 if((curpos.x + 1 == target.x) && (curpos.y == target.y)) {
81 if((curpos.x + 1 == target.x) && (curpos.y + 1 == target.y)) {
85 if((curpos.x == target.x) && (curpos.y + 1 == target.y)) {
89 if((curpos.x - 1 == target.x) && (curpos.y == target.y)) {
95 if((curpos.x - 1 == target.x) && (curpos.y - 1 == target.y)) {
99 if((curpos.x == target.x) && (curpos.y - 1 == target.y)) {
103 if((curpos.x + 1 == target.x) && (curpos.y == target.y)) {
107 if((curpos.x == target.x) && (curpos.y + 1 == target.y)) {
111 if((curpos.x - 1 == target.x) && (curpos.y + 1 == target.y)) {
115 if((curpos.x - 1 == target.x) && (curpos.y == target.y)) {
124 float HexGrid::getAdjacentCost(
const ModelCoordinate& curpos,
const ModelCoordinate& target) {
125 assert(isAccessible(curpos, target));
126 if (curpos == target) {
128 }
else if (curpos.y == target.y) {
131 double a = VERTICAL_MULTIP * m_yscale;
132 double b = HEX_TO_EDGE * m_xscale;
133 return sqrt((a * a) + (b * b));
137 const std::string& HexGrid::getType()
const {
138 static std::string type(
"hexagonal");
142 const std::string& HexGrid::getName()
const {
143 static std::string hexGrid(
"Hex Grid");
147 double HexGrid::getXZigzagOffset(
double y) {
151 int i_layer_y =
static_cast<int>(ay);
152 double offset = ay -
static_cast<double>(i_layer_y);
153 if ((i_layer_y % 2) == 1) {
156 return HEX_TO_EDGE * offset;
159 ExactModelCoordinate HexGrid::toMapCoordinates(
const ExactModelCoordinate& layer_coords) {
160 ExactModelCoordinate tranformed_coords(layer_coords);
161 tranformed_coords.x += getXZigzagOffset(layer_coords.y);
162 tranformed_coords.y *= VERTICAL_MULTIP;
163 ExactModelCoordinate result = m_matrix * tranformed_coords;
164 FL_DBG(_log, LMsg(
"layercoords ") << layer_coords <<
" converted to map: " << result);
168 ExactModelCoordinate HexGrid::toExactLayerCoordinates(
const ExactModelCoordinate& map_coord) {
169 ExactModelCoordinate layer_coords = m_inverse_matrix * map_coord;
170 layer_coords.y /= VERTICAL_MULTIP;
171 layer_coords.x -= getXZigzagOffset(layer_coords.y);
172 FL_DBG(_log, LMsg(
"mapcoords ") << map_coord <<
" converted to layer: " << layer_coords);
176 ModelCoordinate HexGrid::toLayerCoordinates(
const ExactModelCoordinate& map_coord) {
177 FL_DBG(_log, LMsg(
"==============\nConverting map coords ") << map_coord <<
" to int layer coords...");
178 ExactModelCoordinate elc = m_inverse_matrix * map_coord;
179 elc.y *= VERTICAL_MULTIP_INV;
180 ExactModelCoordinate lc = ExactModelCoordinate(floor(elc.x), floor(elc.y));
181 double dx = elc.x - lc.x;
182 double dy = elc.y - lc.y;
183 int x =
static_cast<int>(lc.x);
184 int y =
static_cast<int>(lc.y);
185 FL_DBG(_log, LMsg(
"elc=") << elc <<
", lc=" << lc);
186 FL_DBG(_log, LMsg(
"x=") << x <<
", y=" << y <<
", dx=" << dx <<
", dy=" << dy);
187 ModelCoordinate result;
190 FL_DBG(_log,
"In even row");
191 if ((1 - dy) < HEX_EDGE_HALF) {
192 FL_DBG(_log,
"In lower rect area");
193 result = ModelCoordinate(x, y+1);
195 else if (dy < HEX_EDGE_HALF) {
196 FL_DBG(_log,
"In upper rect area");
198 FL_DBG(_log,
"...on right");
199 result = ModelCoordinate(x+1, y);
202 FL_DBG(_log,
"...on left");
203 result = ModelCoordinate(x, y);
208 FL_DBG(_log,
"In middle triangle area");
210 FL_DBG(_log,
"In left triangles");
211 if (ptInTriangle(ExactModelCoordinate(dx, dy),
212 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
213 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
214 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
216 FL_DBG(_log,
"..upper part");
217 result = ModelCoordinate(x, y);
219 FL_DBG(_log,
"..lower part");
220 result = ModelCoordinate(x, y+1);
223 FL_DBG(_log,
"In right triangles");
224 if (ptInTriangle(ExactModelCoordinate(dx, dy),
225 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
226 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
227 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
229 FL_DBG(_log,
"..upper part");
230 result = ModelCoordinate(x+1, y);
232 FL_DBG(_log,
"..lower part");
233 result = ModelCoordinate(x, y+1);
239 FL_DBG(_log,
"In uneven row");
240 if (dy < HEX_EDGE_HALF) {
241 FL_DBG(_log,
"In upper rect area");
242 result = ModelCoordinate(x, y);
244 else if ((1 - dy) < HEX_EDGE_HALF) {
245 FL_DBG(_log,
"In lower rect area");
247 FL_DBG(_log,
"...on right");
248 result = ModelCoordinate(x+1, y+1);
251 FL_DBG(_log,
"...on left");
252 result = ModelCoordinate(x, y+1);
256 FL_DBG(_log,
"In middle triangle area");
258 FL_DBG(_log,
"In left triangles");
259 if (ptInTriangle(ExactModelCoordinate(dx, dy),
260 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
261 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
262 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
264 FL_DBG(_log,
"..lower part");
265 result = ModelCoordinate(x, y+1);
267 FL_DBG(_log,
"..upper part");
268 result = ModelCoordinate(x, y);
271 FL_DBG(_log,
"In right triangles");
272 if (ptInTriangle(ExactModelCoordinate(dx, dy),
273 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
274 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
275 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
277 FL_DBG(_log,
"..lower part");
278 result = ModelCoordinate(x+1, y+1);
280 FL_DBG(_log,
"..upper part");
281 result = ModelCoordinate(x, y);
286 FL_DBG(_log, LMsg(
" result = ") << result);
290 void HexGrid::getVertices(std::vector<ExactModelCoordinate>& vtx,
const ModelCoordinate& cell) {
291 FL_DBG(_log, LMsg(
"===============\ngetting vertices for ") << cell);
293 double x =
static_cast<double>(cell.x);
294 double y =
static_cast<double>(cell.y);
295 double horiz_shift = 0;
296 if (cell.y % 2 != 0) {
297 horiz_shift = HEX_TO_EDGE;
298 FL_DBG(_log,
"on uneven row");
302 #define ADD_PT(_x, _y) vtx.push_back(ExactModelCoordinate(_x, _y));
304 ty = y - VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
305 tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
308 ty = y - VERTICAL_MULTIP_INV * HEX_TO_CORNER;
309 tx = x - getXZigzagOffset(ty) + horiz_shift;
312 ty = y - VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
313 tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
316 ty = y + VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
317 tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
320 ty = y + VERTICAL_MULTIP_INV * HEX_TO_CORNER;
321 tx = x - getXZigzagOffset(ty) + horiz_shift;
324 ty = y + VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
325 tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;