TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CellImpl.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef TRINITY_CELLIMPL_H
20 #define TRINITY_CELLIMPL_H
21 
22 #include <cmath>
23 
24 #include "Cell.h"
25 #include "Map.h"
26 #include "Object.h"
27 
28 inline Cell::Cell(CellCoord const& p)
29 {
30  data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS;
31  data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
32  data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
33  data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
34  data.Part.nocreate = 0;
35  data.Part.reserved = 0;
36 }
37 
38 inline Cell::Cell(float x, float y)
39 {
41  data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS;
42  data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
43  data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
44  data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
45  data.Part.nocreate = 0;
46  data.Part.reserved = 0;
47 }
48 
49 inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
50 {
51  if (radius <= 0.0f)
52  {
54  return CellArea(center, center);
55  }
56 
57  CellCoord centerX = Trinity::ComputeCellCoord(x - radius, y - radius).normalize();
58  CellCoord centerY = Trinity::ComputeCellCoord(x + radius, y + radius).normalize();
59 
60  return CellArea(centerX, centerY);
61 }
62 
63 template<class T, class CONTAINER>
64 inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, float radius, float x_off, float y_off) const
65 {
66  if (!standing_cell.IsCoordValid())
67  return;
68 
69  //no jokes here... Actually placing ASSERT() here was good idea, but
70  //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?)
71  //maybe it is better to just return when radius <= 0.0f?
72  if (radius <= 0.0f)
73  {
74  map.Visit(*this, visitor);
75  return;
76  }
77  //lets limit the upper value for search radius
78  if (radius > SIZE_OF_GRIDS)
79  radius = SIZE_OF_GRIDS;
80 
81  //lets calculate object coord offsets from cell borders.
82  CellArea area = Cell::CalculateCellArea(x_off, y_off, radius);
83  //if radius fits inside standing cell
84  if (!area)
85  {
86  map.Visit(*this, visitor);
87  return;
88  }
89 
90  //visit all cells, found in CalculateCellArea()
91  //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
92  //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values
93  //there are nothing to optimize because SIZE_OF_GRID_CELL is too big...
94  if ((area.high_bound.x_coord > (area.low_bound.x_coord + 4)) && (area.high_bound.y_coord > (area.low_bound.y_coord + 4)))
95  {
96  VisitCircle(visitor, map, area.low_bound, area.high_bound);
97  return;
98  }
99 
100  //ALWAYS visit standing cell first!!! Since we deal with small radiuses
101  //it is very essential to call visitor for standing cell firstly...
102  map.Visit(*this, visitor);
103 
104  // loop the cell range
105  for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
106  {
107  for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
108  {
109  CellCoord cellCoord(x, y);
110  //lets skip standing cell since we already visited it
111  if (cellCoord != standing_cell)
112  {
113  Cell r_zone(cellCoord);
114  r_zone.data.Part.nocreate = this->data.Part.nocreate;
115  map.Visit(r_zone, visitor);
116  }
117  }
118  }
119 }
120 
121 template<class T, class CONTAINER>
122 inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, WorldObject const& obj, float radius) const
123 {
124  //we should increase search radius by object's radius, otherwise
125  //we could have problems with huge creatures, which won't attack nearest players etc
126  Visit(standing_cell, visitor, map, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY());
127 }
128 
129 template<class T, class CONTAINER>
130 inline void Cell::VisitCircle(TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, CellCoord const& begin_cell, CellCoord const& end_cell) const
131 {
132  //here is an algorithm for 'filling' circum-squared octagon
133  uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f);
134  //lets calculate x_start/x_end coords for central strip...
135  const uint32 x_start = begin_cell.x_coord + x_shift;
136  const uint32 x_end = end_cell.x_coord - x_shift;
137 
138  //visit central strip with constant width...
139  for (uint32 x = x_start; x <= x_end; ++x)
140  {
141  for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
142  {
143  CellCoord cellCoord(x, y);
144  Cell r_zone(cellCoord);
145  r_zone.data.Part.nocreate = this->data.Part.nocreate;
146  map.Visit(r_zone, visitor);
147  }
148  }
149 
150  //if x_shift == 0 then we have too small cell area, which were already
151  //visited at previous step, so just return from procedure...
152  if (x_shift == 0)
153  return;
154 
155  uint32 y_start = end_cell.y_coord;
156  uint32 y_end = begin_cell.y_coord;
157  //now we are visiting borders of an octagon...
158  for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step)
159  {
160  //each step reduces strip height by 2 cells...
161  y_end += 1;
162  y_start -= 1;
163  for (uint32 y = y_start; y >= y_end; --y)
164  {
165  //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom
166  //e.g. filling 2 trapezoids after filling central cell strip...
167  CellCoord cellCoord_left(x_start - step, y);
168  Cell r_zone_left(cellCoord_left);
169  r_zone_left.data.Part.nocreate = this->data.Part.nocreate;
170  map.Visit(r_zone_left, visitor);
171 
172  //right trapezoid cell visit
173  CellCoord cellCoord_right(x_end + step, y);
174  Cell r_zone_right(cellCoord_right);
175  r_zone_right.data.Part.nocreate = this->data.Part.nocreate;
176  map.Visit(r_zone_right, visitor);
177  }
178  }
179 }
180 #endif
struct Cell::@307::@308 Part
#define SIZE_OF_GRIDS
Definition: GridDefines.h:39
Definition: TypeContainerVisitor.h:32
CoordPair & normalize()
Definition: GridDefines.h:143
Cell()
Definition: Cell.h:51
#define MAX_NUMBER_OF_CELLS
Definition: GridDefines.h:35
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:193
union Cell::@307 data
Definition: Object.h:423
uint32 y_coord
Definition: GridDefines.h:156
static CellArea CalculateCellArea(float x, float y, float radius)
Definition: CellImpl.h:49
uint32 x_coord
Definition: GridDefines.h:155
Definition: Cell.h:32
float GetPositionY() const
Definition: Position.h:105
CellCoord low_bound
Definition: Cell.h:45
uint32_t uint32
Definition: Define.h:150
G3D::int16 y
Definition: Vector2int16.h:38
bool IsCoordValid() const
Definition: GridDefines.h:138
Definition: Map.h:259
void VisitCircle(TypeContainerVisitor< T, CONTAINER > &, Map &, CellCoord const &, CellCoord const &) const
Definition: CellImpl.h:130
Definition: Cell.h:49
void Visit(const Cell &cell, TypeContainerVisitor< T, CONTAINER > &visitor)
Definition: Map.h:811
CellCoord high_bound
Definition: Cell.h:46
uint32_t uint32
Definition: g3dmath.h:168
G3D::int16 x
Definition: Vector2int16.h:37
float GetPositionX() const
Definition: Position.h:104
float GetObjectSize() const
Definition: Object.cpp:2656
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:122