FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
hexgrid.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <cassert>
24 
25 // 3rd party library includes
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "util/math/fife_math.h"
32 #include "util/log/logger.h"
33 
34 #include "hexgrid.h"
35 
36 namespace FIFE {
37  static Logger _log(LM_HEXGRID);
38 
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);
44  static const double VERTICAL_MULTIP_INV = 1 / VERTICAL_MULTIP;
45  static const double HEX_EDGE_GRADIENT = 1 / Mathd::Sqrt(3);
46 
48  CellGrid() {
49  FL_DBG(_log, "Constructing new HexGrid");
50  FL_DBG(_log, LMsg("HEX_WIDTH ") << HEX_WIDTH);
51  FL_DBG(_log, LMsg("HEX_TO_EDGE ") << HEX_TO_EDGE);
52  FL_DBG(_log, LMsg("HEX_TO_CORNER ") << HEX_TO_CORNER);
53  FL_DBG(_log, LMsg("HEX_EDGE_HALF ") << HEX_EDGE_HALF);
54  FL_DBG(_log, LMsg("VERTICAL_MULTIP ") << VERTICAL_MULTIP);
55  }
56 
58  HexGrid* nGrid = new HexGrid();
59  nGrid->setRotation(m_rotation);
60  nGrid->setXScale(m_xscale);
61  nGrid->setYScale(m_yscale);
62  nGrid->setXShift(m_xshift);
63  nGrid->setYShift(m_yshift);
64  nGrid->setZShift(m_zshift);
66 
67  return nGrid;
68  }
69 
71  }
72 
73  bool HexGrid::isAccessible(const ModelCoordinate& curpos, const ModelCoordinate& target) {
74  int32_t x = target.x-curpos.x;
75  int32_t y = target.y-curpos.y;
76 
77  if (ABS(x) <= 1 && ABS(y) <= 1) {
78  if (y == 0) {
79  return true;
80  } else if (curpos.y & 1) {
81  if (x >= 0) return true;
82  } else if (x <= 0) return true;
83  }
84  return false;
85  }
86 
87  double HexGrid::getAdjacentCost(const ModelCoordinate& curpos, const ModelCoordinate& target) {
88  if (curpos == target) {
89  return 0.0;
90  }
91  return 1.0;
92  }
93 
94  double HexGrid::getHeuristicCost(const ModelCoordinate& curpos, const ModelCoordinate& target) {
95  return static_cast<double>(ABS(target.x - curpos.x) + ABS(target.y - curpos.y));
96  }
97 
98  const std::string& HexGrid::getType() const {
99  static std::string type("hexagonal");
100  return type;
101  }
102 
103  const std::string& HexGrid::getName() const {
104  static std::string hexGrid("Hex Grid");
105  return hexGrid;
106  }
107 
108  double HexGrid::getXZigzagOffset(double y) {
109  // each uneven row has shifted coordinate of 0.5 horizontally
110  // shift has to be gradual on vertical axis
111  double ay = ABS(y);
112  int32_t i_layer_y = static_cast<int32_t>(ay);
113  double offset = ay - static_cast<double>(i_layer_y);
114  if ((i_layer_y % 2) == 1) {
115  offset = 1 - offset;
116  }
117  return HEX_TO_EDGE * offset;
118  }
119 
121  ExactModelCoordinate tranformed_coords(layer_coords);
122  tranformed_coords.x += getXZigzagOffset(layer_coords.y);
123  tranformed_coords.y *= VERTICAL_MULTIP;
124  ExactModelCoordinate result = m_matrix * tranformed_coords;
125  FL_DBG(_log, LMsg("layercoords ") << layer_coords << " converted to map: " << result);
126  return result;
127  }
128 
130  ExactModelCoordinate layer_coords = m_inverse_matrix * map_coord;
131  layer_coords.y /= VERTICAL_MULTIP;
132  layer_coords.x -= getXZigzagOffset(layer_coords.y);
133  FL_DBG(_log, LMsg("mapcoords ") << map_coord << " converted to layer: " << layer_coords);
134  return layer_coords;
135  }
136 
138  FL_DBG(_log, LMsg("==============\nConverting map coords ") << map_coord << " to int32_t layer coords...");
139  ExactModelCoordinate elc = m_inverse_matrix * map_coord;
140  elc.y *= VERTICAL_MULTIP_INV;
141 
142  // approximate conversion using squares instead of hexes
143  if( static_cast<int32_t>(round(elc.y)) & 1 )
144  elc.x -= 0.5;
145  ExactModelCoordinate lc = ExactModelCoordinate(round(elc.x), round(elc.y), round(elc.z));
146 
147  int32_t x = static_cast<int32_t>(lc.x);
148  int32_t y = static_cast<int32_t>(lc.y);
149  int32_t z = static_cast<int32_t>(lc.z);
150 
151  // distance of given point from our approximation
152  // If y uneven dx=-dx and dy=-dy
153  double dx,dy;
154  if (y & 1) {
155  dx = elc.x - lc.x;
156  dy = elc.y - lc.y;
157  } else {
158  dx = lc.x - elc.x;
159  dy = lc.y - elc.y;
160  }
161 
162  // adjustment for cases where our approximation lies beyond the hex edge
163  if (ABS(dy) > ((HEX_TO_CORNER - HEX_EDGE_GRADIENT * ABS(dx)) * VERTICAL_MULTIP_INV)) {
164  int8_t ddx, ddy;
165  if (dx>0) ddx = -1;
166  else ddx = 0;
167 
168  if (dy>0) ddy = -1;
169  else ddy = 1;
170 
171  if (y & 1) {
172  ddx = -ddx;
173  ddy = -ddy;
174  }
175 
176  x += ddx;
177  y += ddy;
178  }
179 
180  return ModelCoordinate(x,y,z);
181  }
182 
183  void HexGrid::getVertices(std::vector<ExactModelCoordinate>& vtx, const ModelCoordinate& cell) {
184  FL_DBG(_log, LMsg("===============\ngetting vertices for ") << cell);
185  vtx.clear();
186  double x = static_cast<double>(cell.x);
187  double y = static_cast<double>(cell.y);
188  double horiz_shift = 0;
189  if (cell.y % 2 != 0) {
190  horiz_shift = HEX_TO_EDGE;
191  FL_DBG(_log, "on uneven row");
192  }
193  double tx, ty;
194 
195  #define ADD_PT(_x, _y) vtx.push_back(ExactModelCoordinate(_x, _y));
196  // FL_DBG(_log, LMsg("Added point ") << _x << ", " << _y)
198  tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
199  ADD_PT(tx, ty);
200 
202  tx = x - getXZigzagOffset(ty) + horiz_shift;
203  ADD_PT(tx, ty);
204 
206  tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
207  ADD_PT(tx, ty);
208 
210  tx = x + HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
211  ADD_PT(tx, ty);
212 
214  tx = x - getXZigzagOffset(ty) + horiz_shift;
215  ADD_PT(tx, ty);
216 
218  tx = x - HEX_TO_EDGE - getXZigzagOffset(ty) + horiz_shift;
219  ADD_PT(tx, ty);
220  }
221 
222  std::vector<ModelCoordinate> HexGrid::toMultiCoordinates(const ModelCoordinate& position, const std::vector<ModelCoordinate>& orig, bool reverse) {
223  std::vector<ModelCoordinate> coords;
224  std::vector<ModelCoordinate>::const_iterator it = orig.begin();
225  if (reverse) {
226  for (; it != orig.end(); ++it) {
227  ModelCoordinate mc = position;
228  if (mc.y % 2 != 0) {
229  mc.x -= (*it).x;
230  mc.y -= (*it).y;
231  if (mc.y % 2 == 0) {
232  mc.x -= 1;
233  }
234  } else {
235  mc.x -= (*it).x;
236  mc.y -= (*it).y;
237  }
238  coords.push_back(mc);
239  }
240  } else {
241  for (; it != orig.end(); ++it) {
242  ModelCoordinate mc = position;
243  if (mc.y % 2 != 0) {
244  mc.x += (*it).x;
245  mc.y += (*it).y;
246  if (mc.y % 2 == 0) {
247  mc.x += 1;
248  }
249  } else {
250  mc.x += (*it).x;
251  mc.y += (*it).y;
252  }
253  coords.push_back(mc);
254  }
255  }
256  return coords;
257  }
258 }
double m_xscale
Definition: cellgrid.h:243
virtual ~HexGrid()
Definition: hexgrid.cpp:70
static const double VERTICAL_MULTIP_INV
Definition: hexgrid.cpp:44
static T Cos(T _val)
Definition: fife_math.h:216
#define ABS(x)
Definition: fife_math.h:40
static T Sqrt(T _val)
Definition: fife_math.h:276
double getXZigzagOffset(double y)
Definition: hexgrid.cpp:108
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
void setZShift(const double zshift)
Set the cellgrid z shift.
Definition: cellgrid.h:156
double m_yshift
Definition: cellgrid.h:241
#define ADD_PT(_x, _y)
double getAdjacentCost(const ModelCoordinate &curpos, const ModelCoordinate &target)
Returns distance const from curpos to target point only cells adjacent to curpos are considered in th...
Definition: hexgrid.cpp:87
ExactModelCoordinate toExactLayerCoordinates(const ExactModelCoordinate &map_coord)
Transforms given point from map coordinates to layer coordinates.
Definition: hexgrid.cpp:129
std::vector< ModelCoordinate > toMultiCoordinates(const ModelCoordinate &position, const std::vector< ModelCoordinate > &orig, bool reverse)
Returns point vector with coordinates for a multi object.
Definition: hexgrid.cpp:222
static const double HEX_EDGE_GRADIENT
Definition: hexgrid.cpp:45
static Logger _log(LM_AUDIO)
DoubleMatrix m_inverse_matrix
Definition: cellgrid.h:239
void setXShift(const double &xshift)
Set the cellgrid x shift.
Definition: cellgrid.h:130
void setYScale(const double scale)
Set the cellgrid y-scaling.
Definition: cellgrid.h:177
ExactModelCoordinate toMapCoordinates(const ExactModelCoordinate &layer_coords)
Transforms given point from layer coordinates to map coordinates.
Definition: hexgrid.cpp:120
void setXScale(const double scale)
Set the cellgrid x-scaling.
Definition: cellgrid.h:169
static const double HEX_TO_EDGE
Definition: hexgrid.cpp:40
static const double HEX_WIDTH
Definition: hexgrid.cpp:39
void setYShift(const double yshift)
Set the cellgrid y shift.
Definition: cellgrid.h:143
Point3D ModelCoordinate
Definition: modelcoords.h:37
static T Sin(T _val)
Definition: fife_math.h:266
bool m_allow_diagonals
Definition: cellgrid.h:247
CellGrid * clone()
Returns clone of this cellgrid.
Definition: hexgrid.cpp:57
double m_rotation
Definition: cellgrid.h:246
DoubleMatrix m_matrix
Definition: cellgrid.h:238
double getHeuristicCost(const ModelCoordinate &curpos, const ModelCoordinate &target)
Returns distance const from curpos to target point.
Definition: hexgrid.cpp:94
const std::string & getType() const
Type of cellgrid.
Definition: hexgrid.cpp:98
void setAllowDiagonals(const bool allow_diagonals)
Set whether diagonal cell access is allowed.
Definition: cellgrid.h:221
DoublePoint3D ExactModelCoordinate
Definition: modelcoords.h:36
static const double HEX_TO_CORNER
Definition: hexgrid.cpp:41
double m_zshift
Definition: cellgrid.h:242
const std::string & getName() const
Name of the cellgrid (DEPRECATED? -jwt)
Definition: hexgrid.cpp:103
void getVertices(std::vector< ExactModelCoordinate > &vtx, const ModelCoordinate &cell)
Fills given point vector with vertices from selected cell.
Definition: hexgrid.cpp:183
A 3D Point.
Definition: point.h:202
double m_yscale
Definition: cellgrid.h:244
static num_type pi()
Definition: fife_math.h:133
void setRotation(const double rotation)
Set the cellgrid rotation.
Definition: cellgrid.h:208
static const double VERTICAL_MULTIP
Definition: hexgrid.cpp:43
double m_xshift
Definition: cellgrid.h:240
static const double HEX_EDGE_HALF
Definition: hexgrid.cpp:42
ModelCoordinate toLayerCoordinates(const ExactModelCoordinate &map_coord)
Transforms given point from map coordinates to layer coordinates.
Definition: hexgrid.cpp:137
bool isAccessible(const ModelCoordinate &curpos, const ModelCoordinate &target)
Tells if given target point is accessible from curpos only cells adjacent to curpos are considered in...
Definition: hexgrid.cpp:73
#define FL_DBG(logger, msg)
Definition: logger.h:70