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:
-rw-r--r--defines.hpp7
-rw-r--r--generator/generator_tests/check_mwms.cpp13
-rw-r--r--indexer/CMakeLists.txt5
-rw-r--r--indexer/cell_value_pair.hpp45
-rw-r--r--indexer/data_factory.hpp4
-rw-r--r--indexer/displacement_manager.hpp36
-rw-r--r--indexer/feature_covering.cpp33
-rw-r--r--indexer/feature_covering.hpp8
-rw-r--r--indexer/feature_loader.cpp14
-rw-r--r--indexer/geometry_serialization.hpp16
-rw-r--r--indexer/indexer_tests/interval_index_test.cpp28
-rw-r--r--indexer/interval_index.hpp6
-rw-r--r--indexer/interval_index_builder.hpp44
-rw-r--r--indexer/locality_index_builder.cpp88
-rw-r--r--indexer/locality_index_builder.hpp59
-rw-r--r--indexer/locality_object.cpp34
-rw-r--r--indexer/locality_object.hpp47
-rw-r--r--indexer/scale_index.hpp17
-rw-r--r--indexer/scale_index_builder.hpp20
-rw-r--r--xcode/indexer/indexer.xcodeproj/project.pbxproj20
20 files changed, 424 insertions, 120 deletions
diff --git a/defines.hpp b/defines.hpp
index 4dbbf06569..93b3f55f65 100644
--- a/defines.hpp
+++ b/defines.hpp
@@ -45,6 +45,9 @@
#define TRANSIT_FILE_TAG "transit"
#define UGC_FILE_TAG "ugc"
+#define LOCALITY_DATA_FILE_TAG "locdata"
+#define LOCALITY_INDEX_FILE_TAG "locidx"
+
#define READY_FILE_EXTENSION ".ready"
#define RESUME_FILE_EXTENSION ".resume"
#define DOWNLOADING_FILE_EXTENSION ".downloading"
@@ -57,6 +60,10 @@
#define CELL2FEATURE_SORTED_EXT ".c2f.sorted"
#define CELL2FEATURE_TMP_EXT ".c2f.tmp"
+#define LOCALITY_INDEX_TMP_EXT ".locidx.tmp"
+#define CELL2LOCALITY_SORTED_EXT ".c2l.sorted"
+#define CELL2LOCALITY_TMP_EXT ".c2l.tmp"
+
#define COUNTRIES_FILE "countries.txt"
#define COUNTRIES_META_FILE "countries_meta.txt"
#define COUNTRIES_OBSOLETE_FILE "countries_obsolete.txt"
diff --git a/generator/generator_tests/check_mwms.cpp b/generator/generator_tests/check_mwms.cpp
index 10fab2cb9e..8d63957007 100644
--- a/generator/generator_tests/check_mwms.cpp
+++ b/generator/generator_tests/check_mwms.cpp
@@ -11,6 +11,12 @@
#include "base/logging.hpp"
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <vector>
+
+using namespace std;
UNIT_TEST(CheckMWM_LoadAll)
{
@@ -50,9 +56,12 @@ UNIT_TEST(CheckMWM_GeomIndex)
VarSerialVectorReader<ReaderT> treesReader(source);
// Make interval index objects for each scale bucket.
- vector<unique_ptr<IntervalIndex<ReaderT>>> scale2Index;
+ vector<unique_ptr<IntervalIndex<ReaderT, uint32_t>>> scale2Index;
for (size_t i = 0; i < treesReader.Size(); ++i)
- scale2Index.emplace_back(new IntervalIndex<ReaderT>(treesReader.SubReader(static_cast<uint32_t>(i))));
+ {
+ scale2Index.emplace_back(make_unique<IntervalIndex<ReaderT, uint32_t>>(
+ treesReader.SubReader(static_cast<uint32_t>(i))));
+ }
// Pass full coverage as input for test.
uint64_t beg = 0;
diff --git a/indexer/CMakeLists.txt b/indexer/CMakeLists.txt
index b25a5e9ce9..2e227b4024 100644
--- a/indexer/CMakeLists.txt
+++ b/indexer/CMakeLists.txt
@@ -13,6 +13,7 @@ set(
categories_index.hpp
cell_coverer.hpp
cell_id.hpp
+ cell_value_pair.hpp
centers_table.cpp
centers_table.hpp
cities_boundaries_serdes.hpp
@@ -91,6 +92,10 @@ set(
index.hpp
interval_index_builder.hpp
interval_index.hpp
+ locality_index_builder.hpp
+ locality_index_builder.cpp
+ locality_object.hpp
+ locality_object.cpp
map_object.cpp
map_object.hpp
map_style_reader.cpp
diff --git a/indexer/cell_value_pair.hpp b/indexer/cell_value_pair.hpp
new file mode 100644
index 0000000000..5533ab1706
--- /dev/null
+++ b/indexer/cell_value_pair.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "base/macros.hpp"
+
+#include <cstdint>
+
+namespace covering
+{
+template <typename Value>
+class CellValuePair
+{
+public:
+ using ValueType = Value;
+
+ CellValuePair() = default;
+
+ CellValuePair(uint64_t cell, Value value)
+ : m_cellLo(UINT64_LO(cell)), m_cellHi(UINT64_HI(cell)), m_value(value)
+ {
+ }
+
+ bool operator<(CellValuePair const & rhs) const
+ {
+ if (m_cellHi != rhs.m_cellHi)
+ return m_cellHi < rhs.m_cellHi;
+ if (m_cellLo != rhs.m_cellLo)
+ return m_cellLo < rhs.m_cellLo;
+ return m_value < rhs.m_value;
+ }
+
+ uint64_t GetCell() const { return UINT64_FROM_UINT32(m_cellHi, m_cellLo); }
+ Value GetValue() const { return m_value; }
+
+private:
+ uint32_t m_cellLo = 0;
+ uint32_t m_cellHi = 0;
+ Value m_value = 0;
+};
+
+// For backward compatibility.
+static_assert(sizeof(CellValuePair<uint32_t>) == 12, "");
+#ifndef OMIM_OS_LINUX
+static_assert(std::is_trivially_copyable<CellValuePair<uint32_t>>::value, "");
+#endif
+} // namespace covering
diff --git a/indexer/data_factory.hpp b/indexer/data_factory.hpp
index 079ed87c83..c2589ef70e 100644
--- a/indexer/data_factory.hpp
+++ b/indexer/data_factory.hpp
@@ -24,9 +24,9 @@ public:
inline feature::RegionData const & GetRegionData() const { return m_regionData; }
template <typename Reader>
- std::unique_ptr<IntervalIndex<Reader>> CreateIndex(Reader const & reader) const
+ std::unique_ptr<IntervalIndex<Reader, uint32_t>> CreateIndex(Reader const & reader) const
{
CHECK_NOT_EQUAL(m_version.GetFormat(), version::Format::v1, ("Old maps format is not supported"));
- return std::make_unique<IntervalIndex<Reader>>(reader);
+ return std::make_unique<IntervalIndex<Reader, uint32_t>>(reader);
}
};
diff --git a/indexer/displacement_manager.hpp b/indexer/displacement_manager.hpp
index 4b642a2367..48bff14455 100644
--- a/indexer/displacement_manager.hpp
+++ b/indexer/displacement_manager.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "indexer/cell_id.hpp"
+#include "indexer/cell_value_pair.hpp"
#include "indexer/classificator.hpp"
#include "indexer/drawing_rules.hpp"
#include "indexer/feature_data.hpp"
@@ -28,40 +29,11 @@ double constexpr kPOIDisplacementRadiusMultiplier = kPOIDisplacementRadiusPixels
namespace covering
{
-class CellFeaturePair
-{
-public:
- CellFeaturePair() : m_cellLo(0), m_cellHi(0), m_feature(0) {}
-
- CellFeaturePair(uint64_t cell, uint32_t feature)
- : m_cellLo(UINT64_LO(cell)), m_cellHi(UINT64_HI(cell)), m_feature(feature)
- {
- }
-
- bool operator<(CellFeaturePair const & rhs) const
- {
- if (m_cellHi != rhs.m_cellHi)
- return m_cellHi < rhs.m_cellHi;
- if (m_cellLo != rhs.m_cellLo)
- return m_cellLo < rhs.m_cellLo;
- return m_feature < rhs.m_feature;
- }
-
- uint64_t GetCell() const { return UINT64_FROM_UINT32(m_cellHi, m_cellLo); }
- uint32_t GetFeature() const { return m_feature; }
-private:
- uint32_t m_cellLo;
- uint32_t m_cellHi;
- uint32_t m_feature;
-};
-static_assert(sizeof(CellFeaturePair) == 12, "");
-#ifndef OMIM_OS_LINUX
-static_assert(std::is_trivially_copyable<CellFeaturePair>::value, "");
-#endif
-
class CellFeatureBucketTuple
{
public:
+ using CellFeaturePair = CellValuePair<uint32_t>;
+
CellFeatureBucketTuple() : m_bucket(0) {}
CellFeatureBucketTuple(CellFeaturePair const & p, uint32_t bucket) : m_pair(p), m_bucket(bucket)
{
@@ -91,6 +63,8 @@ template <class TSorter>
class DisplacementManager
{
public:
+ using CellFeaturePair = CellFeatureBucketTuple::CellFeaturePair;
+
DisplacementManager(TSorter & sorter) : m_sorter(sorter) {}
/// Add feature at bucket (zoom) to displaceable queue if possible. Pass to bucket otherwise.
diff --git a/indexer/feature_covering.cpp b/indexer/feature_covering.cpp
index 2c468059a0..b5b15a74dd 100644
--- a/indexer/feature_covering.cpp
+++ b/indexer/feature_covering.cpp
@@ -1,7 +1,9 @@
#include "indexer/feature_covering.hpp"
+
#include "indexer/cell_coverer.hpp"
#include "indexer/cell_id.hpp"
#include "indexer/feature.hpp"
+#include "indexer/locality_object.hpp"
#include "indexer/scales.hpp"
#include "geometry/covering_utils.hpp"
@@ -113,25 +115,23 @@ public:
}
};
-}
-
-namespace covering
-{
-
-vector<int64_t> CoverFeature(FeatureType const & f, int cellDepth, uint64_t cellPenaltyArea)
+void GetIntersection(FeatureType const & f, FeatureIntersector & fIsect)
{
// We need to cover feature for the best geometry, because it's indexed once for the
// first top level scale. Do reset current cached geometry first.
f.ResetGeometry();
int const scale = FeatureType::BEST_GEOMETRY;
- FeatureIntersector fIsect;
f.ForEachPoint(fIsect, scale);
f.ForEachTriangle(fIsect, scale);
CHECK(!(fIsect.m_trg.empty() && fIsect.m_polyline.empty()) &&
f.GetLimitRect(scale).IsValid(), (f.DebugString(scale)));
+}
+vector<int64_t> CoverIntersection(FeatureIntersector const & fIsect, int cellDepth,
+ uint64_t cellPenaltyArea)
+{
if (fIsect.m_trg.empty() && fIsect.m_polyline.size() == 1)
{
m2::PointD const pt = fIsect.m_polyline[0];
@@ -149,6 +149,25 @@ vector<int64_t> CoverFeature(FeatureType const & f, int cellDepth, uint64_t cell
return res;
}
+}
+
+namespace covering
+{
+vector<int64_t> CoverFeature(FeatureType const & f, int cellDepth, uint64_t cellPenaltyArea)
+{
+ FeatureIntersector fIsect;
+ GetIntersection(f, fIsect);
+ return CoverIntersection(fIsect, cellDepth, cellPenaltyArea);
+}
+
+vector<int64_t> CoverLocality(indexer::LocalityObject const & o, int cellDepth,
+ uint64_t cellPenaltyArea)
+{
+ FeatureIntersector fIsect;
+ o.ForEachPoint(fIsect);
+ o.ForEachTriangle(fIsect);
+ return CoverIntersection(fIsect, cellDepth, cellPenaltyArea);
+}
void SortAndMergeIntervals(IntervalsT v, IntervalsT & res)
{
diff --git a/indexer/feature_covering.hpp b/indexer/feature_covering.hpp
index 83efd421ed..eff609a4d7 100644
--- a/indexer/feature_covering.hpp
+++ b/indexer/feature_covering.hpp
@@ -9,6 +9,11 @@
class FeatureType;
+namespace indexer
+{
+class LocalityObject;
+} // namespace indexer
+
namespace covering
{
typedef pair<int64_t, int64_t> IntervalT;
@@ -19,6 +24,9 @@ namespace covering
int cellDepth,
uint64_t cellPenaltyArea);
+ vector<int64_t> CoverLocality(indexer::LocalityObject const & o, int cellDepth,
+ uint64_t cellPenaltyArea);
+
void AppendLowerLevels(RectId id, int cellDepth, IntervalsT & intervals);
// Cover viewport with RectIds and append their RectIds as well.
diff --git a/indexer/feature_loader.cpp b/indexer/feature_loader.cpp
index 5493febc6c..7b2fbdcef2 100644
--- a/indexer/feature_loader.cpp
+++ b/indexer/feature_loader.cpp
@@ -159,21 +159,13 @@ void LoaderCurrent::ParseHeader2()
trgCount += 2;
char const * start = static_cast<char const *>(src.PtrC());
-
- FeatureType::points_t points;
- src = ArrayByteSource(serial::LoadInnerTriangles(start, trgCount, cp, points));
-
+ src = ArrayByteSource(serial::LoadInnerTriangles(start, trgCount, cp, m_pF->m_triangles));
m_pF->m_innerStats.m_strips = static_cast<uint32_t>(src.PtrC() - start);
-
- for (uint8_t i = 2; i < trgCount; ++i)
- {
- m_pF->m_triangles.push_back(points[i-2]);
- m_pF->m_triangles.push_back(points[i-1]);
- m_pF->m_triangles.push_back(points[i]);
- }
}
else
+ {
ReadOffsets(src, trgMask, m_trgOffsets);
+ }
}
m_pF->m_innerStats.m_size = static_cast<uint32_t>(src.PtrC() - DataPtr());
diff --git a/indexer/geometry_serialization.hpp b/indexer/geometry_serialization.hpp
index 31751be8cc..fe38201c67 100644
--- a/indexer/geometry_serialization.hpp
+++ b/indexer/geometry_serialization.hpp
@@ -153,9 +153,21 @@ namespace serial
}
inline void const * LoadInnerTriangles(void const * pBeg, size_t count,
- CodingParams const & params, OutPointsT & points)
+ CodingParams const & params, OutPointsT & triangles)
{
- return LoadInner(&geo_coding::DecodeTriangleStrip, pBeg, count, params, points);
+ CHECK_GREATER_OR_EQUAL(count, 2, ());
+ triangles.clear();
+ OutPointsT points;
+ void const * res = LoadInner(&geo_coding::DecodeTriangleStrip, pBeg, count, params, points);
+
+ triangles.reserve((count - 2) * 3);
+ for (size_t i = 2; i < count; ++i)
+ {
+ triangles.push_back(points[i - 2]);
+ triangles.push_back(points[i - 1]);
+ triangles.push_back(points[i]);
+ }
+ return res;
}
class TrianglesChainSaver
diff --git a/indexer/indexer_tests/interval_index_test.cpp b/indexer/indexer_tests/interval_index_test.cpp
index a128187a45..0372b96f07 100644
--- a/indexer/indexer_tests/interval_index_test.cpp
+++ b/indexer/indexer_tests/interval_index_test.cpp
@@ -12,11 +12,15 @@ namespace
{
struct CellIdFeaturePairForTest
{
- CellIdFeaturePairForTest(uint64_t cell, uint32_t feature) : m_Cell(cell), m_Feature(feature) {}
- uint64_t GetCell() const { return m_Cell; }
- uint32_t GetFeature() const { return m_Feature; }
- uint64_t m_Cell;
- uint32_t m_Feature;
+ using ValueType = uint32_t;
+
+ CellIdFeaturePairForTest(uint64_t cell, uint32_t value) : m_cell(cell), m_value(value) {}
+
+ uint64_t GetCell() const { return m_cell; }
+ uint32_t GetValue() const { return m_value; }
+
+ uint64_t m_cell;
+ uint32_t m_value;
};
}
@@ -119,7 +123,7 @@ UNIT_TEST(IntervalIndex_Serialized)
TEST_EQUAL(serialIndex, vector<uint8_t>(expSerial, expSerial + ARRAY_SIZE(expSerial) - 1), ());
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
uint32_t expected [] = {0, 1, 2};
vector<uint32_t> values;
TEST_EQUAL(index.KeyEnd(), 0x10000, ());
@@ -137,7 +141,7 @@ UNIT_TEST(IntervalIndex_Simple)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
TEST_EQUAL(index.KeyEnd(), 0x10000000000ULL, ());
{
uint32_t expected [] = {0, 1, 2};
@@ -188,7 +192,7 @@ UNIT_TEST(IntervalIndex_Empty)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
{
vector<uint32_t> values;
index.ForEach(MakeBackInsertFunctor(values), 0ULL, 0xFFFFFFFFFFULL);
@@ -207,7 +211,7 @@ UNIT_TEST(IntervalIndex_Simple2)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
{
uint32_t expected [] = {0, 1, 2, 3};
vector<uint32_t> values;
@@ -226,7 +230,7 @@ UNIT_TEST(IntervalIndex_Simple3)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
{
uint32_t expected [] = {0, 1};
vector<uint32_t> values;
@@ -245,7 +249,7 @@ UNIT_TEST(IntervalIndex_Simple4)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
{
uint32_t expected [] = {0, 1};
vector<uint32_t> values;
@@ -266,7 +270,7 @@ UNIT_TEST(IntervalIndex_Simple5)
MemWriter<vector<char> > writer(serialIndex);
BuildIntervalIndex(data.begin(), data.end(), writer, 40);
MemReader reader(&serialIndex[0], serialIndex.size());
- IntervalIndex<MemReader> index(reader);
+ IntervalIndex<MemReader, uint32_t> index(reader);
{
uint32_t expected [] = {0, 1, 2, 3};
vector<uint32_t> values;
diff --git a/indexer/interval_index.hpp b/indexer/interval_index.hpp
index 147740a85e..477f5fe34c 100644
--- a/indexer/interval_index.hpp
+++ b/indexer/interval_index.hpp
@@ -32,7 +32,7 @@ public:
enum { kVersion = 1 };
};
-template <class ReaderT>
+template <class ReaderT, typename Value>
class IntervalIndex : public IntervalIndexBase
{
typedef IntervalIndexBase base_t;
@@ -83,7 +83,7 @@ private:
ArrayByteSource src(&data[0]);
void const * pEnd = &data[0] + size;
- uint32_t value = 0;
+ Value value = 0;
while (src.Ptr() < pEnd)
{
uint32_t key = 0;
@@ -91,7 +91,7 @@ private:
key = SwapIfBigEndian(key);
if (key > end)
break;
- value += ReadVarInt<int32_t>(src);
+ value += ReadVarInt<int64_t>(src);
if (key >= beg)
f(value);
}
diff --git a/indexer/interval_index_builder.hpp b/indexer/interval_index_builder.hpp
index e2498b1924..86fa29d511 100644
--- a/indexer/interval_index_builder.hpp
+++ b/indexer/interval_index_builder.hpp
@@ -29,7 +29,6 @@
// +------------------------------+
// | Level N data |
// +------------------------------+
-
class IntervalIndexBuilder
{
public:
@@ -46,8 +45,8 @@ public:
uint32_t GetLevelCount() const { return m_Levels; }
- template <class WriterT, typename CellIdValueIterT>
- void BuildIndex(WriterT & writer, CellIdValueIterT const & beg, CellIdValueIterT const & end)
+ template <class Writer, typename CellIdValueIter>
+ void BuildIndex(Writer & writer, CellIdValueIter const & beg, CellIdValueIter const & end)
{
CHECK(CheckIntervalIndexInputSequence(beg, end), ());
@@ -107,16 +106,16 @@ public:
writer.Seek(lastPos);
}
- template <typename CellIdValueIterT>
- bool CheckIntervalIndexInputSequence(CellIdValueIterT const & beg, CellIdValueIterT const & end)
+ template <typename CellIdValueIter>
+ bool CheckIntervalIndexInputSequence(CellIdValueIter const & beg, CellIdValueIter const & end)
{
// Check that [beg, end) is sorted and log most populous cell.
if (beg != end)
{
uint32_t count = 0;
uint32_t maxCount = 0;
- typename CellIdValueIterT::value_type mostPopulousCell = *beg;
- CellIdValueIterT it = beg;
+ typename CellIdValueIter::value_type mostPopulousCell = *beg;
+ CellIdValueIter it = beg;
uint64_t prev = it->GetCell();
for (++it; it != end; ++it)
{
@@ -132,16 +131,17 @@ public:
}
if (maxCount > 0)
{
- LOG(LINFO, ("Most populous cell:", maxCount,
- mostPopulousCell.GetCell(), mostPopulousCell.GetFeature()));
+ LOG(LINFO, ("Most populous cell:", maxCount, mostPopulousCell.GetCell(),
+ mostPopulousCell.GetValue()));
}
}
uint32_t const keyBits = 8 * m_LeafBytes + m_Levels * m_BitsPerLevel;
- for (CellIdValueIterT it = beg; it != end; ++it)
+ for (CellIdValueIter it = beg; it != end; ++it)
{
CHECK_LESS(it->GetCell(), 1ULL << keyBits, ());
- CHECK_EQUAL(it->GetFeature(), static_cast<uint32_t>(it->GetFeature()), ());
+ // We use static_cast<int64_t>(value) in BuildLeaves to store values difference as VarInt.
+ CHECK_EQUAL(it->GetValue(), static_cast<int64_t>(it->GetValue()), ());
}
return true;
@@ -170,8 +170,8 @@ public:
}
}
- template <class WriterT, typename CellIdValueIterT>
- void BuildLevel(WriterT & writer, CellIdValueIterT const & beg, CellIdValueIterT const & end,
+ template <class Writer, typename CellIdValueIter>
+ void BuildLevel(Writer & writer, CellIdValueIter const & beg, CellIdValueIter const & end,
int level, uint32_t const * childSizesBeg, uint32_t const * childSizesEnd,
vector<uint32_t> & sizes)
{
@@ -182,7 +182,7 @@ public:
uint64_t prevKey = static_cast<uint64_t>(-1);
uint32_t childOffset = 0;
uint32_t nextChildOffset = 0;
- for (CellIdValueIterT it = beg; it != end; ++it)
+ for (CellIdValueIter it = beg; it != end; ++it)
{
uint64_t const key = it->GetCell() >> skipBits;
if (key == prevKey)
@@ -204,18 +204,20 @@ public:
ASSERT_EQUAL(childSizesBeg, childSizesEnd, ());
}
- template <class WriterT, typename CellIdValueIterT>
- void BuildLeaves(WriterT & writer, CellIdValueIterT const & beg, CellIdValueIterT const & end,
+ template <class Writer, typename CellIdValueIter>
+ void BuildLeaves(Writer & writer, CellIdValueIter const & beg, CellIdValueIter const & end,
vector<uint32_t> & sizes)
{
+ using Value = typename CellIdValueIter::value_type::ValueType;
+
uint32_t const skipBits = 8 * m_LeafBytes;
uint64_t prevKey = 0;
uint64_t prevValue = 0;
uint64_t prevPos = writer.Pos();
- for (CellIdValueIterT it = beg; it != end; ++it)
+ for (CellIdValueIter it = beg; it != end; ++it)
{
uint64_t const key = it->GetCell();
- uint64_t const value = it->GetFeature();
+ Value const value = it->GetValue();
if (it != beg && (key >> skipBits) != (prevKey >> skipBits))
{
sizes.push_back(static_cast<uint32_t>(writer.Pos() - prevPos));
@@ -265,9 +267,9 @@ private:
uint32_t m_Levels, m_BitsPerLevel, m_LeafBytes, m_LastBitsMask;
};
-template <class WriterT, typename CellIdValueIterT>
-void BuildIntervalIndex(CellIdValueIterT const & beg, CellIdValueIterT const & end,
- WriterT & writer, uint32_t keyBits)
+template <class Writer, typename CellIdValueIter>
+void BuildIntervalIndex(CellIdValueIter const & beg, CellIdValueIter const & end, Writer & writer,
+ uint32_t keyBits)
{
IntervalIndexBuilder(keyBits, 1).BuildIndex(writer, beg, end);
}
diff --git a/indexer/locality_index_builder.cpp b/indexer/locality_index_builder.cpp
new file mode 100644
index 0000000000..d1fa29d010
--- /dev/null
+++ b/indexer/locality_index_builder.cpp
@@ -0,0 +1,88 @@
+#include "indexer/locality_index_builder.hpp"
+
+#include "indexer/locality_object.hpp"
+
+#include "defines.hpp"
+
+#include "coding/file_container.hpp"
+#include "coding/var_record_reader.hpp"
+
+#include "base/logging.hpp"
+
+namespace indexer
+{
+namespace
+{
+template <class ReaderT>
+class LocalityVector
+{
+ DISALLOW_COPY(LocalityVector);
+
+public:
+ LocalityVector(ReaderT const & reader) : m_recordReader(reader, 256 /* expectedRecordSize */) {}
+
+ template <class ToDo>
+ void ForEach(ToDo && toDo) const
+ {
+ m_recordReader.ForEachRecord([&](uint32_t pos, char const * data, uint32_t /*size*/) {
+ LocalityObject o;
+ o.Deserialize(data);
+ toDo(o);
+ });
+ }
+
+private:
+ friend class LocalityVectorReader;
+
+ VarRecordReader<FilesContainerR::TReader, &VarRecordSizeReaderVarint> m_recordReader;
+};
+
+// Test features vector (reader) that combines all the needed data for stand-alone work.
+// Used in generator_tool and unit tests.
+class LocalityVectorReader
+{
+ DISALLOW_COPY(LocalityVectorReader);
+
+public:
+ explicit LocalityVectorReader(string const & filePath)
+ : m_cont(filePath), m_vector(m_cont.GetReader(LOCALITY_DATA_FILE_TAG))
+ {
+ }
+
+ LocalityVector<ModelReaderPtr> const & GetVector() const { return m_vector; }
+
+private:
+ FilesContainerR m_cont;
+ LocalityVector<ModelReaderPtr> m_vector;
+};
+} // namespace
+
+bool BuildLocalityIndexFromDataFile(string const & dataFile, string const & tmpFile)
+{
+ try
+ {
+ string const idxFileName(tmpFile + LOCALITY_INDEX_TMP_EXT);
+ {
+ LocalityVectorReader localities(datFile);
+ FileWriter writer(idxFileName);
+
+ covering::BuildLocalityIndex(localities.GetVector(), writer, tmpFile);
+ }
+
+ FilesContainerW(datFile, FileWriter::OP_WRITE_EXISTING)
+ .Write(idxFileName, LOCALITY_INDEX_FILE_TAG);
+ FileWriter::DeleteFileX(idxFileName);
+ }
+ catch (Reader::Exception const & e)
+ {
+ LOG(LERROR, ("Error while reading file:", e.Msg()));
+ return false;
+ }
+ catch (Writer::Exception const & e)
+ {
+ LOG(LERROR, ("Error writing index file:", e.Msg()));
+ return false;
+ }
+ return true;
+}
+} // namespace indexer
diff --git a/indexer/locality_index_builder.hpp b/indexer/locality_index_builder.hpp
new file mode 100644
index 0000000000..3719cac9e8
--- /dev/null
+++ b/indexer/locality_index_builder.hpp
@@ -0,0 +1,59 @@
+#pragma once
+#include "indexer/cell_id.hpp"
+#include "indexer/cell_value_pair.hpp"
+#include "indexer/feature_covering.hpp"
+#include "indexer/interval_index_builder.hpp"
+#include "indexer/locality_object.hpp"
+#include "indexer/scales.hpp"
+
+#include "coding/dd_vector.hpp"
+#include "coding/file_sort.hpp"
+#include "coding/writer.hpp"
+
+#include "base/logging.hpp"
+#include "base/macros.hpp"
+#include "base/scope_guard.hpp"
+
+#include "defines.hpp"
+
+#include <string>
+#include <vector>
+
+namespace covering
+{
+template <class TObjectsVector, class TWriter>
+void BuildLocalityIndex(TObjectsVector const & objects, TWriter & writer,
+ string const & tmpFilePrefix)
+{
+ string const cellsToValueFile = tmpFilePrefix + CELL2LOCALITY_SORTED_EXT + ".all";
+ MY_SCOPE_GUARD(cellsToValueFileGuard, bind(&FileWriter::DeleteFileX, cellsToValueFile));
+ {
+ FileWriter cellsToValueWriter(cellsToValueFile);
+
+ WriterFunctor<FileWriter> out(cellsToValueWriter);
+ FileSorter<CellValuePair<uint64_t>, WriterFunctor<FileWriter>> sorter(
+ 1024 * 1024 /* bufferBytes */, tmpFilePrefix + CELL2LOCALITY_TMP_EXT, out);
+ objects.ForEach([&sorter](indexer::LocalityObject const & o) {
+ // @todo(t.yan): adjust cellPenaltyArea for whole world locality index.
+ std::vector<int64_t> const cells =
+ covering::CoverLocality(o, GetCodingDepth(scales::GetUpperScale()), 250 /* cellPenaltyArea */);
+ for (auto const & cell : cells)
+ sorter.Add(CellValuePair<uint64_t>(cell, o.GetStoredId()));
+ });
+ sorter.SortAndFinish();
+ }
+
+ FileReader reader(cellsToValueFile);
+ DDVector<CellValuePair<uint64_t>, FileReader, uint64_t> cellsToValue(reader);
+
+ {
+ BuildIntervalIndex(cellsToValue.begin(), cellsToValue.end(), writer,
+ RectId::DEPTH_LEVELS * 2 + 1);
+ }
+}
+} // namespace covering
+
+namespace indexer
+{
+bool BuildLocalityIndexFromDataFile(std::string const & dataFile, std::string const & tmpFile);
+} // namespace indexer
diff --git a/indexer/locality_object.cpp b/indexer/locality_object.cpp
new file mode 100644
index 0000000000..c348d31315
--- /dev/null
+++ b/indexer/locality_object.cpp
@@ -0,0 +1,34 @@
+#include "indexer/locality_object.hpp"
+
+#include "indexer/feature_decl.hpp"
+#include "indexer/geometry_serialization.hpp"
+
+#include "coding/byte_stream.hpp"
+
+namespace indexer
+{
+void LocalityObject::Deserialize(char const * data)
+{
+ ArrayByteSource src(data);
+ serial::CodingParams cp = {};
+ ReadPrimitiveFromSource(src, m_id);
+ uint8_t type;
+ ReadPrimitiveFromSource(src, type);
+
+ if (type == feature::GEOM_POINT)
+ {
+ m_points.push_back(serial::LoadPoint(src, cp));
+ return;
+ }
+
+ ASSERT_EQUAL(type, feature::GEOM_AREA, ("Only supported types are GEOM_POINT and GEOM_AREA."));
+ uint8_t trgCount;
+ ReadPrimitiveFromSource(src, trgCount);
+ if (trgCount > 0)
+ {
+ trgCount += 2;
+ char const * start = static_cast<char const *>(src.PtrC());
+ serial::LoadInnerTriangles(start, trgCount, cp, m_triangles);
+ }
+}
+} // namespace indexer
diff --git a/indexer/locality_object.hpp b/indexer/locality_object.hpp
new file mode 100644
index 0000000000..b89b030ec2
--- /dev/null
+++ b/indexer/locality_object.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "geometry/point2d.hpp"
+
+#include "base/buffer_vector.hpp"
+#include "base/osm_id.hpp"
+
+#include <cstdint>
+#include <vector>
+
+namespace indexer
+{
+// Class for intermediate objects used to build LocalityIndex.
+class LocalityObject
+{
+public:
+ // Decodes id stored in LocalityIndex. See GetStoredId().
+ static osm::Id FromStoredId(uint64_t storedId) { return osm::Id(storedId >> 2 | storedId << 62); }
+
+ // We need LocalityIndex object id to be at most numeric_limits<int64_t>::max().
+ // We use incremental encoding for ids and need to keep ids of close object close if it is possible.
+ // To ensure it we move two leading bits which encodes object type to the end of id.
+ uint64_t GetStoredId() const { return m_id << 2 | m_id >> 62; }
+
+ void Deserialize(char const * data);
+
+ template <typename ToDo>
+ void ForEachPoint(ToDo && toDo) const
+ {
+ for (auto const & p : m_points)
+ toDo(p);
+ }
+
+ template <typename ToDo>
+ void ForEachTriangle(ToDo && toDo) const
+ {
+ for (size_t i = 2; i < m_triangles.size(); i += 3)
+ toDo(m_triangles[i - 2], m_triangles[i - 1], m_triangles[i]);
+ }
+
+private:
+ uint64_t m_id = 0;
+ std::vector<m2::PointD> m_points;
+ // m_triangles[3 * i], m_triangles[3 * i + 1], m_triangles[3 * i + 2] form the i-th triangle.
+ buffer_vector<m2::PointD, 32> m_triangles;
+};
+} // namespace indexer
diff --git a/indexer/scale_index.hpp b/indexer/scale_index.hpp
index bcc71d52ba..096f00c200 100644
--- a/indexer/scale_index.hpp
+++ b/indexer/scale_index.hpp
@@ -24,18 +24,13 @@ public:
}
};
-template <class ReaderT>
+template <class Reader>
class ScaleIndex : public ScaleIndexBase
{
public:
- typedef ReaderT ReaderType;
-
ScaleIndex() = default;
- ScaleIndex(ReaderT const & reader, IndexFactory const & factory)
- {
- Attach(reader, factory);
- }
+ ScaleIndex(Reader const & reader, IndexFactory const & factory) { Attach(reader, factory); }
~ScaleIndex()
{
@@ -47,12 +42,12 @@ public:
m_IndexForScale.clear();
}
- void Attach(ReaderT const & reader, IndexFactory const & factory)
+ void Attach(Reader const & reader, IndexFactory const & factory)
{
Clear();
- ReaderSource<ReaderT> source(reader);
- VarSerialVectorReader<ReaderT> treesReader(source);
+ ReaderSource<Reader> source(reader);
+ VarSerialVectorReader<Reader> treesReader(source);
for (uint32_t i = 0; i < treesReader.Size(); ++i)
m_IndexForScale.push_back(factory.CreateIndex(treesReader.SubReader(i)));
}
@@ -69,5 +64,5 @@ public:
}
private:
- std::vector<std::unique_ptr<IntervalIndex<ReaderT>>> m_IndexForScale;
+ std::vector<std::unique_ptr<IntervalIndex<Reader, uint32_t>>> m_IndexForScale;
};
diff --git a/indexer/scale_index_builder.hpp b/indexer/scale_index_builder.hpp
index eb4fedce28..21442d4c12 100644
--- a/indexer/scale_index_builder.hpp
+++ b/indexer/scale_index_builder.hpp
@@ -120,23 +120,6 @@ private:
vector<uint32_t> & m_cellsInBucket;
};
-template <class SinkT>
-class CellFeaturePairSinkAdapter
-{
-public:
- explicit CellFeaturePairSinkAdapter(SinkT & sink) : m_Sink(sink) {}
-
- void operator() (int64_t cellId, uint64_t value) const
- {
- // uint64_t -> uint32_t : assume that feature dat file not more than 4Gb
- CellFeaturePair cellFeaturePair(cellId, static_cast<uint32_t>(value));
- m_Sink.Write(&cellFeaturePair, sizeof(cellFeaturePair));
- }
-
-private:
- SinkT & m_Sink;
-};
-
template <class TFeaturesVector, class TWriter>
void IndexScales(feature::DataHeader const & header, TFeaturesVector const & features,
TWriter & writer, string const & tmpFilePrefix)
@@ -200,7 +183,8 @@ void IndexScales(feature::DataHeader const & header, TFeaturesVector const & fea
{
FileReader reader(cellsToFeatureFile);
- DDVector<CellFeaturePair, FileReader, uint64_t> cellsToFeatures(reader);
+ DDVector<CellFeatureBucketTuple::CellFeaturePair, FileReader, uint64_t> cellsToFeatures(
+ reader);
SubWriter<TWriter> subWriter(writer);
LOG(LINFO, ("Building interval index for bucket:", bucket));
BuildIntervalIndex(cellsToFeatures.begin(), cellsToFeatures.end(), subWriter,
diff --git a/xcode/indexer/indexer.xcodeproj/project.pbxproj b/xcode/indexer/indexer.xcodeproj/project.pbxproj
index 51e60d50f6..144b336623 100644
--- a/xcode/indexer/indexer.xcodeproj/project.pbxproj
+++ b/xcode/indexer/indexer.xcodeproj/project.pbxproj
@@ -69,6 +69,11 @@
3D74EF241F8F559D0081202C /* ugc_types_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D74EF231F8F559D0081202C /* ugc_types_test.cpp */; };
3D928F671D50F9FE001670E0 /* index_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D928F651D50F9FE001670E0 /* index_helpers.cpp */; };
3D928F681D50F9FE001670E0 /* index_helpers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D928F661D50F9FE001670E0 /* index_helpers.hpp */; };
+ 40009062201F5CB000963E18 /* cell_value_pair.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4000905D201F5CAF00963E18 /* cell_value_pair.hpp */; };
+ 40009063201F5CB000963E18 /* locality_object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4000905E201F5CAF00963E18 /* locality_object.cpp */; };
+ 40009064201F5CB000963E18 /* locality_index_builder.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4000905F201F5CAF00963E18 /* locality_index_builder.hpp */; };
+ 40009065201F5CB000963E18 /* locality_object.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 40009060201F5CB000963E18 /* locality_object.hpp */; };
+ 40009066201F5CB000963E18 /* locality_index_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40009061201F5CB000963E18 /* locality_index_builder.cpp */; };
4099F6491FC7142A002A7B05 /* fake_feature_ids.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4099F6471FC71429002A7B05 /* fake_feature_ids.cpp */; };
4099F64A1FC7142A002A7B05 /* fake_feature_ids.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4099F6481FC7142A002A7B05 /* fake_feature_ids.hpp */; };
456B3FB41EDEEB65009B3D1F /* scales_patch.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 456B3FB31EDEEB65009B3D1F /* scales_patch.hpp */; };
@@ -300,6 +305,11 @@
3D74EF231F8F559D0081202C /* ugc_types_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ugc_types_test.cpp; sourceTree = "<group>"; };
3D928F651D50F9FE001670E0 /* index_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_helpers.cpp; sourceTree = "<group>"; };
3D928F661D50F9FE001670E0 /* index_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = index_helpers.hpp; sourceTree = "<group>"; };
+ 4000905D201F5CAF00963E18 /* cell_value_pair.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cell_value_pair.hpp; sourceTree = "<group>"; };
+ 4000905E201F5CAF00963E18 /* locality_object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = locality_object.cpp; sourceTree = "<group>"; };
+ 4000905F201F5CAF00963E18 /* locality_index_builder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = locality_index_builder.hpp; sourceTree = "<group>"; };
+ 40009060201F5CB000963E18 /* locality_object.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = locality_object.hpp; sourceTree = "<group>"; };
+ 40009061201F5CB000963E18 /* locality_index_builder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = locality_index_builder.cpp; sourceTree = "<group>"; };
4099F6471FC71429002A7B05 /* fake_feature_ids.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fake_feature_ids.cpp; sourceTree = "<group>"; };
4099F6481FC7142A002A7B05 /* fake_feature_ids.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = fake_feature_ids.hpp; sourceTree = "<group>"; };
456B3FB31EDEEB65009B3D1F /* scales_patch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scales_patch.hpp; sourceTree = "<group>"; };
@@ -672,6 +682,11 @@
6753409C1A3F53CB00A0A8C3 /* indexer */ = {
isa = PBXGroup;
children = (
+ 4000905D201F5CAF00963E18 /* cell_value_pair.hpp */,
+ 40009061201F5CB000963E18 /* locality_index_builder.cpp */,
+ 4000905F201F5CAF00963E18 /* locality_index_builder.hpp */,
+ 4000905E201F5CAF00963E18 /* locality_object.cpp */,
+ 40009060201F5CB000963E18 /* locality_object.hpp */,
456E1B141F90E5B6009C32E1 /* cities_boundaries_serdes.hpp */,
456E1B171F90E5B7009C32E1 /* city_boundary.hpp */,
456E1B151F90E5B6009C32E1 /* ftypes_sponsored.cpp */,
@@ -847,6 +862,7 @@
F6381BFA1CD26C9C004CA943 /* new_feature_categories.hpp in Headers */,
56C74C231C749E4700B71B9F /* search_delimiters.hpp in Headers */,
675341131A3F540F00A0A8C3 /* feature_algo.hpp in Headers */,
+ 40009064201F5CB000963E18 /* locality_index_builder.hpp in Headers */,
6726C1D21A49DAAC005EEA39 /* feature_meta.hpp in Headers */,
347F337F1C454242009758CC /* trie_builder.hpp in Headers */,
34664CF71D49FEC1003D7096 /* centers_table.hpp in Headers */,
@@ -875,6 +891,7 @@
6753413F1A3F540F00A0A8C3 /* scale_index.hpp in Headers */,
6753410E1A3F540F00A0A8C3 /* drawing_rules.hpp in Headers */,
670C615C1AB0691900C38A8C /* features_offsets_table.hpp in Headers */,
+ 40009065201F5CB000963E18 /* locality_object.hpp in Headers */,
6758AED41BB4413000C26E27 /* drules_selector.hpp in Headers */,
675341061A3F540F00A0A8C3 /* coding_params.hpp in Headers */,
3D0AEAF91FBAF9E900AD042B /* test_with_custom_mwms.hpp in Headers */,
@@ -884,6 +901,7 @@
456E1B1A1F90E5B7009C32E1 /* ftypes_sponsored.hpp in Headers */,
675341411A3F540F00A0A8C3 /* scales.hpp in Headers */,
675341321A3F540F00A0A8C3 /* interval_index_builder.hpp in Headers */,
+ 40009062201F5CB000963E18 /* cell_value_pair.hpp in Headers */,
347F337C1C454242009758CC /* rank_table.hpp in Headers */,
6753414B1A3F540F00A0A8C3 /* tesselator_decl.hpp in Headers */,
F61F83071E4B187500B37B7A /* road_shields_parser.hpp in Headers */,
@@ -1089,6 +1107,7 @@
3D928F671D50F9FE001670E0 /* index_helpers.cpp in Sources */,
3D0AEAFA1FBAF9E900AD042B /* test_with_custom_mwms.cpp in Sources */,
340DF9D01C1FF04D00B5C7EC /* osm_editor.cpp in Sources */,
+ 40009066201F5CB000963E18 /* locality_index_builder.cpp in Sources */,
67F183731BD4FCF500AB1840 /* map_style.cpp in Sources */,
6758AED31BB4413000C26E27 /* drules_selector.cpp in Sources */,
6753411A1A3F540F00A0A8C3 /* feature_impl.cpp in Sources */,
@@ -1111,6 +1130,7 @@
675341161A3F540F00A0A8C3 /* feature_data.cpp in Sources */,
34583BC91C88552100F94664 /* editable_map_object.cpp in Sources */,
675341031A3F540F00A0A8C3 /* classificator.cpp in Sources */,
+ 40009063201F5CB000963E18 /* locality_object.cpp in Sources */,
675341401A3F540F00A0A8C3 /* scales.cpp in Sources */,
6753411E1A3F540F00A0A8C3 /* feature_loader.cpp in Sources */,
675341051A3F540F00A0A8C3 /* coding_params.cpp in Sources */,