Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvng <viktor.govako@gmail.com>2016-12-25 17:38:58 +0300
committervng <viktor.govako@gmail.com>2016-12-25 17:38:58 +0300
commit0080acadff1b041a771098d9eb8a6296a63f243c (patch)
treed01073a27b61cdd6941a05ccf2742d85b70d8b18 /indexer/cell_coverer.hpp
parent4b24b9f7c5190c120233558ae425b3bffb9197df (diff)
[index] More accurate rect covering in ForEachInRect.
Diffstat (limited to 'indexer/cell_coverer.hpp')
-rw-r--r--indexer/cell_coverer.hpp97
1 files changed, 47 insertions, 50 deletions
diff --git a/indexer/cell_coverer.hpp b/indexer/cell_coverer.hpp
index 8d47091ada..352ec4cb21 100644
--- a/indexer/cell_coverer.hpp
+++ b/indexer/cell_coverer.hpp
@@ -2,54 +2,58 @@
#include "indexer/cell_id.hpp"
+#include "base/buffer_vector.hpp"
+
#include "std/queue.hpp"
#include "std/vector.hpp"
// TODO: Move neccessary functions to geometry/covering_utils.hpp and delete this file.
+constexpr int SPLIT_RECT_CELLS_COUNT = 512;
+
template <typename BoundsT, typename CellIdT>
-inline void SplitRectCell(CellIdT id,
- double minX, double minY,
- double maxX, double maxY,
- vector<CellIdT> & result)
+inline int SplitRectCell(CellIdT const & id, m2::RectD const & rect,
+ array<pair<CellIdT, m2::RectD>, 4> & result)
{
+ int index = 0;
for (int8_t i = 0; i < 4; ++i)
{
- CellIdT child = id.Child(i);
+ CellIdT const child = id.Child(i);
double minCellX, minCellY, maxCellX, maxCellY;
CellIdConverter<BoundsT, CellIdT>::GetCellBounds(child, minCellX, minCellY, maxCellX, maxCellY);
- if (!((maxX < minCellX) || (minX > maxCellX) || (maxY < minCellY) || (minY > maxCellY)))
- result.push_back(child);
+
+ m2::RectD const childRect(minCellX, minCellY, maxCellX, maxCellY);
+ if (rect.IsIntersect(childRect))
+ result[index++] = {child, childRect};
}
+ return index;
}
template <typename BoundsT, typename CellIdT>
-inline void CoverRect(double minX, double minY,
- double maxX, double maxY,
- size_t cells_count, int maxDepth,
- vector<CellIdT> & cells)
+inline void CoverRect(m2::RectD rect, size_t cellsCount, int maxDepth,
+ vector<CellIdT> & result)
{
- if (minX < BoundsT::minX) minX = BoundsT::minX;
- if (minY < BoundsT::minY) minY = BoundsT::minY;
- if (maxX > BoundsT::maxX) maxX = BoundsT::maxX;
- if (maxY > BoundsT::maxY) maxY = BoundsT::maxY;
-
- if (minX >= maxX || minY >= maxY)
- return;
-
- CellIdT commonCell =
- CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(minX, minY, maxX, maxY);
+ ASSERT(result.empty(), ());
+ {
+ // Fit rect to converter bounds.
+ if (!rect.Intersect({ BoundsT::minX, BoundsT::minY, BoundsT::maxX, BoundsT::maxY }))
+ return;
+ ASSERT(rect.IsValid(), ());
+ }
- vector<CellIdT> result;
+ CellIdT const commonCell = CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(
+ rect.minX(), rect.minY(), rect.maxX(), rect.maxY());
- queue<CellIdT> cellQueue;
+ priority_queue<CellIdT,
+ buffer_vector<CellIdT, SPLIT_RECT_CELLS_COUNT>,
+ typename CellIdT::GreaterLevelOrder> cellQueue;
cellQueue.push(commonCell);
maxDepth -= 1;
- while (!cellQueue.empty() && cellQueue.size() + result.size() < cells_count)
+ while (!cellQueue.empty() && cellQueue.size() + result.size() < cellsCount)
{
- CellIdT id = cellQueue.front();
+ CellIdT id = cellQueue.top();
cellQueue.pop();
while (id.Level() > maxDepth)
@@ -61,44 +65,37 @@ inline void CoverRect(double minX, double minY,
break;
}
- vector<CellIdT> children;
- SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
+ array<pair<CellIdT, m2::RectD>, 4> arr;
+ int const count = SplitRectCell<BoundsT>(id, rect, arr);
- // Children shouldn't be empty, but if it is, ignore this cellid in release.
- ASSERT(!children.empty(), (id, minX, minY, maxX, maxY));
- if (children.empty())
+ if (cellQueue.size() + result.size() + count <= cellsCount)
{
- result.push_back(id);
- continue;
- }
-
- if (cellQueue.size() + result.size() + children.size() <= cells_count)
- {
- for (size_t i = 0; i < children.size(); ++i)
- cellQueue.push(children[i]);
+ for (int i = 0; i < count; ++i)
+ {
+ if (rect.IsRectInside(arr[i].second))
+ result.push_back(arr[i].first);
+ else
+ cellQueue.push(arr[i].first);
+ }
}
else
+ {
result.push_back(id);
+ }
}
for (; !cellQueue.empty(); cellQueue.pop())
- result.push_back(cellQueue.front());
-
- for (size_t i = 0; i < result.size(); ++i)
{
- CellIdT id = result[i];
+ CellIdT id = cellQueue.top();
while (id.Level() < maxDepth)
{
- vector<CellIdT> children;
- SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
- if (children.size() == 1)
- id = children[0];
+ array<pair<CellIdT, m2::RectD>, 4> arr;
+ int const count = SplitRectCell<BoundsT>(id, rect, arr);
+ if (count == 1)
+ id = arr[0].first;
else
break;
}
- result[i] = id;
+ result.push_back(id);
}
-
- ASSERT_LESS_OR_EQUAL(result.size(), cells_count, (minX, minY, maxX, maxY));
- cells.insert(cells.end(), result.begin(), result.end());
}