mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 04:53:36 +00:00
[feature] Added RouteRelation and linked it with FeatureType.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
committed by
Konstantin Pastbin
parent
315bba2a22
commit
b85c11ea5a
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#define DATA_FILE_EXTENSION ".mwm"
|
#define DATA_FILE_EXTENSION ".mwm"
|
||||||
#define DATA_FILE_EXTENSION_TMP ".mwm.tmp"
|
#define DATA_FILE_EXTENSION_TMP ".mwm.tmp"
|
||||||
|
#define RELATIONS_FILE_EXTENSION_TMP ".rels.tmp"
|
||||||
#define DIFF_FILE_EXTENSION ".mwmdiff"
|
#define DIFF_FILE_EXTENSION ".mwmdiff"
|
||||||
#define DIFF_APPLYING_FILE_EXTENSION ".diff.applying"
|
#define DIFF_APPLYING_FILE_EXTENSION ".diff.applying"
|
||||||
#define FONT_FILE_EXTENSION ".ttf"
|
#define FONT_FILE_EXTENSION ".ttf"
|
||||||
@@ -22,8 +23,11 @@
|
|||||||
#define OFFSET_EXT ".offs"
|
#define OFFSET_EXT ".offs"
|
||||||
#define ID2REL_EXT ".id2rel"
|
#define ID2REL_EXT ".id2rel"
|
||||||
|
|
||||||
|
auto constexpr TMP_OFFSETS_EXT = OFFSET_EXT EXTENSION_TMP;
|
||||||
|
|
||||||
#define CENTERS_FILE_TAG "centers"
|
#define CENTERS_FILE_TAG "centers"
|
||||||
#define FEATURES_FILE_TAG "features"
|
#define FEATURES_FILE_TAG "features"
|
||||||
|
#define RELATIONS_FILE_TAG "relations"
|
||||||
#define GEOMETRY_FILE_TAG "geom"
|
#define GEOMETRY_FILE_TAG "geom"
|
||||||
#define TRIANGLE_FILE_TAG "trg"
|
#define TRIANGLE_FILE_TAG "trg"
|
||||||
#define INDEX_FILE_TAG "idx"
|
#define INDEX_FILE_TAG "idx"
|
||||||
@@ -36,7 +40,7 @@
|
|||||||
#define POSTCODE_POINTS_FILE_TAG "postcode_points"
|
#define POSTCODE_POINTS_FILE_TAG "postcode_points"
|
||||||
#define POSTCODES_FILE_TAG "postcodes"
|
#define POSTCODES_FILE_TAG "postcodes"
|
||||||
#define CITIES_BOUNDARIES_FILE_TAG "cities_boundaries"
|
#define CITIES_BOUNDARIES_FILE_TAG "cities_boundaries"
|
||||||
#define FEATURE_TO_OSM_FILE_TAG "feature_to_osm"
|
#define FEATURE_TO_OSM_FILE_TAG "feature_to_osm" // not used in prod
|
||||||
#define HEADER_FILE_TAG "header"
|
#define HEADER_FILE_TAG "header"
|
||||||
#define VERSION_FILE_TAG "version"
|
#define VERSION_FILE_TAG "version"
|
||||||
#define METADATA_FILE_TAG "meta"
|
#define METADATA_FILE_TAG "meta"
|
||||||
@@ -47,6 +51,7 @@
|
|||||||
#define ROUTING_FILE_TAG "routing"
|
#define ROUTING_FILE_TAG "routing"
|
||||||
#define CROSS_MWM_FILE_TAG "cross_mwm"
|
#define CROSS_MWM_FILE_TAG "cross_mwm"
|
||||||
#define FEATURE_OFFSETS_FILE_TAG "offs"
|
#define FEATURE_OFFSETS_FILE_TAG "offs"
|
||||||
|
#define RELATION_OFFSETS_FILE_TAG "rel_offs"
|
||||||
#define SEARCH_RANKS_FILE_TAG "ranks"
|
#define SEARCH_RANKS_FILE_TAG "ranks"
|
||||||
#define POPULARITY_RANKS_FILE_TAG "popularity"
|
#define POPULARITY_RANKS_FILE_TAG "popularity"
|
||||||
#define REGION_INFO_FILE_TAG "rgninfo"
|
#define REGION_INFO_FILE_TAG "rgninfo"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ bool BuildCentersTableFromDataFile(std::string const & filename, bool forceRebui
|
|||||||
if (!forceRebuild && rcont.IsExist(CENTERS_FILE_TAG))
|
if (!forceRebuild && rcont.IsExist(CENTERS_FILE_TAG))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto const table = feature::FeaturesOffsetsTable::Load(rcont);
|
auto const table = feature::FeaturesOffsetsTable::Load(rcont, FEATURE_OFFSETS_FILE_TAG);
|
||||||
if (!table)
|
if (!table)
|
||||||
{
|
{
|
||||||
LOG(LERROR, ("Can't load offsets table from:", filename));
|
LOG(LERROR, ("Can't load offsets table from:", filename));
|
||||||
@@ -32,7 +32,7 @@ bool BuildCentersTableFromDataFile(std::string const & filename, bool forceRebui
|
|||||||
}
|
}
|
||||||
|
|
||||||
feature::DataHeader const header(rcont);
|
feature::DataHeader const header(rcont);
|
||||||
FeaturesVector const features(rcont, header, table.get(), nullptr);
|
FeaturesVector const features(rcont, header, table.get(), nullptr, nullptr);
|
||||||
|
|
||||||
builder.SetGeometryParams(header.GetBounds());
|
builder.SetGeometryParams(header.GetBounds());
|
||||||
features.ForEach([&](FeatureType & ft, uint32_t featureId) { builder.Put(featureId, feature::GetCenter(ft)); });
|
features.ForEach([&](FeatureType & ft, uint32_t featureId) { builder.Put(featureId, feature::GetCenter(ft)); });
|
||||||
|
|||||||
@@ -631,7 +631,10 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
|
|||||||
CHECK(type != GeomType::Undefined, ());
|
CHECK(type != GeomType::Undefined, ());
|
||||||
if (type == GeomType::Point)
|
if (type == GeomType::Point)
|
||||||
{
|
{
|
||||||
serial::SavePoint(sink, m_center, params);
|
uint64_t const encoded =
|
||||||
|
coding::EncodePointDeltaAsUint(PointDToPointU(m_center, params.GetCoordBits()), params.GetBasePoint());
|
||||||
|
CHECK_GREATER(bits::NumHiZeroBits64(encoded), 1, ());
|
||||||
|
WriteVarUint(sink, encoded << 1); // Relations control bit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,6 +660,9 @@ void FeatureBuilder::SerializeForMwm(SupportingData & data, serial::GeometryCodi
|
|||||||
bitSink.Write(trgCount != 0 ? trgCount : data.m_trgMask, 4);
|
bitSink.Write(trgCount != 0 ? trgCount : data.m_trgMask, 4);
|
||||||
bitSink.Write(trgCount == 0 ? 1 : 0, 1);
|
bitSink.Write(trgCount == 0 ? 1 : 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relations control bit
|
||||||
|
bitSink.Write(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == GeomType::Line)
|
if (type == GeomType::Line)
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ public:
|
|||||||
|
|
||||||
void operator()(FeatureType & f, uint32_t const & id)
|
void operator()(FeatureType & f, uint32_t const & id)
|
||||||
{
|
{
|
||||||
f.ParseHeader2();
|
f.ParseAllBeforeGeometry();
|
||||||
|
|
||||||
if (!GetBicycleModel().IsRoad(feature::TypesHolder(f)))
|
if (!GetBicycleModel().IsRoad(feature::TypesHolder(f)))
|
||||||
{
|
{
|
||||||
++m_notRoadCount;
|
++m_notRoadCount;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
void operator()(FeatureType & f, uint32_t)
|
void operator()(FeatureType & f, uint32_t)
|
||||||
{
|
{
|
||||||
f.ParseHeader2();
|
f.ParseAllBeforeGeometry();
|
||||||
|
|
||||||
FeatureType::InnerGeomStat const innerStats = f.GetInnerStats();
|
FeatureType::InnerGeomStat const innerStats = f.GetInnerStats();
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ struct Color
|
|||||||
constexpr Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
|
constexpr Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
|
||||||
: Color(red << 24 | green << 16 | blue << 8 | alpha)
|
: Color(red << 24 | green << 16 | blue << 8 | alpha)
|
||||||
{}
|
{}
|
||||||
|
constexpr Color(uint8_t red, uint8_t green, uint8_t blue) : Color(red, green, blue, 255) {}
|
||||||
constexpr Color(uint32_t rgb, uint8_t alpha)
|
constexpr Color(uint32_t rgb, uint8_t alpha)
|
||||||
: Color(ExtractByte(rgb, 2), ExtractByte(rgb, 1), ExtractByte(rgb, 0), alpha)
|
: Color(ExtractByte(rgb, 2), ExtractByte(rgb, 1), ExtractByte(rgb, 0), alpha)
|
||||||
{}
|
{}
|
||||||
@@ -58,6 +59,10 @@ struct Color
|
|||||||
{
|
{
|
||||||
return {ExtractByte(argb, 2), ExtractByte(argb, 1), ExtractByte(argb, 0), ExtractByte(argb, 3)};
|
return {ExtractByte(argb, 2), ExtractByte(argb, 1), ExtractByte(argb, 0), ExtractByte(argb, 3)};
|
||||||
}
|
}
|
||||||
|
constexpr static Color FromRGBA(uint32_t rgba)
|
||||||
|
{
|
||||||
|
return {ExtractByte(rgba, 3), ExtractByte(rgba, 2), ExtractByte(rgba, 1), ExtractByte(rgba, 0)};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static uint8_t ExtractByte(uint32_t number, uint8_t byteIdx) { return (number >> (8 * byteIdx)) & 0xFF; }
|
constexpr static uint8_t ExtractByte(uint32_t number, uint8_t byteIdx) { return (number >> (8 * byteIdx)) & 0xFF; }
|
||||||
|
|||||||
@@ -103,10 +103,11 @@ set(SRC
|
|||||||
metadata_serdes.hpp
|
metadata_serdes.hpp
|
||||||
mwm_set.cpp
|
mwm_set.cpp
|
||||||
mwm_set.hpp
|
mwm_set.hpp
|
||||||
postcodes_matcher.cpp # it's in indexer due to editor which is in indexer and depends on postcodes_marcher
|
postcodes_matcher.cpp # it's in indexer EditableMapObject depends on postcodes_matcher
|
||||||
postcodes_matcher.hpp # it's in indexer due to editor which is in indexer and depends on postcodes_marcher
|
postcodes_matcher.hpp # it's in indexer EditableMapObject depends on postcodes_matcher
|
||||||
rank_table.cpp
|
rank_table.cpp
|
||||||
rank_table.hpp
|
rank_table.hpp
|
||||||
|
route_relation.hpp
|
||||||
road_shields_parser.cpp
|
road_shields_parser.cpp
|
||||||
road_shields_parser.hpp
|
road_shields_parser.hpp
|
||||||
scale_index.hpp
|
scale_index.hpp
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ std::unique_ptr<FeatureType> FeatureType::CreateFromMapObject(osm::MapObject con
|
|||||||
ft->m_parsed.m_types = true;
|
ft->m_parsed.m_types = true;
|
||||||
ft->m_header = CalculateHeader(emo.GetTypes().Size(), headerGeomType, ft->m_params);
|
ft->m_header = CalculateHeader(emo.GetTypes().Size(), headerGeomType, ft->m_params);
|
||||||
ft->m_parsed.m_header2 = true;
|
ft->m_parsed.m_header2 = true;
|
||||||
|
ft->m_parsed.m_relations = true;
|
||||||
|
|
||||||
ft->m_id = emo.GetID();
|
ft->m_id = emo.GetID();
|
||||||
return ft;
|
return ft;
|
||||||
@@ -305,7 +306,17 @@ void FeatureType::ParseCommon()
|
|||||||
|
|
||||||
if (GetGeomType() == GeomType::Point)
|
if (GetGeomType() == GeomType::Point)
|
||||||
{
|
{
|
||||||
m_center = serial::LoadPoint(source, m_loadInfo->GetDefGeometryCodingParams());
|
uint64_t decoded = ReadVarUint<uint64_t>(source);
|
||||||
|
|
||||||
|
if (m_loadInfo->m_version >= DatSectionHeader::Version::V1)
|
||||||
|
{
|
||||||
|
m_hasRelations = (decoded & 0x1) == 1;
|
||||||
|
decoded >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const & cp = m_loadInfo->GetDefGeometryCodingParams();
|
||||||
|
m_center = PointUToPointD(coding::DecodePointDeltaFromUint(decoded, cp.GetBasePoint()), cp.GetCoordBits());
|
||||||
|
|
||||||
m_limitRect.Add(m_center);
|
m_limitRect.Add(m_center);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,13 +340,7 @@ int8_t FeatureType::GetLayer()
|
|||||||
return m_params.layer;
|
return m_params.layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there is a room to store more information in Header2 (geometry header),
|
// TODO: One of the free bits could be used for a closed line flag to avoid storing identical first + last points.
|
||||||
// but it needs a mwm version change.
|
|
||||||
// 1st bit - inner / outer flag
|
|
||||||
// 4 more bits - inner points/triangles count or outer geom offsets mask
|
|
||||||
// (but actually its enough to store number of the first existing geom level only - 2 bits)
|
|
||||||
// 3-5 more bits are spare
|
|
||||||
// One of them could be used for a closed line flag to avoid storing identical first + last points.
|
|
||||||
void FeatureType::ParseHeader2()
|
void FeatureType::ParseHeader2()
|
||||||
{
|
{
|
||||||
if (m_parsed.m_header2)
|
if (m_parsed.m_header2)
|
||||||
@@ -347,7 +352,10 @@ void FeatureType::ParseHeader2()
|
|||||||
|
|
||||||
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
||||||
if (headerGeomType != HeaderGeomType::Line && headerGeomType != HeaderGeomType::Area)
|
if (headerGeomType != HeaderGeomType::Line && headerGeomType != HeaderGeomType::Area)
|
||||||
|
{
|
||||||
|
m_offsets.m_relations = m_offsets.m_header2;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BitSource bitSource(m_data.data() + m_offsets.m_header2);
|
BitSource bitSource(m_data.data() + m_offsets.m_header2);
|
||||||
uint8_t elemsCount = bitSource.Read(4);
|
uint8_t elemsCount = bitSource.Read(4);
|
||||||
@@ -362,13 +370,15 @@ void FeatureType::ParseHeader2()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_EQUAL(m_loadInfo->m_version, DatSectionHeader::Version::V1, ());
|
ASSERT(m_loadInfo->m_version >= DatSectionHeader::Version::V1, ());
|
||||||
bool const isOuter = (bitSource.Read(1) == 1);
|
bool const isOuter = (bitSource.Read(1) == 1);
|
||||||
if (isOuter)
|
if (isOuter)
|
||||||
{
|
{
|
||||||
geomScalesMask = elemsCount;
|
geomScalesMask = elemsCount;
|
||||||
elemsCount = 0;
|
elemsCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_hasRelations = (bitSource.Read(1) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayByteSource src(bitSource.RoundPtr());
|
ArrayByteSource src(bitSource.RoundPtr());
|
||||||
@@ -426,6 +436,23 @@ void FeatureType::ParseHeader2()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_offsets.m_relations = CalcOffset(src, m_data.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureType::ParseRelations()
|
||||||
|
{
|
||||||
|
if (m_parsed.m_relations)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ParseHeader2();
|
||||||
|
|
||||||
|
ArrayByteSource src(m_data.data() + m_offsets.m_relations);
|
||||||
|
|
||||||
|
if (m_hasRelations)
|
||||||
|
ReadVarUInt32SortedShortArray(src, m_relationIDs);
|
||||||
|
|
||||||
|
m_parsed.m_relations = true;
|
||||||
|
|
||||||
// Size of the whole header incl. inner geometry / triangles.
|
// Size of the whole header incl. inner geometry / triangles.
|
||||||
m_innerStats.m_size = CalcOffset(src, m_data.data());
|
m_innerStats.m_size = CalcOffset(src, m_data.data());
|
||||||
}
|
}
|
||||||
@@ -442,7 +469,7 @@ void FeatureType::ResetGeometry()
|
|||||||
if (GetGeomType() != GeomType::Point)
|
if (GetGeomType() != GeomType::Point)
|
||||||
m_limitRect = m2::RectD();
|
m_limitRect = m2::RectD();
|
||||||
|
|
||||||
m_parsed.m_header2 = m_parsed.m_points = m_parsed.m_triangles = false;
|
m_parsed.m_relations = m_parsed.m_header2 = m_parsed.m_points = m_parsed.m_triangles = false;
|
||||||
m_offsets.m_pts.clear();
|
m_offsets.m_pts.clear();
|
||||||
m_offsets.m_trg.clear();
|
m_offsets.m_trg.clear();
|
||||||
m_ptsSimpMask = 0;
|
m_ptsSimpMask = 0;
|
||||||
@@ -501,9 +528,9 @@ void FeatureType::ParseGeometry(int scale)
|
|||||||
|
|
||||||
FeatureType::GeomStat FeatureType::GetOuterGeometryStats()
|
FeatureType::GeomStat FeatureType::GetOuterGeometryStats()
|
||||||
{
|
{
|
||||||
CHECK(m_loadInfo && m_parsed.m_header2 && !m_parsed.m_points, ("Call geometry stats first and once!"));
|
CHECK(m_loadInfo && m_parsed.m_relations && !m_parsed.m_points, ());
|
||||||
size_t const scalesCount = m_loadInfo->GetScalesCount();
|
size_t const scalesCount = m_loadInfo->GetScalesCount();
|
||||||
ASSERT_LESS_OR_EQUAL(scalesCount, DataHeader::kMaxScalesCount, ("MWM has too many geometry scales!"));
|
ASSERT_LESS_OR_EQUAL(scalesCount, DataHeader::kMaxScalesCount, ());
|
||||||
FeatureType::GeomStat res;
|
FeatureType::GeomStat res;
|
||||||
|
|
||||||
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
||||||
@@ -576,10 +603,9 @@ void FeatureType::ParseTriangles(int scale)
|
|||||||
|
|
||||||
FeatureType::GeomStat FeatureType::GetOuterTrianglesStats()
|
FeatureType::GeomStat FeatureType::GetOuterTrianglesStats()
|
||||||
{
|
{
|
||||||
CHECK(m_loadInfo && m_parsed.m_header2 && !m_parsed.m_triangles, ("Call geometry stats first and once!"));
|
CHECK(m_loadInfo && m_parsed.m_relations && !m_parsed.m_triangles, ());
|
||||||
int const scalesCount = m_loadInfo->GetScalesCount();
|
int const scalesCount = m_loadInfo->GetScalesCount();
|
||||||
ASSERT_LESS_OR_EQUAL(scalesCount, static_cast<int>(DataHeader::kMaxScalesCount),
|
ASSERT_LESS_OR_EQUAL(scalesCount, static_cast<int>(DataHeader::kMaxScalesCount), ());
|
||||||
("MWM has too many geometry scales!"));
|
|
||||||
FeatureType::GeomStat res;
|
FeatureType::GeomStat res;
|
||||||
|
|
||||||
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
auto const headerGeomType = static_cast<HeaderGeomType>(Header(m_data) & HEADER_MASK_GEOMTYPE);
|
||||||
@@ -868,3 +894,16 @@ bool FeatureType::HasMetadata(feature::Metadata::EType type)
|
|||||||
|
|
||||||
return base::FindIf(m_metaIds, [&type](auto const & v) { return v.first == type; }) != m_metaIds.end();
|
return base::FindIf(m_metaIds, [&type](auto const & v) { return v.first == type; }) != m_metaIds.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FeatureType::RelationIDsV const & FeatureType::GetRelations()
|
||||||
|
{
|
||||||
|
ParseRelations();
|
||||||
|
return m_relationIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @pre id is from m_relationIDs.
|
||||||
|
feature::RouteRelationBase FeatureType::ReadRelation(uint32_t id)
|
||||||
|
{
|
||||||
|
ParseRelations();
|
||||||
|
return m_loadInfo->ReadRelation(id);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "indexer/feature_data.hpp"
|
#include "indexer/feature_data.hpp"
|
||||||
#include "indexer/metadata_serdes.hpp"
|
#include "indexer/metadata_serdes.hpp"
|
||||||
|
#include "indexer/route_relation.hpp"
|
||||||
|
|
||||||
#include "geometry/point2d.hpp"
|
#include "geometry/point2d.hpp"
|
||||||
#include "geometry/rect2d.hpp"
|
#include "geometry/rect2d.hpp"
|
||||||
@@ -82,6 +83,8 @@ public:
|
|||||||
FeatureID const & GetID() const { return m_id; }
|
FeatureID const & GetID() const { return m_id; }
|
||||||
|
|
||||||
void ParseHeader2();
|
void ParseHeader2();
|
||||||
|
void ParseRelations();
|
||||||
|
void ParseAllBeforeGeometry() { ParseRelations(); }
|
||||||
void ResetGeometry();
|
void ResetGeometry();
|
||||||
void ParseGeometry(int scale);
|
void ParseGeometry(int scale);
|
||||||
void ParseTriangles(int scale);
|
void ParseTriangles(int scale);
|
||||||
@@ -195,31 +198,41 @@ public:
|
|||||||
GeomStat GetOuterTrianglesStats();
|
GeomStat GetOuterTrianglesStats();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
using RelationIDsV = feature::ShortArray;
|
||||||
|
RelationIDsV const & GetRelations();
|
||||||
|
|
||||||
|
feature::RouteRelationBase ReadRelation(uint32_t id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ParsedFlags
|
struct ParsedFlags
|
||||||
{
|
{
|
||||||
bool m_types : 1;
|
bool m_types : 1;
|
||||||
bool m_common : 1;
|
bool m_common : 1;
|
||||||
bool m_header2 : 1;
|
bool m_header2 : 1;
|
||||||
|
bool m_relations : 1;
|
||||||
bool m_points : 1;
|
bool m_points : 1;
|
||||||
bool m_triangles : 1;
|
bool m_triangles : 1;
|
||||||
bool m_metadata : 1;
|
bool m_metadata : 1;
|
||||||
bool m_metaIds : 1;
|
bool m_metaIds : 1;
|
||||||
|
|
||||||
ParsedFlags() { Reset(); }
|
ParsedFlags() { Reset(); }
|
||||||
void Reset() { m_types = m_common = m_header2 = m_points = m_triangles = m_metadata = m_metaIds = false; }
|
void Reset()
|
||||||
|
{
|
||||||
|
m_types = m_common = m_header2 = m_relations = m_points = m_triangles = m_metadata = m_metaIds = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Offsets
|
struct Offsets
|
||||||
{
|
{
|
||||||
uint32_t m_common = 0;
|
uint32_t m_common = 0;
|
||||||
uint32_t m_header2 = 0;
|
uint32_t m_header2 = 0;
|
||||||
|
uint32_t m_relations = 0;
|
||||||
GeometryOffsets m_pts;
|
GeometryOffsets m_pts;
|
||||||
GeometryOffsets m_trg;
|
GeometryOffsets m_trg;
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
m_common = m_header2 = 0;
|
m_common = m_header2 = m_relations = 0;
|
||||||
m_pts.clear();
|
m_pts.clear();
|
||||||
m_trg.clear();
|
m_trg.clear();
|
||||||
}
|
}
|
||||||
@@ -252,6 +265,9 @@ private:
|
|||||||
Offsets m_offsets;
|
Offsets m_offsets;
|
||||||
uint32_t m_ptsSimpMask = 0;
|
uint32_t m_ptsSimpMask = 0;
|
||||||
|
|
||||||
|
RelationIDsV m_relationIDs;
|
||||||
|
bool m_hasRelations = false;
|
||||||
|
|
||||||
InnerGeomStat m_innerStats;
|
InnerGeomStat m_innerStats;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_MOVE(FeatureType);
|
DISALLOW_COPY_AND_MOVE(FeatureType);
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ FeatureSource::FeatureSource(MwmSet::MwmHandle const & handle) : m_handle(handle
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto const & value = *m_handle.GetValue();
|
auto const & value = *m_handle.GetValue();
|
||||||
m_vector = std::make_unique<FeaturesVector>(value.m_cont, value.GetHeader(), value.m_table.get(),
|
m_vector = std::make_unique<FeaturesVector>(value.m_cont, value.GetHeader(), value.m_ftTable.get(),
|
||||||
value.m_metaDeserializer.get());
|
value.m_relTable.get(), value.m_metaDeserializer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FeatureSource::GetNumFeatures() const
|
size_t FeatureSource::GetNumFeatures() const
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
#include "indexer/features_offsets_table.hpp"
|
#include "indexer/features_offsets_table.hpp"
|
||||||
|
|
||||||
#include "indexer/dat_section_header.hpp"
|
|
||||||
#include "indexer/features_vector.hpp"
|
#include "indexer/features_vector.hpp"
|
||||||
|
|
||||||
#include "platform/local_country_file.hpp"
|
|
||||||
#include "platform/local_country_file_utils.hpp"
|
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
#include "coding/files_container.hpp"
|
#include "coding/files_container.hpp"
|
||||||
@@ -14,11 +11,11 @@
|
|||||||
#include "base/logging.hpp"
|
#include "base/logging.hpp"
|
||||||
#include "base/scope_guard.hpp"
|
#include "base/scope_guard.hpp"
|
||||||
|
|
||||||
|
namespace feature
|
||||||
|
{
|
||||||
using namespace platform;
|
using namespace platform;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace feature
|
|
||||||
{
|
|
||||||
void FeaturesOffsetsTable::Builder::PushOffset(uint32_t const offset)
|
void FeaturesOffsetsTable::Builder::PushOffset(uint32_t const offset)
|
||||||
{
|
{
|
||||||
ASSERT(m_offsets.empty() || m_offsets.back() < offset, ());
|
ASSERT(m_offsets.empty() || m_offsets.back() < offset, ());
|
||||||
@@ -63,14 +60,14 @@ unique_ptr<FeaturesOffsetsTable> FeaturesOffsetsTable::Load(string const & fileP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
unique_ptr<FeaturesOffsetsTable> FeaturesOffsetsTable::Load(FilesContainerR const & cont)
|
unique_ptr<FeaturesOffsetsTable> FeaturesOffsetsTable::Load(FilesContainerR const & cont, std::string const & tag)
|
||||||
{
|
{
|
||||||
unique_ptr<FeaturesOffsetsTable> table(new FeaturesOffsetsTable());
|
unique_ptr<FeaturesOffsetsTable> table(new FeaturesOffsetsTable());
|
||||||
|
|
||||||
table->m_file.Open(cont.GetFileName());
|
table->m_file.Open(cont.GetFileName());
|
||||||
auto p = cont.GetAbsoluteOffsetAndSize(FEATURE_OFFSETS_FILE_TAG);
|
auto p = cont.GetAbsoluteOffsetAndSize(tag);
|
||||||
ASSERT(p.first % 4 == 0, (p.first)); // will get troubles in succinct otherwise
|
ASSERT(p.first % 4 == 0, (p.first)); // will get troubles in succinct otherwise
|
||||||
table->m_handle.Assign(table->m_file.Map(p.first, p.second, FEATURE_OFFSETS_FILE_TAG));
|
table->m_handle.Assign(table->m_file.Map(p.first, p.second, tag));
|
||||||
|
|
||||||
succinct::mapper::map(table->m_table, table->m_handle.GetData<char>());
|
succinct::mapper::map(table->m_table, table->m_handle.GetData<char>());
|
||||||
return table;
|
return table;
|
||||||
@@ -80,9 +77,7 @@ void FeaturesOffsetsTable::Build(FilesContainerR const & cont, string const & st
|
|||||||
{
|
{
|
||||||
Builder builder;
|
Builder builder;
|
||||||
FeaturesVector::ForEachOffset(cont, [&builder](uint32_t offset) { builder.PushOffset(offset); });
|
FeaturesVector::ForEachOffset(cont, [&builder](uint32_t offset) { builder.PushOffset(offset); });
|
||||||
|
Build(builder)->Save(storePath);
|
||||||
unique_ptr<FeaturesOffsetsTable> table(Build(builder));
|
|
||||||
table->Save(storePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeaturesOffsetsTable::Save(string const & filePath)
|
void FeaturesOffsetsTable::Save(string const & filePath)
|
||||||
@@ -123,7 +118,7 @@ bool BuildOffsetsTable(string const & filePath)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string const destPath = filePath + ".offsets";
|
string const destPath = filePath + TMP_OFFSETS_EXT;
|
||||||
SCOPE_GUARD(fileDeleter, bind(FileWriter::DeleteFileX, destPath));
|
SCOPE_GUARD(fileDeleter, bind(FileWriter::DeleteFileX, destPath));
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -140,5 +135,4 @@ bool BuildOffsetsTable(string const & filePath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace feature
|
} // namespace feature
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
/// Load table by full path to the table file.
|
/// Load table by full path to the table file.
|
||||||
static std::unique_ptr<FeaturesOffsetsTable> Load(std::string const & filePath);
|
static std::unique_ptr<FeaturesOffsetsTable> Load(std::string const & filePath);
|
||||||
|
|
||||||
static std::unique_ptr<FeaturesOffsetsTable> Load(FilesContainerR const & cont);
|
static std::unique_ptr<FeaturesOffsetsTable> Load(FilesContainerR const & cont, std::string const & tag);
|
||||||
static void Build(FilesContainerR const & cont, std::string const & storePath);
|
static void Build(FilesContainerR const & cont, std::string const & storePath);
|
||||||
|
|
||||||
FeaturesOffsetsTable(FeaturesOffsetsTable const &) = delete;
|
FeaturesOffsetsTable(FeaturesOffsetsTable const &) = delete;
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
#include "platform/constants.hpp"
|
#include "platform/constants.hpp"
|
||||||
|
|
||||||
FeaturesVector::FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header,
|
FeaturesVector::FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header,
|
||||||
feature::FeaturesOffsetsTable const * table,
|
feature::FeaturesOffsetsTable const * ftTable,
|
||||||
|
feature::FeaturesOffsetsTable const * relTable,
|
||||||
indexer::MetadataDeserializer * metaDeserializer)
|
indexer::MetadataDeserializer * metaDeserializer)
|
||||||
: m_loadInfo(cont, header, metaDeserializer)
|
: m_loadInfo(cont, header, relTable, metaDeserializer)
|
||||||
, m_table(table)
|
, m_table(ftTable)
|
||||||
{
|
{
|
||||||
InitRecordsReader();
|
InitRecordsReader();
|
||||||
}
|
}
|
||||||
@@ -44,9 +45,12 @@ FeaturesVectorTest::FeaturesVectorTest(std::string const & filePath)
|
|||||||
FeaturesVectorTest::FeaturesVectorTest(FilesContainerR const & cont)
|
FeaturesVectorTest::FeaturesVectorTest(FilesContainerR const & cont)
|
||||||
: m_cont(cont)
|
: m_cont(cont)
|
||||||
, m_header(m_cont)
|
, m_header(m_cont)
|
||||||
, m_vector(m_cont, m_header, nullptr, nullptr)
|
, m_vector(m_cont, m_header, nullptr, nullptr, nullptr)
|
||||||
{
|
{
|
||||||
m_vector.m_table = feature::FeaturesOffsetsTable::Load(m_cont).release();
|
m_vector.m_table = feature::FeaturesOffsetsTable::Load(m_cont, FEATURE_OFFSETS_FILE_TAG).release();
|
||||||
|
|
||||||
|
if (m_cont.IsExist(RELATION_OFFSETS_FILE_TAG))
|
||||||
|
m_vector.m_loadInfo.m_relTable = feature::FeaturesOffsetsTable::Load(m_cont, RELATION_OFFSETS_FILE_TAG).release();
|
||||||
|
|
||||||
if (m_cont.IsExist(METADATA_FILE_TAG))
|
if (m_cont.IsExist(METADATA_FILE_TAG))
|
||||||
m_vector.m_loadInfo.m_metaDeserializer = indexer::MetadataDeserializer::Load(m_cont).release();
|
m_vector.m_loadInfo.m_metaDeserializer = indexer::MetadataDeserializer::Load(m_cont).release();
|
||||||
@@ -56,4 +60,5 @@ FeaturesVectorTest::~FeaturesVectorTest()
|
|||||||
{
|
{
|
||||||
delete m_vector.m_table;
|
delete m_vector.m_table;
|
||||||
delete m_vector.m_loadInfo.m_metaDeserializer;
|
delete m_vector.m_loadInfo.m_metaDeserializer;
|
||||||
|
delete m_vector.m_loadInfo.m_relTable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ class FeaturesVector
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header,
|
FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header,
|
||||||
feature::FeaturesOffsetsTable const * table, indexer::MetadataDeserializer * metaDeserializer);
|
feature::FeaturesOffsetsTable const * ftTable, feature::FeaturesOffsetsTable const * relTable,
|
||||||
|
indexer::MetadataDeserializer * metaDeserializer);
|
||||||
|
|
||||||
std::unique_ptr<FeatureType> GetByIndex(uint32_t index) const;
|
std::unique_ptr<FeatureType> GetByIndex(uint32_t index) const;
|
||||||
|
|
||||||
@@ -55,7 +56,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
/// Actually, this ctor is needed only for ForEachOffset call.
|
/// Actually, this ctor is needed only for ForEachOffset call.
|
||||||
/// Didn't find a better solution without big refactoring.
|
/// Didn't find a better solution without big refactoring.
|
||||||
FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header) : m_loadInfo(cont, header, nullptr)
|
FeaturesVector(FilesContainerR const & cont, feature::DataHeader const & header)
|
||||||
|
: m_loadInfo(cont, header, nullptr, nullptr)
|
||||||
{
|
{
|
||||||
InitRecordsReader();
|
InitRecordsReader();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ UNIT_TEST(FeaturesOffsetsTable_ReadWrite)
|
|||||||
|
|
||||||
FeaturesOffsetsTable::Build(baseContainer, indexFile);
|
FeaturesOffsetsTable::Build(baseContainer, indexFile);
|
||||||
|
|
||||||
unique_ptr<FeaturesOffsetsTable> table(FeaturesOffsetsTable::Load(baseContainer));
|
unique_ptr<FeaturesOffsetsTable> table(FeaturesOffsetsTable::Load(baseContainer, FEATURE_OFFSETS_FILE_TAG));
|
||||||
TEST(table.get() && table->size() > minFeaturesCount, ());
|
TEST(table.get() && table->size() > minFeaturesCount, ());
|
||||||
|
|
||||||
unique_ptr<FeaturesOffsetsTable> loadedTable(FeaturesOffsetsTable::Load(indexFile));
|
unique_ptr<FeaturesOffsetsTable> loadedTable(FeaturesOffsetsTable::Load(indexFile));
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ UNIT_TEST(FeaturesVectorTest_ParseMetadata)
|
|||||||
TEST(handle.IsAlive(), ());
|
TEST(handle.IsAlive(), ());
|
||||||
|
|
||||||
auto const * value = handle.GetValue();
|
auto const * value = handle.GetValue();
|
||||||
FeaturesVector fv(value->m_cont, value->GetHeader(), value->m_table.get(), value->m_metaDeserializer.get());
|
FeaturesVector fv(value->m_cont, value->GetHeader(), value->m_ftTable.get(), value->m_relTable.get(),
|
||||||
|
value->m_metaDeserializer.get());
|
||||||
|
|
||||||
map<string, int> actual;
|
map<string, int> actual;
|
||||||
fv.ForEach([&](FeatureType & ft, uint32_t index)
|
fv.ForEach([&](FeatureType & ft, uint32_t index)
|
||||||
|
|||||||
@@ -394,12 +394,19 @@ MwmValue::~MwmValue() {}
|
|||||||
|
|
||||||
void MwmValue::SetTable(MwmInfoEx & info)
|
void MwmValue::SetTable(MwmInfoEx & info)
|
||||||
{
|
{
|
||||||
m_table = info.m_table.lock();
|
m_ftTable = info.m_ftTable.lock();
|
||||||
if (m_table)
|
if (!m_ftTable)
|
||||||
return;
|
{
|
||||||
|
m_ftTable = feature::FeaturesOffsetsTable::Load(m_cont, FEATURE_OFFSETS_FILE_TAG);
|
||||||
|
info.m_ftTable = m_ftTable;
|
||||||
|
}
|
||||||
|
|
||||||
m_table = feature::FeaturesOffsetsTable::Load(m_cont);
|
m_relTable = info.m_relTable.lock();
|
||||||
info.m_table = m_table;
|
if (!m_relTable && m_cont.IsExist(RELATION_OFFSETS_FILE_TAG))
|
||||||
|
{
|
||||||
|
m_relTable = feature::FeaturesOffsetsTable::Load(m_cont, RELATION_OFFSETS_FILE_TAG);
|
||||||
|
info.m_relTable = m_relTable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string DebugPrint(MwmSet::RegResult result)
|
string DebugPrint(MwmSet::RegResult result)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ private:
|
|||||||
// only in MwmValue::SetTable() method, which, in turn, is called
|
// only in MwmValue::SetTable() method, which, in turn, is called
|
||||||
// only in the MwmSet critical section, protected by a lock. So,
|
// only in the MwmSet critical section, protected by a lock. So,
|
||||||
// there's an implicit synchronization on this field.
|
// there's an implicit synchronization on this field.
|
||||||
std::weak_ptr<feature::FeaturesOffsetsTable> m_table;
|
std::weak_ptr<feature::FeaturesOffsetsTable> m_ftTable, m_relTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MwmValue;
|
class MwmValue;
|
||||||
@@ -387,7 +387,8 @@ private:
|
|||||||
feature::DataHeader m_header;
|
feature::DataHeader m_header;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<feature::FeaturesOffsetsTable> m_table;
|
// m_ftTable should always present, m_relTable maybe nullptr.
|
||||||
|
std::shared_ptr<feature::FeaturesOffsetsTable> m_ftTable, m_relTable;
|
||||||
std::unique_ptr<indexer::MetadataDeserializer> m_metaDeserializer;
|
std::unique_ptr<indexer::MetadataDeserializer> m_metaDeserializer;
|
||||||
std::unique_ptr<HouseToStreetTable> m_house2street, m_house2place;
|
std::unique_ptr<HouseToStreetTable> m_house2street, m_house2place;
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ unique_ptr<RankTable> RankTable::Load(FilesMappingContainer const & mcont, strin
|
|||||||
void SearchRankTableBuilder::CalcSearchRanks(FilesContainerR & rcont, vector<uint8_t> & ranks)
|
void SearchRankTableBuilder::CalcSearchRanks(FilesContainerR & rcont, vector<uint8_t> & ranks)
|
||||||
{
|
{
|
||||||
feature::DataHeader header(rcont);
|
feature::DataHeader header(rcont);
|
||||||
FeaturesVector featuresVector(rcont, header, nullptr, nullptr);
|
FeaturesVector featuresVector(rcont, header, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
featuresVector.ForEach([&ranks](FeatureType & ft, uint32_t /* index */) { ranks.push_back(CalcSearchRank(ft)); });
|
featuresVector.ForEach([&ranks](FeatureType & ft, uint32_t /* index */) { ranks.push_back(CalcSearchRank(ft)); });
|
||||||
}
|
}
|
||||||
|
|||||||
167
libs/indexer/route_relation.hpp
Normal file
167
libs/indexer/route_relation.hpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "coding/read_write_utils.hpp"
|
||||||
|
#include "coding/string_utf8_multilang.hpp"
|
||||||
|
|
||||||
|
#include "base/buffer_vector.hpp"
|
||||||
|
|
||||||
|
#include "drape/color.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace feature
|
||||||
|
{
|
||||||
|
|
||||||
|
class RouteRelationBase // like RelationType (FeatureType)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type : uint8_t
|
||||||
|
{
|
||||||
|
Foot = 0,
|
||||||
|
Hiking,
|
||||||
|
|
||||||
|
Bicycle,
|
||||||
|
MTB,
|
||||||
|
|
||||||
|
Bus,
|
||||||
|
Train,
|
||||||
|
Tram,
|
||||||
|
Trolleybus,
|
||||||
|
};
|
||||||
|
enum IdxAndFlags : uint8_t
|
||||||
|
{
|
||||||
|
CycleNetworkIdx = 0,
|
||||||
|
OperatorIdx = 1,
|
||||||
|
OfficialRefIdx = 2,
|
||||||
|
FromIdx = 3,
|
||||||
|
ToIdx = 4,
|
||||||
|
WikipediaIdx = 5,
|
||||||
|
CountIdx = 6,
|
||||||
|
|
||||||
|
HasColor = 0x40,
|
||||||
|
HasName = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr dp::Color kEmptyColor = dp::Color::Transparent();
|
||||||
|
|
||||||
|
void SetParam(std::string_view s, IdxAndFlags idx) { m_params[idx] = s; }
|
||||||
|
std::string_view GetParam(IdxAndFlags idx) const { return m_params[idx]; }
|
||||||
|
|
||||||
|
Type GetType() const { return m_type; }
|
||||||
|
dp::Color GetColor() const { return m_color; }
|
||||||
|
std::string const & GetRef() const { return m_ref; }
|
||||||
|
std::string const & GetNetwork() const { return m_network; }
|
||||||
|
|
||||||
|
RouteRelationBase() = default;
|
||||||
|
|
||||||
|
/// @todo Can optimize by storing color as an index in a palette (1 byte).
|
||||||
|
|
||||||
|
template <class TSink>
|
||||||
|
void Write(TSink & sink) const
|
||||||
|
{
|
||||||
|
WriteToSink(sink, uint8_t(m_type));
|
||||||
|
|
||||||
|
uint8_t flags = 0;
|
||||||
|
|
||||||
|
if (m_color != kEmptyColor)
|
||||||
|
flags |= HasColor;
|
||||||
|
if (!m_name.IsEmpty())
|
||||||
|
flags |= HasName;
|
||||||
|
|
||||||
|
for (int i = 0; i < CountIdx; ++i)
|
||||||
|
if (!m_params[i].empty())
|
||||||
|
flags |= (1 << i);
|
||||||
|
|
||||||
|
WriteToSink(sink, flags);
|
||||||
|
|
||||||
|
if (flags & HasColor)
|
||||||
|
WriteToSink(sink, m_color.GetRGBA());
|
||||||
|
|
||||||
|
if (flags & HasName)
|
||||||
|
m_name.WriteNonEmpty(sink);
|
||||||
|
|
||||||
|
rw::Write(sink, m_network);
|
||||||
|
rw::Write(sink, m_ref);
|
||||||
|
|
||||||
|
for (int i = 0; i < CountIdx; ++i)
|
||||||
|
if (!m_params[i].empty())
|
||||||
|
rw::WriteNonEmpty(sink, m_params[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TSource>
|
||||||
|
void Read(TSource & src)
|
||||||
|
{
|
||||||
|
m_type = static_cast<Type>(ReadPrimitiveFromSource<uint8_t>(src));
|
||||||
|
|
||||||
|
uint8_t const flags = ReadPrimitiveFromSource<uint8_t>(src);
|
||||||
|
|
||||||
|
if (flags & HasColor)
|
||||||
|
m_color = dp::Color::FromRGBA(ReadPrimitiveFromSource<uint32_t>(src));
|
||||||
|
|
||||||
|
if (flags & HasName)
|
||||||
|
m_name.ReadNonEmpty(src);
|
||||||
|
|
||||||
|
rw::Read(src, m_network);
|
||||||
|
rw::Read(src, m_ref);
|
||||||
|
|
||||||
|
for (int i = 0; i < CountIdx; ++i)
|
||||||
|
if (flags & (1 << i))
|
||||||
|
rw::ReadNonEmpty(src, m_params[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StringUtf8Multilang m_name;
|
||||||
|
std::string m_network, m_ref;
|
||||||
|
std::array<std::string, CountIdx> m_params;
|
||||||
|
|
||||||
|
dp::Color m_color = kEmptyColor;
|
||||||
|
Type m_type; // from route or route_master tag
|
||||||
|
|
||||||
|
friend class RelationBuilder;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ShortArray = buffer_vector<uint32_t, 2>;
|
||||||
|
|
||||||
|
class RouteRelation : public RouteRelationBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Flags : uint8_t
|
||||||
|
{
|
||||||
|
HasRelationMembers = 0x1,
|
||||||
|
HasParents = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
RouteRelation() = default;
|
||||||
|
|
||||||
|
/// @todo Use RecordReader + buffers?
|
||||||
|
template <class TSource>
|
||||||
|
void Read(TSource & src)
|
||||||
|
{
|
||||||
|
RouteRelationBase::Read(src);
|
||||||
|
|
||||||
|
uint32_t const sz = ReadVarUint<uint32_t>(src);
|
||||||
|
m_ftMembers.reserve(sz);
|
||||||
|
uint32_t prev = 0;
|
||||||
|
for (size_t i = 0; i < sz; ++i)
|
||||||
|
{
|
||||||
|
m_ftMembers.push_back(prev + ReadVarUint<uint32_t>(src));
|
||||||
|
prev = m_ftMembers.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const flags = ReadPrimitiveFromSource<uint8_t>(src);
|
||||||
|
|
||||||
|
if (flags & HasRelationMembers)
|
||||||
|
ReadVarUInt32SortedShortArray(src, m_relMembers);
|
||||||
|
|
||||||
|
if (flags & HasParents)
|
||||||
|
ReadVarUInt32SortedShortArray(src, m_relParents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint32_t> m_ftMembers;
|
||||||
|
ShortArray m_relMembers;
|
||||||
|
ShortArray m_relParents;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace feature
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
#include "indexer/shared_load_info.hpp"
|
#include "indexer/shared_load_info.hpp"
|
||||||
|
|
||||||
#include "indexer/feature_impl.hpp"
|
#include "indexer/feature_impl.hpp"
|
||||||
|
#include "indexer/features_offsets_table.hpp"
|
||||||
|
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
|
|
||||||
namespace feature
|
namespace feature
|
||||||
{
|
{
|
||||||
SharedLoadInfo::SharedLoadInfo(FilesContainerR const & cont, DataHeader const & header,
|
SharedLoadInfo::SharedLoadInfo(FilesContainerR const & cont, DataHeader const & header,
|
||||||
|
feature::FeaturesOffsetsTable const * relTable,
|
||||||
indexer::MetadataDeserializer * metaDeserializer)
|
indexer::MetadataDeserializer * metaDeserializer)
|
||||||
: m_cont(cont)
|
: m_cont(cont)
|
||||||
, m_header(header)
|
, m_header(header)
|
||||||
|
, m_relTable(relTable)
|
||||||
, m_metaDeserializer(metaDeserializer)
|
, m_metaDeserializer(metaDeserializer)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -28,4 +31,15 @@ SharedLoadInfo::Reader SharedLoadInfo::GetTrianglesReader(size_t ind) const
|
|||||||
return m_cont.GetReader(GetTagForIndex(TRIANGLE_FILE_TAG, ind));
|
return m_cont.GetReader(GetTagForIndex(TRIANGLE_FILE_TAG, ind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RouteRelationBase SharedLoadInfo::ReadRelation(uint32_t id) const
|
||||||
|
{
|
||||||
|
auto reader = m_cont.GetReader(RELATIONS_FILE_TAG);
|
||||||
|
ReaderSource src(reader);
|
||||||
|
src.Skip(m_relTable->GetFeatureOffset(id));
|
||||||
|
|
||||||
|
RouteRelationBase res;
|
||||||
|
res.Read(src);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace feature
|
} // namespace feature
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "indexer/dat_section_header.hpp"
|
#include "indexer/dat_section_header.hpp"
|
||||||
#include "indexer/data_header.hpp"
|
#include "indexer/data_header.hpp"
|
||||||
|
#include "indexer/route_relation.hpp"
|
||||||
|
|
||||||
#include "coding/files_container.hpp"
|
#include "coding/files_container.hpp"
|
||||||
#include "coding/geometry_coding.hpp"
|
#include "coding/geometry_coding.hpp"
|
||||||
@@ -15,6 +16,8 @@ class MetadataDeserializer;
|
|||||||
|
|
||||||
namespace feature
|
namespace feature
|
||||||
{
|
{
|
||||||
|
class FeaturesOffsetsTable;
|
||||||
|
|
||||||
// This info is created once per FeaturesVector.
|
// This info is created once per FeaturesVector.
|
||||||
class SharedLoadInfo
|
class SharedLoadInfo
|
||||||
{
|
{
|
||||||
@@ -22,12 +25,14 @@ public:
|
|||||||
using Reader = FilesContainerR::TReader;
|
using Reader = FilesContainerR::TReader;
|
||||||
|
|
||||||
SharedLoadInfo(FilesContainerR const & cont, DataHeader const & header,
|
SharedLoadInfo(FilesContainerR const & cont, DataHeader const & header,
|
||||||
indexer::MetadataDeserializer * metaDeserializer);
|
feature::FeaturesOffsetsTable const * relTable, indexer::MetadataDeserializer * metaDeserializer);
|
||||||
|
|
||||||
Reader GetDataReader() const;
|
Reader GetDataReader() const;
|
||||||
Reader GetGeometryReader(size_t ind) const;
|
Reader GetGeometryReader(size_t ind) const;
|
||||||
Reader GetTrianglesReader(size_t ind) const;
|
Reader GetTrianglesReader(size_t ind) const;
|
||||||
|
|
||||||
|
RouteRelationBase ReadRelation(uint32_t id) const;
|
||||||
|
|
||||||
serial::GeometryCodingParams const & GetDefGeometryCodingParams() const
|
serial::GeometryCodingParams const & GetDefGeometryCodingParams() const
|
||||||
{
|
{
|
||||||
return m_header.GetDefGeometryCodingParams();
|
return m_header.GetDefGeometryCodingParams();
|
||||||
@@ -47,6 +52,7 @@ private:
|
|||||||
DataHeader const & m_header;
|
DataHeader const & m_header;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
feature::FeaturesOffsetsTable const * m_relTable;
|
||||||
indexer::MetadataDeserializer * m_metaDeserializer;
|
indexer::MetadataDeserializer * m_metaDeserializer;
|
||||||
feature::DatSectionHeader::Version m_version;
|
feature::DatSectionHeader::Version m_version;
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ public:
|
|||||||
|
|
||||||
m_src.ForEachFeature(r, [this](FeatureType & ft)
|
m_src.ForEachFeature(r, [this](FeatureType & ft)
|
||||||
{
|
{
|
||||||
ft.ParseHeader2();
|
ft.ParseAllBeforeGeometry();
|
||||||
|
|
||||||
(void)ft.GetOuterGeometryStats();
|
(void)ft.GetOuterGeometryStats();
|
||||||
(void)ft.GetOuterTrianglesStats();
|
(void)ft.GetOuterTrianglesStats();
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void TestConcurrentAccessToFeatures(string const & mwm)
|
|||||||
auto const handle = dataSource.GetMwmHandleByCountryFile(countryFile);
|
auto const handle = dataSource.GetMwmHandleByCountryFile(countryFile);
|
||||||
TEST(handle.IsAlive(), (local));
|
TEST(handle.IsAlive(), (local));
|
||||||
|
|
||||||
auto const featureNumber = handle.GetValue()->m_table->size();
|
auto const featureNumber = handle.GetValue()->m_ftTable->size();
|
||||||
// Note. If hardware_concurrency() returns 0 it means that number of core is not defined.
|
// Note. If hardware_concurrency() returns 0 it means that number of core is not defined.
|
||||||
// If hardware_concurrency() returns 1 it means that only one core is available.
|
// If hardware_concurrency() returns 1 it means that only one core is available.
|
||||||
// In the both cases 2 threads should be used for this test.
|
// In the both cases 2 threads should be used for this test.
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ void CoverRect(m2::RectD const & rect, int scale, covering::Intervals & result)
|
|||||||
MwmContext::MwmContext(MwmSet::MwmHandle handle)
|
MwmContext::MwmContext(MwmSet::MwmHandle handle)
|
||||||
: m_handle(std::move(handle))
|
: m_handle(std::move(handle))
|
||||||
, m_value(*m_handle.GetValue())
|
, m_value(*m_handle.GetValue())
|
||||||
, m_vector(m_value.m_cont, m_value.GetHeader(), m_value.m_table.get(), m_value.m_metaDeserializer.get())
|
, m_vector(m_value.m_cont, m_value.GetHeader(), m_value.m_ftTable.get(), m_value.m_relTable.get(),
|
||||||
|
m_value.m_metaDeserializer.get())
|
||||||
, m_index(m_value.m_cont.GetReader(INDEX_FILE_TAG))
|
, m_index(m_value.m_cont.GetReader(INDEX_FILE_TAG))
|
||||||
, m_centers(m_value)
|
, m_centers(m_value)
|
||||||
, m_editableSource(m_handle)
|
, m_editableSource(m_handle)
|
||||||
|
|||||||
@@ -194,7 +194,8 @@ public:
|
|||||||
|
|
||||||
void Process(FeatureType & f, map<uint32_t, base::GeoObjectId> const & ft2osm)
|
void Process(FeatureType & f, map<uint32_t, base::GeoObjectId> const & ft2osm)
|
||||||
{
|
{
|
||||||
f.ParseHeader2();
|
f.ParseAllBeforeGeometry();
|
||||||
|
|
||||||
string const & category = GetReadableType(f);
|
string const & category = GetReadableType(f);
|
||||||
auto const & meta = f.GetMetadata();
|
auto const & meta = f.GetMetadata();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user