2018-06-09 17:14:08 +02:00
|
|
|
// Copyright 2017, University of Freiburg,
|
|
|
|
|
// Chair of Algorithms and Data Structures.
|
|
|
|
|
// Author: Patrick Brosi <brosip@informatik.uni-freiburg.de>
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
Grid<V, G, T>::Grid(bool bldIdx)
|
|
|
|
|
: _width(0),
|
|
|
|
|
_height(0),
|
|
|
|
|
_cellWidth(0),
|
|
|
|
|
_cellHeight(0),
|
|
|
|
|
_xWidth(0),
|
|
|
|
|
_yHeight(0),
|
|
|
|
|
_hasValIdx(bldIdx) {}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
Grid<V, G, T>::Grid() : Grid<V, G, T>(true) {}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
Grid<V, G, T>::Grid(double w, double h, const Box<T>& bbox)
|
|
|
|
|
: Grid<V, G, T>(w, h, bbox, true) {}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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 =
|
2018-07-15 14:13:31 +02:00
|
|
|
bbox.getUpperRight().getX() - bbox.getLowerLeft().getX();
|
2018-06-09 17:14:08 +02:00
|
|
|
_height =
|
2018-07-15 14:13:31 +02:00
|
|
|
bbox.getUpperRight().getY() - bbox.getLowerLeft().getY();
|
2018-06-09 17:14:08 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
void Grid<V, G, T>::add(G<T> geom, V val) {
|
|
|
|
|
Box<T> box = getBoundingBox(geom);
|
2018-07-15 14:13:31 +02:00
|
|
|
size_t swX = getCellXFromX(box.getLowerLeft().getX());
|
|
|
|
|
size_t swY = getCellYFromY(box.getLowerLeft().getY());
|
2018-06-09 17:14:08 +02:00
|
|
|
|
2018-07-15 14:13:31 +02:00
|
|
|
size_t neX = getCellXFromX(box.getUpperRight().getX());
|
|
|
|
|
size_t neY = getCellYFromY(box.getUpperRight().getY());
|
2018-06-09 17:14:08 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
void Grid<V, G, T>::get(const Box<T>& box, std::set<V>* s) const {
|
2018-07-15 14:13:31 +02:00
|
|
|
size_t swX = getCellXFromX(box.getLowerLeft().getX());
|
|
|
|
|
size_t swY = getCellYFromY(box.getLowerLeft().getY());
|
2018-06-09 17:14:08 +02:00
|
|
|
|
2018-07-15 14:13:31 +02:00
|
|
|
size_t neX = getCellXFromX(box.getUpperRight().getX());
|
|
|
|
|
size_t neY = getCellYFromY(box.getUpperRight().getY());
|
2018-06-09 17:14:08 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
void Grid<V, G, T>::get(const G<T>& geom, double d, std::set<V>* s) const {
|
|
|
|
|
Box<T> a = getBoundingBox(geom);
|
2018-07-15 14:13:31 +02:00
|
|
|
Box<T> b(Point<T>(a.getLowerLeft().getX() - d,
|
|
|
|
|
a.getLowerLeft().getY() - d),
|
|
|
|
|
Point<T>(a.getUpperRight().getX() + d,
|
|
|
|
|
a.getUpperRight().getY() + d));
|
2018-06-09 17:14:08 +02:00
|
|
|
return get(b, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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; });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
Box<T> Grid<V, G, T>::getBox(size_t x, size_t y) const {
|
2018-07-15 14:13:31 +02:00
|
|
|
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);
|
2018-06-09 17:14:08 +02:00
|
|
|
return Box<T>(sw, ne);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
size_t Grid<V, G, T>::getCellXFromX(double x) const {
|
2018-07-15 14:13:31 +02:00
|
|
|
float dist = x - _bb.getLowerLeft().getX();
|
2018-06-09 17:14:08 +02:00
|
|
|
if (dist < 0) dist = 0;
|
|
|
|
|
return floor(dist / _cellWidth);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
size_t Grid<V, G, T>::getCellYFromY(double y) const {
|
2018-07-15 14:13:31 +02:00
|
|
|
float dist = y - _bb.getLowerLeft().getY();
|
2018-06-09 17:14:08 +02:00
|
|
|
if (dist < 0) dist = 0;
|
|
|
|
|
return floor(dist / _cellHeight);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
size_t Grid<V, G, T>::getXWidth() const {
|
|
|
|
|
return _xWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
2018-07-22 18:37:03 +02:00
|
|
|
template <typename V, template <typename> class G, typename T>
|
2018-06-09 17:14:08 +02:00
|
|
|
size_t Grid<V, G, T>::getYHeight() const {
|
|
|
|
|
return _yHeight;
|
|
|
|
|
}
|