Grid.tpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright 2017, University of Freiburg,
  2. // Chair of Algorithms and Data Structures.
  3. // Author: Patrick Brosi <brosip@informatik.uni-freiburg.de>
  4. // _____________________________________________________________________________
  5. template <typename V, template <typename> class G, typename T>
  6. Grid<V, G, T>::Grid(bool bldIdx)
  7. : _width(0),
  8. _height(0),
  9. _cellWidth(0),
  10. _cellHeight(0),
  11. _xWidth(0),
  12. _yHeight(0),
  13. _hasValIdx(bldIdx) {}
  14. // _____________________________________________________________________________
  15. template <typename V, template <typename> class G, typename T>
  16. Grid<V, G, T>::Grid() : Grid<V, G, T>(true) {}
  17. // _____________________________________________________________________________
  18. template <typename V, template <typename> class G, typename T>
  19. Grid<V, G, T>::Grid(double w, double h, const Box<T>& bbox)
  20. : Grid<V, G, T>(w, h, bbox, true) {}
  21. // _____________________________________________________________________________
  22. template <typename V, template <typename> class G, typename T>
  23. Grid<V, G, T>::Grid(double w, double h, const Box<T>& bbox, bool bValIdx)
  24. : _cellWidth(fabs(w)),
  25. _cellHeight(fabs(h)),
  26. _bb(bbox),
  27. _hasValIdx(bValIdx) {
  28. _width =
  29. bbox.getUpperRight().getX() - bbox.getLowerLeft().getX();
  30. _height =
  31. bbox.getUpperRight().getY() - bbox.getLowerLeft().getY();
  32. if (_width < 0 || _height < 0) {
  33. _width = 0;
  34. _height = 0;
  35. _xWidth = 0;
  36. _yHeight = 0;
  37. return;
  38. }
  39. _xWidth = ceil(_width / _cellWidth);
  40. _yHeight = ceil(_height / _cellHeight);
  41. // resize rows
  42. _grid.resize(_xWidth);
  43. // resize columns
  44. for (size_t i = 0; i < _xWidth; i++) {
  45. _grid[i].resize(_yHeight);
  46. }
  47. }
  48. // _____________________________________________________________________________
  49. template <typename V, template <typename> class G, typename T>
  50. void Grid<V, G, T>::add(G<T> geom, V val) {
  51. Box<T> box = getBoundingBox(geom);
  52. size_t swX = getCellXFromX(box.getLowerLeft().getX());
  53. size_t swY = getCellYFromY(box.getLowerLeft().getY());
  54. size_t neX = getCellXFromX(box.getUpperRight().getX());
  55. size_t neY = getCellYFromY(box.getUpperRight().getY());
  56. for (size_t x = swX; x <= neX && x < _grid.size(); x++) {
  57. for (size_t y = swY; y <= neY && y < _grid[x].size(); y++) {
  58. if (intersects(geom, getBox(x, y))) {
  59. add(x, y, val);
  60. }
  61. }
  62. }
  63. }
  64. // _____________________________________________________________________________
  65. template <typename V, template <typename> class G, typename T>
  66. void Grid<V, G, T>::add(size_t x, size_t y, V val) {
  67. _grid[x][y].insert(val);
  68. if (_hasValIdx) _index[val].insert(std::pair<size_t, size_t>(x, y));
  69. }
  70. // _____________________________________________________________________________
  71. template <typename V, template <typename> class G, typename T>
  72. void Grid<V, G, T>::get(const Box<T>& box, std::set<V>* s) const {
  73. size_t swX = getCellXFromX(box.getLowerLeft().getX());
  74. size_t swY = getCellYFromY(box.getLowerLeft().getY());
  75. size_t neX = getCellXFromX(box.getUpperRight().getX());
  76. size_t neY = getCellYFromY(box.getUpperRight().getY());
  77. for (size_t x = swX; x <= neX && x >= 0 && x < _xWidth; x++)
  78. for (size_t y = swY; y <= neY && y >= 0 && y < _yHeight; y++) get(x, y, s);
  79. }
  80. // _____________________________________________________________________________
  81. template <typename V, template <typename> class G, typename T>
  82. void Grid<V, G, T>::get(const G<T>& geom, double d, std::set<V>* s) const {
  83. Box<T> a = getBoundingBox(geom);
  84. Box<T> b(Point<T>(a.getLowerLeft().getX() - d,
  85. a.getLowerLeft().getY() - d),
  86. Point<T>(a.getUpperRight().getX() + d,
  87. a.getUpperRight().getY() + d));
  88. return get(b, s);
  89. }
  90. // _____________________________________________________________________________
  91. template <typename V, template <typename> class G, typename T>
  92. void Grid<V, G, T>::get(size_t x, size_t y, std::set<V>* s) const {
  93. if (_hasValIdx) {
  94. s->insert(_grid[x][y].begin(), _grid[x][y].end());
  95. } else {
  96. // if we dont have a value index, we have a set of deleted nodes.
  97. // in this case, only insert if not deleted
  98. std::copy_if(_grid[x][y].begin(), _grid[x][y].end(),
  99. std::inserter(*s, s->end()),
  100. [&](const V& v) { return Grid<V, G, T>::_removed.count(v) == 0; });
  101. }
  102. }
  103. // _____________________________________________________________________________
  104. template <typename V, template <typename> class G, typename T>
  105. void Grid<V, G, T>::remove(V val) {
  106. if (_hasValIdx) {
  107. auto i = _index.find(val);
  108. if (i == _index.end()) return;
  109. for (auto pair : i->second) {
  110. _grid[pair.first][pair.second].erase(
  111. _grid[pair.first][pair.second].find(val));
  112. }
  113. _index.erase(i);
  114. } else {
  115. _removed.insert(val);
  116. }
  117. }
  118. // _____________________________________________________________________________
  119. template <typename V, template <typename> class G, typename T>
  120. void Grid<V, G, T>::getNeighbors(const V& val, double d, std::set<V>* s) const {
  121. if (!_hasValIdx) throw GridException("No value index build!");
  122. auto it = _index.find(val);
  123. if (it == _index.end()) return;
  124. size_t xPerm = ceil(d / _cellWidth);
  125. size_t yPerm = ceil(d / _cellHeight);
  126. for (auto pair : it->second) {
  127. getCellNeighbors(pair.first, pair.second, xPerm, yPerm, s);
  128. }
  129. }
  130. // _____________________________________________________________________________
  131. template <typename V, template <typename> class G, typename T>
  132. void Grid<V, G, T>::getCellNeighbors(const V& val, size_t d,
  133. std::set<V>* s) const {
  134. if (!_hasValIdx) throw GridException("No value index build!");
  135. auto it = _index.find(val);
  136. if (it == _index.end()) return;
  137. for (auto pair : it->second) {
  138. getCellNeighbors(pair.first, pair.second, d, d, s);
  139. }
  140. }
  141. // _____________________________________________________________________________
  142. template <typename V, template <typename> class G, typename T>
  143. void Grid<V, G, T>::getCellNeighbors(size_t cx, size_t cy, size_t xPerm,
  144. size_t yPerm, std::set<V>* s) const {
  145. size_t swX = xPerm > cx ? 0 : cx - xPerm;
  146. size_t swY = yPerm > cy ? 0 : cy - yPerm;
  147. size_t neX = xPerm + cx + 1 > _xWidth ? _xWidth : cx + xPerm + 1;
  148. size_t neY = yPerm + cy + 1 > _yHeight ? _yHeight : cy + yPerm + 1;
  149. for (size_t x = swX; x < neX; x++) {
  150. for (size_t y = swY; y < neY; y++) {
  151. s->insert(_grid[x][y].begin(), _grid[x][y].end());
  152. }
  153. }
  154. }
  155. // _____________________________________________________________________________
  156. template <typename V, template <typename> class G, typename T>
  157. std::set<std::pair<size_t, size_t> > Grid<V, G, T>::getCells(
  158. const V& val) const {
  159. if (!_hasValIdx) throw GridException("No value index build!");
  160. return _index.find(val)->second;
  161. }
  162. // _____________________________________________________________________________
  163. template <typename V, template <typename> class G, typename T>
  164. Box<T> Grid<V, G, T>::getBox(size_t x, size_t y) const {
  165. Point<T> sw(_bb.getLowerLeft().getX() + x * _cellWidth,
  166. _bb.getLowerLeft().getY() + y * _cellHeight);
  167. Point<T> ne(_bb.getLowerLeft().getX() + (x + 1) * _cellWidth,
  168. _bb.getLowerLeft().getY() + (y + 1) * _cellHeight);
  169. return Box<T>(sw, ne);
  170. }
  171. // _____________________________________________________________________________
  172. template <typename V, template <typename> class G, typename T>
  173. size_t Grid<V, G, T>::getCellXFromX(double x) const {
  174. float dist = x - _bb.getLowerLeft().getX();
  175. if (dist < 0) dist = 0;
  176. return floor(dist / _cellWidth);
  177. }
  178. // _____________________________________________________________________________
  179. template <typename V, template <typename> class G, typename T>
  180. size_t Grid<V, G, T>::getCellYFromY(double y) const {
  181. float dist = y - _bb.getLowerLeft().getY();
  182. if (dist < 0) dist = 0;
  183. return floor(dist / _cellHeight);
  184. }
  185. // _____________________________________________________________________________
  186. template <typename V, template <typename> class G, typename T>
  187. size_t Grid<V, G, T>::getXWidth() const {
  188. return _xWidth;
  189. }
  190. // _____________________________________________________________________________
  191. template <typename V, template <typename> class G, typename T>
  192. size_t Grid<V, G, T>::getYHeight() const {
  193. return _yHeight;
  194. }