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:
authorAlex Zolotarev <deathbaba@gmail.com>2010-12-05 19:24:16 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-22 22:33:57 +0300
commitd6e12b7ce4bcbf0ccd1c07eb25de143422913c34 (patch)
treea7e910c330ce4da9b4f2d8be76067adece2561c4 /indexer/cell_coverer.hpp
One Month In Minsk. Made in Belarus.
Diffstat (limited to 'indexer/cell_coverer.hpp')
-rw-r--r--indexer/cell_coverer.hpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/indexer/cell_coverer.hpp b/indexer/cell_coverer.hpp
new file mode 100644
index 0000000000..8afc068e53
--- /dev/null
+++ b/indexer/cell_coverer.hpp
@@ -0,0 +1,293 @@
+#pragma once
+
+#include "cell_id.hpp"
+
+#include "../std/queue.hpp"
+#include "../std/vector.hpp"
+
+inline bool IntersectsHoriz(CoordT x1, CoordT y1, CoordT x2, CoordT y2,
+ CoordT y, CoordT l, CoordT r)
+{
+ CoordT d = (y1 - y) * (y2 - y);
+ if (d > 0) return false;
+
+ CoordT x = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
+
+ if ((l - x) * (r - x) <= 0) return true; else return false;
+}
+
+inline bool IntersectsVert(CoordT x1, CoordT y1, CoordT x2, CoordT y2,
+ CoordT x, CoordT b, CoordT t)
+{
+ CoordT d = (x1 - x) * (x2 - x);
+ if (d > 0) return false;
+
+ CoordT y = y1 + (y2 - y1) * (x - x1) / (x2 - x1);
+
+ if ((b - y) * (t - y) <= 0) return true; else return false;
+}
+
+template <typename BoundsT, typename CellIdT>
+inline bool CellIntersects(vector<CoordPointT> const & polyLine, CellIdT id)
+{
+ CoordT minX, minY, maxX, maxY;
+ CellIdConverter<BoundsT, CellIdT>::GetCellBounds(id, minX, minY, maxX, maxY);
+ CoordPointT minPoint = make_pair(minX, minY);
+ CoordPointT maxPoint = make_pair(maxX, maxY);
+
+ for (size_t i = 0; i < polyLine.size() - 1; ++i)
+ {
+ if (IntersectsHoriz(polyLine[i].first, polyLine[i].second,
+ polyLine[i + 1].first, polyLine[i + 1].second,
+ minPoint.second, minPoint.first, maxPoint.first)) return true;
+
+ if (IntersectsHoriz(polyLine[i].first, polyLine[i].second,
+ polyLine[i + 1].first, polyLine[i + 1].second,
+ maxPoint.second, minPoint.first, maxPoint.first)) return true;
+
+ if (IntersectsVert(polyLine[i].first, polyLine[i].second,
+ polyLine[i + 1].first, polyLine[i + 1].second,
+ minPoint.first, minPoint.second, maxPoint.second)) return true;
+
+ if (IntersectsVert(polyLine[i].first, polyLine[i].second,
+ polyLine[i + 1].first, polyLine[i + 1].second,
+ maxPoint.first, minPoint.second, maxPoint.second)) return true;
+ }
+
+ return false;
+}
+
+template <typename BoundsT, typename CellIdT>
+inline void SplitCell(vector<CoordPointT> const & polyLine, queue<CellIdT> & cellQueue)
+{
+ CellIdT id = cellQueue.front();
+ cellQueue.pop();
+
+ for (size_t i = 0; i < 4; ++i)
+ {
+ CellIdT child = id.Child(i);
+
+ if (CellIntersects<BoundsT>(polyLine, child))
+ {
+ cellQueue.push(child);
+ }
+ }
+}
+
+template <typename ItT>
+inline bool FindBounds(ItT begin, ItT end,
+ CoordT & minX, CoordT & minY, CoordT & maxX, CoordT & maxY)
+{
+ if (begin == end) return false;
+
+ minX = begin->first;
+ maxX = begin->first;
+ minY = begin->second;
+ maxY = begin->second;
+
+ for (ItT it = begin; it != end; ++it)
+ {
+ if (it->first < minX) minX = it->first;
+ if (it->first > maxX) maxX = it->first;
+ if (it->second < minY) minY = it->second;
+ if (it->second > maxY) maxY = it->second;
+ }
+
+ return true;
+}
+
+template <typename BoundsT, typename CellIdT>
+inline CellIdT CoverPoint(CoordPointT const & point)
+{
+ return CellIdConverter<BoundsT, CellIdT>::ToCellId(point.first, point.second);
+}
+
+template <typename BoundsT, typename CellIdT>
+inline void CoverPolyLine(vector< CoordPointT > const & polyLine, size_t cellDepth,
+ vector<CellIdT> & cells)
+{
+ CoordT minX = 0, minY = 0, maxX = 0, maxY = 0;
+ FindBounds(polyLine.begin(), polyLine.end(), minX, minY, maxX, maxY);
+
+ CellIdT commonCell =
+ CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(minX, minY, maxX, maxY);
+
+ queue<CellIdT> cellQueue;
+ cellQueue.push(commonCell);
+ while (cellQueue.front().Level() < static_cast<int>(cellDepth)) // cellQueue.size() < cells_count
+ {
+ SplitCell<BoundsT>(polyLine, cellQueue);
+ }
+
+ while (!cellQueue.empty())
+ {
+ cells.push_back(cellQueue.front());
+ cellQueue.pop();
+ }
+}
+
+template <typename BoundsT, typename CellIdT>
+inline void SplitRectCell(CellIdT id,
+ CoordT minX, CoordT minY,
+ CoordT maxX, CoordT maxY,
+ vector<CellIdT> & result)
+{
+ for (size_t i = 0; i < 4; ++i)
+ {
+ CellIdT child = id.Child(i);
+ CoordT 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);
+ }
+}
+
+template <typename BoundsT, typename CellIdT>
+inline void CoverRect(CoordT minX, CoordT minY,
+ CoordT maxX, CoordT maxY,
+ size_t cells_count,
+ vector<CellIdT> & cells)
+{
+ ASSERT_LESS(minX, maxX, ());
+ ASSERT_LESS(minY, maxY, ());
+
+ 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;
+
+ CellIdT commonCell =
+ CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(minX, minY, maxX, maxY);
+
+ vector<CellIdT> result;
+
+ queue<CellIdT> cellQueue;
+ cellQueue.push(commonCell);
+
+ while (!cellQueue.empty() && cellQueue.size() + result.size() < cells_count)
+ {
+ CellIdT id = cellQueue.front();
+ cellQueue.pop();
+
+ if (id.Level() == CellIdT::DEPTH_LEVELS - 1)
+ {
+ result.push_back(id);
+ break;
+ }
+
+ vector<CellIdT> children;
+ SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
+
+ // 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())
+ {
+ 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]);
+ }
+ 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];
+ while (id.Level() < CellIdT::DEPTH_LEVELS - 1)
+ {
+ vector<CellIdT> children;
+ SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
+ if (children.size() == 1)
+ id = children[0];
+ else
+ break;
+ }
+ result[i] = id;
+ }
+
+ ASSERT_LESS_OR_EQUAL(result.size(), cells_count, (minX, minY, maxX, maxY));
+ cells.insert(cells.end(), result.begin(), result.end());
+}
+
+/*
+template <typename BoundsT, typename CellIdT>
+inline void CoverPolygon(vector<CoordPointT> const & polyLine, size_t cellDepth,
+ vector<CellIdT> & cells)
+{
+ CoverPolyLine<BoundsT>(polyLine, cellDepth, cells);
+ if (cells.size() < 8)
+ return;
+
+ CellIdT minX = CellX(cells[0]), minY = CellY(cells[0]),
+ maxX = CellX(cells[0]), maxY = CellY(cells[0]);
+ for (size_t i = 1; i < cells.size(); ++i)
+ {
+ CellIdT cellX = CellX(cells[i]);
+ CellIdT cellY = CellY(cells[i]);
+
+ if (cellX.m_V < minX.m_V) minX.m_V = cellX.m_V;
+ if (cellY.m_V < minY.m_V) minY.m_V = cellY.m_V;
+ if (cellX.m_V > maxX.m_V) maxX.m_V = cellX.m_V;
+ if (cellY.m_V > maxY.m_V) maxY.m_V = cellY.m_V;
+ }
+
+ vector< vector<bool> > covered;
+ covered.resize(static_cast<size_t>(maxY.m_V - minY.m_V + 3));
+ for (size_t i = 0; i < covered.size(); ++i)
+ {
+ covered[i].resize(static_cast<size_t>(maxX.m_V - minX.m_V + 3));
+ }
+
+ vector< vector<bool> > outer = covered;
+
+ for (size_t i = 0; i < cells.size(); ++i)
+ {
+ size_t offsetX = static_cast<size_t>(CellX(cells[i]).m_V - minX.m_V + 1);
+ size_t offsetY = static_cast<size_t>(CellY(cells[i]).m_V - minY.m_V + 1);
+
+ covered[offsetY][offsetX] = true;
+ }
+
+ queue< pair<size_t, size_t> > flood;
+ size_t outerY = outer.size();
+ size_t outerX = outer[0].size();
+ flood.push(make_pair(0, 0));
+
+ while (!flood.empty())
+ {
+ size_t i = flood.front().first;
+ size_t j = flood.front().second;
+ flood.pop();
+ outer[i][j] = true;
+ if ((j > 0) && (!outer[i][j - 1]) && (!covered[i][j - 1]))
+ flood.push(make_pair(i, j - 1));
+ if ((i > 0) && (!outer[i - 1][j]) && (!covered[i - 1][j]))
+ flood.push(make_pair(i - 1, j));
+ if ((j < outerX - 1) && (!outer[i][j + 1]) && (!covered[i][j + 1]))
+ flood.push(make_pair(i, j + 1));
+ if ((i < outerY - 1) && (!outer[i + 1][j]) && (!covered[i + 1][j]))
+ flood.push(make_pair(i + 1, j));
+ }
+
+ cells.clear();
+
+ for (size_t i = 0; i < outer.size(); ++i)
+ {
+ for (size_t j = 0; j < outer[i].size(); ++j)
+ {
+ if (!outer[i][j])
+ {
+ cells.push_back(CellFromCellXY(cellDepth, minX.m_V + j - 1, minY.m_V + i - 1));
+ }
+ }
+ }
+}
+*/