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 = Mathd::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 HexGrid* nGrid =
new HexGrid(m_allow_diagonals);
57 nGrid->setRotation(m_rotation);
58 nGrid->setXScale(m_xscale);
59 nGrid->setYScale(m_yscale);
60 nGrid->setXShift(m_xshift);
61 nGrid->setYShift(m_yshift);
62 nGrid->setZShift(m_zshift);
70 bool HexGrid::isAccessible(
const ModelCoordinate& curpos,
const ModelCoordinate& target) {
71 if (curpos == target) {
77 if((curpos.x == target.x) && (curpos.y - 1 == target.y)) {
81 if((curpos.x + 1 == target.x) && (curpos.y - 1 == target.y)) {
85 if((curpos.x + 1 == target.x) && (curpos.y == target.y)) {
89 if((curpos.x + 1 == target.x) && (curpos.y + 1 == target.y)) {
93 if((curpos.x == target.x) && (curpos.y + 1 == target.y)) {
97 if((curpos.x - 1 == target.x) && (curpos.y == target.y)) {
103 if((curpos.x - 1 == target.x) && (curpos.y - 1 == target.y)) {
107 if((curpos.x == target.x) && (curpos.y - 1 == target.y)) {
111 if((curpos.x + 1 == target.x) && (curpos.y == target.y)) {
115 if((curpos.x == target.x) && (curpos.y + 1 == target.y)) {
119 if((curpos.x - 1 == target.x) && (curpos.y + 1 == target.y)) {
123 if((curpos.x - 1 == target.x) && (curpos.y == target.y)) {
132 double HexGrid::getAdjacentCost(
const ModelCoordinate& curpos,
const ModelCoordinate& target) {
133 assert(isAccessible(curpos, target));
134 if (curpos == target) {
136 }
else if (curpos.y == target.y) {
139 double a = VERTICAL_MULTIP * m_yscale;
140 double b = HEX_TO_EDGE * m_xscale;
141 return Mathd::Sqrt((a * a) + (b * b));
145 const std::string& HexGrid::getType()
const {
146 static std::string type(
"hexagonal");
150 const std::string& HexGrid::getName()
const {
151 static std::string hexGrid(
"Hex Grid");
155 double HexGrid::getXZigzagOffset(
double y) {
159 int32_t i_layer_y =
static_cast<int32_t
>(ay);
160 double offset = ay -
static_cast<double>(i_layer_y);
161 if ((i_layer_y % 2) == 1) {
164 return HEX_TO_EDGE * offset;
167 ExactModelCoordinate HexGrid::toMapCoordinates(
const ExactModelCoordinate& layer_coords) {
168 ExactModelCoordinate tranformed_coords(layer_coords);
169 tranformed_coords.x += getXZigzagOffset(layer_coords.y);
170 tranformed_coords.y *= VERTICAL_MULTIP;
171 ExactModelCoordinate result = m_matrix * tranformed_coords;
172 FL_DBG(_log, LMsg(
"layercoords ") << layer_coords <<
" converted to map: " << result);
176 ExactModelCoordinate HexGrid::toExactLayerCoordinates(
const ExactModelCoordinate& map_coord) {
177 ExactModelCoordinate layer_coords = m_inverse_matrix * map_coord;
178 layer_coords.y /= VERTICAL_MULTIP;
179 layer_coords.x -= getXZigzagOffset(layer_coords.y);
180 FL_DBG(_log, LMsg(
"mapcoords ") << map_coord <<
" converted to layer: " << layer_coords);
184 ModelCoordinate HexGrid::toLayerCoordinates(
const ExactModelCoordinate& map_coord) {
185 FL_DBG(_log, LMsg(
"==============\nConverting map coords ") << map_coord <<
" to int32_t layer coords...");
186 ExactModelCoordinate elc = m_inverse_matrix * map_coord;
187 elc.y *= VERTICAL_MULTIP_INV;
188 ExactModelCoordinate lc = ExactModelCoordinate(floor(elc.x), floor(elc.y), floor(elc.z));
189 double dx = elc.x - lc.x;
190 double dy = elc.y - lc.y;
191 double dz = elc.z - lc.z;
192 int32_t x =
static_cast<int32_t
>(lc.x);
193 int32_t y =
static_cast<int32_t
>(lc.y);
194 int32_t z =
static_cast<int32_t
>(lc.z);
197 ModelCoordinate result;
201 if ((1 - dy) < HEX_EDGE_HALF) {
202 FL_DBG(_log,
"In lower rect area");
203 result = ModelCoordinate(x, y+1, z);
205 else if (dy < HEX_EDGE_HALF) {
209 result = ModelCoordinate(x+1, y, z);
213 result = ModelCoordinate(x, y, z);
221 if (ptInTriangle(ExactModelCoordinate(dx, dy),
222 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
223 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
224 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
227 result = ModelCoordinate(x, y, z);
230 result = ModelCoordinate(x, y+1, z);
234 if (ptInTriangle(ExactModelCoordinate(dx, dy),
235 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
236 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
237 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
240 result = ModelCoordinate(x+1, y, z);
243 result = ModelCoordinate(x, y+1, z);
250 if (dy < HEX_EDGE_HALF) {
252 result = ModelCoordinate(x, y, z);
254 else if ((1 - dy) < HEX_EDGE_HALF) {
258 result = ModelCoordinate(x+1, y+1, z);
262 result = ModelCoordinate(x, y+1, z);
269 if (ptInTriangle(ExactModelCoordinate(dx, dy),
270 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
271 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
272 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
275 result = ModelCoordinate(x, y+1, z);
278 result = ModelCoordinate(x, y, z);
282 if (ptInTriangle(ExactModelCoordinate(dx, dy),
283 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
284 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
285 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
288 result = ModelCoordinate(x+1, y+1, z);
291 result = ModelCoordinate(x, y, z);
300 void HexGrid::getVertices(std::vector<ExactModelCoordinate>& vtx,
const ModelCoordinate& cell) {
301 FL_DBG(_log, LMsg(
"===============\ngetting vertices for ") << cell);
303 double x =
static_cast<double>(cell.x);
304 double y =
static_cast<double>(cell.y);
305 double horiz_shift = 0;
306 if (cell.y % 2 != 0) {
307 horiz_shift = HEX_TO_EDGE;
308 FL_DBG(_log,
"on uneven row");
312 #define ADD_PT(_x, _y) vtx.push_back(ExactModelCoordinate(_x, _y));
314 ty = y - VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
315 tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
318 ty = y - VERTICAL_MULTIP_INV * HEX_TO_CORNER;
319 tx = x - getXZigzagOffset(ty) + horiz_shift;
322 ty = y - VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
323 tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
326 ty = y + VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
327 tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
330 ty = y + VERTICAL_MULTIP_INV * HEX_TO_CORNER;
331 tx = x - getXZigzagOffset(ty) + horiz_shift;
334 ty = y + VERTICAL_MULTIP_INV * HEX_EDGE_HALF;
335 tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...