123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // Copyright 2017, University of Freiburg,
- // Chair of Algorithms and Data Structures.
- // Author: Patrick Brosi <brosip@informatik.uni-freiburg.de>
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- Grid<V, G, T>::Grid(bool bldIdx)
- : _width(0),
- _height(0),
- _cellWidth(0),
- _cellHeight(0),
- _xWidth(0),
- _yHeight(0),
- _hasValIdx(bldIdx) {}
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- Grid<V, G, T>::Grid() : Grid<V, G, T>(true) {}
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- Grid<V, G, T>::Grid(double w, double h, const Box<T>& bbox)
- : Grid<V, G, T>(w, h, bbox, true) {}
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- Grid<V, G, T>::Grid(double w, double h, const Box<T>& bbox, bool bValIdx)
- : _cellWidth(fabs(w)),
- _cellHeight(fabs(h)),
- _bb(bbox),
- _hasValIdx(bValIdx) {
- _width =
- bbox.getUpperRight().getX() - bbox.getLowerLeft().getX();
- _height =
- bbox.getUpperRight().getY() - bbox.getLowerLeft().getY();
- if (_width < 0 || _height < 0) {
- _width = 0;
- _height = 0;
- _xWidth = 0;
- _yHeight = 0;
- return;
- }
- _xWidth = ceil(_width / _cellWidth);
- _yHeight = ceil(_height / _cellHeight);
- // resize rows
- _grid.resize(_xWidth);
- // resize columns
- for (size_t i = 0; i < _xWidth; i++) {
- _grid[i].resize(_yHeight);
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::add(G<T> geom, V val) {
- Box<T> box = getBoundingBox(geom);
- size_t swX = getCellXFromX(box.getLowerLeft().getX());
- size_t swY = getCellYFromY(box.getLowerLeft().getY());
- size_t neX = getCellXFromX(box.getUpperRight().getX());
- size_t neY = getCellYFromY(box.getUpperRight().getY());
- for (size_t x = swX; x <= neX && x < _grid.size(); x++) {
- for (size_t y = swY; y <= neY && y < _grid[x].size(); y++) {
- if (intersects(geom, getBox(x, y))) {
- add(x, y, val);
- }
- }
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::add(size_t x, size_t y, V val) {
- _grid[x][y].insert(val);
- if (_hasValIdx) _index[val].insert(std::pair<size_t, size_t>(x, y));
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::get(const Box<T>& box, std::set<V>* s) const {
- size_t swX = getCellXFromX(box.getLowerLeft().getX());
- size_t swY = getCellYFromY(box.getLowerLeft().getY());
- size_t neX = getCellXFromX(box.getUpperRight().getX());
- size_t neY = getCellYFromY(box.getUpperRight().getY());
- for (size_t x = swX; x <= neX && x >= 0 && x < _xWidth; x++)
- for (size_t y = swY; y <= neY && y >= 0 && y < _yHeight; y++) get(x, y, s);
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::get(const G<T>& geom, double d, std::set<V>* s) const {
- Box<T> a = getBoundingBox(geom);
- Box<T> b(Point<T>(a.getLowerLeft().getX() - d,
- a.getLowerLeft().getY() - d),
- Point<T>(a.getUpperRight().getX() + d,
- a.getUpperRight().getY() + d));
- return get(b, s);
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::get(size_t x, size_t y, std::set<V>* s) const {
- if (_hasValIdx) {
- s->insert(_grid[x][y].begin(), _grid[x][y].end());
- } else {
- // if we dont have a value index, we have a set of deleted nodes.
- // in this case, only insert if not deleted
- std::copy_if(_grid[x][y].begin(), _grid[x][y].end(),
- std::inserter(*s, s->end()),
- [&](const V& v) { return Grid<V, G, T>::_removed.count(v) == 0; });
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::remove(V val) {
- if (_hasValIdx) {
- auto i = _index.find(val);
- if (i == _index.end()) return;
- for (auto pair : i->second) {
- _grid[pair.first][pair.second].erase(
- _grid[pair.first][pair.second].find(val));
- }
- _index.erase(i);
- } else {
- _removed.insert(val);
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::getNeighbors(const V& val, double d, std::set<V>* s) const {
- if (!_hasValIdx) throw GridException("No value index build!");
- auto it = _index.find(val);
- if (it == _index.end()) return;
- size_t xPerm = ceil(d / _cellWidth);
- size_t yPerm = ceil(d / _cellHeight);
- for (auto pair : it->second) {
- getCellNeighbors(pair.first, pair.second, xPerm, yPerm, s);
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::getCellNeighbors(const V& val, size_t d,
- std::set<V>* s) const {
- if (!_hasValIdx) throw GridException("No value index build!");
- auto it = _index.find(val);
- if (it == _index.end()) return;
- for (auto pair : it->second) {
- getCellNeighbors(pair.first, pair.second, d, d, s);
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- void Grid<V, G, T>::getCellNeighbors(size_t cx, size_t cy, size_t xPerm,
- size_t yPerm, std::set<V>* s) const {
- size_t swX = xPerm > cx ? 0 : cx - xPerm;
- size_t swY = yPerm > cy ? 0 : cy - yPerm;
- size_t neX = xPerm + cx + 1 > _xWidth ? _xWidth : cx + xPerm + 1;
- size_t neY = yPerm + cy + 1 > _yHeight ? _yHeight : cy + yPerm + 1;
- for (size_t x = swX; x < neX; x++) {
- for (size_t y = swY; y < neY; y++) {
- s->insert(_grid[x][y].begin(), _grid[x][y].end());
- }
- }
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- std::set<std::pair<size_t, size_t> > Grid<V, G, T>::getCells(
- const V& val) const {
- if (!_hasValIdx) throw GridException("No value index build!");
- return _index.find(val)->second;
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- Box<T> Grid<V, G, T>::getBox(size_t x, size_t y) const {
- Point<T> sw(_bb.getLowerLeft().getX() + x * _cellWidth,
- _bb.getLowerLeft().getY() + y * _cellHeight);
- Point<T> ne(_bb.getLowerLeft().getX() + (x + 1) * _cellWidth,
- _bb.getLowerLeft().getY() + (y + 1) * _cellHeight);
- return Box<T>(sw, ne);
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- size_t Grid<V, G, T>::getCellXFromX(double x) const {
- float dist = x - _bb.getLowerLeft().getX();
- if (dist < 0) dist = 0;
- return floor(dist / _cellWidth);
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- size_t Grid<V, G, T>::getCellYFromY(double y) const {
- float dist = y - _bb.getLowerLeft().getY();
- if (dist < 0) dist = 0;
- return floor(dist / _cellHeight);
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- size_t Grid<V, G, T>::getXWidth() const {
- return _xWidth;
- }
- // _____________________________________________________________________________
- template <typename V, template <typename> class G, typename T>
- size_t Grid<V, G, T>::getYHeight() const {
- return _yHeight;
- }
|