Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
239
libs/routing/cross_border_graph.hpp
Normal file
239
libs/routing/cross_border_graph.hpp
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/latlon_with_altitude.hpp"
|
||||
|
||||
#include "routing_common/num_mwm_id.hpp"
|
||||
|
||||
#include "coding/point_coding.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/varint.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "geometry/latlon.hpp"
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace routing
|
||||
{
|
||||
|
||||
using RegionSegmentId = uint32_t;
|
||||
|
||||
struct CrossBorderSegmentEnding
|
||||
{
|
||||
CrossBorderSegmentEnding() = default;
|
||||
CrossBorderSegmentEnding(m2::PointD const & point, NumMwmId const & mwmId);
|
||||
CrossBorderSegmentEnding(ms::LatLon const & point, NumMwmId const & mwmId);
|
||||
|
||||
LatLonWithAltitude m_point;
|
||||
NumMwmId m_numMwmId = std::numeric_limits<NumMwmId>::max();
|
||||
};
|
||||
|
||||
struct CrossBorderSegment
|
||||
{
|
||||
CrossBorderSegmentEnding m_start;
|
||||
CrossBorderSegmentEnding m_end;
|
||||
|
||||
double m_weight = 0.0;
|
||||
};
|
||||
|
||||
using CrossBorderSegments = std::unordered_map<RegionSegmentId, CrossBorderSegment>;
|
||||
using MwmIdToSegmentIds = std::unordered_map<NumMwmId, std::vector<RegionSegmentId>>;
|
||||
|
||||
struct CrossBorderGraph
|
||||
{
|
||||
void AddCrossBorderSegment(RegionSegmentId segId, CrossBorderSegment const & segment);
|
||||
|
||||
CrossBorderSegments m_segments;
|
||||
MwmIdToSegmentIds m_mwms;
|
||||
};
|
||||
|
||||
class CrossBorderGraphSerializer
|
||||
{
|
||||
public:
|
||||
CrossBorderGraphSerializer() = delete;
|
||||
|
||||
template <class Sink>
|
||||
static void Serialize(CrossBorderGraph const & graph, Sink & sink, std::shared_ptr<NumMwmIds> numMwmIds);
|
||||
|
||||
template <class Source>
|
||||
static void Deserialize(CrossBorderGraph & graph, Source & src, std::shared_ptr<NumMwmIds> numMwmIds);
|
||||
|
||||
private:
|
||||
static uint32_t constexpr kVersion = 1;
|
||||
static double constexpr kDouble2Int = 1.0E6;
|
||||
|
||||
struct Header
|
||||
{
|
||||
Header() = default;
|
||||
explicit Header(CrossBorderGraph const & graph, uint32_t version = kVersion);
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const;
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src);
|
||||
|
||||
uint32_t m_numRegions = 0;
|
||||
uint32_t m_numRoads = 0;
|
||||
|
||||
uint32_t m_version = kVersion;
|
||||
};
|
||||
|
||||
static size_t constexpr kBitsForDouble = 30;
|
||||
|
||||
static uint32_t Hash(std::string const & s);
|
||||
};
|
||||
|
||||
// static
|
||||
template <class Sink>
|
||||
void CrossBorderGraphSerializer::Serialize(CrossBorderGraph const & graph, Sink & sink,
|
||||
std::shared_ptr<NumMwmIds> numMwmIds)
|
||||
{
|
||||
Header header(graph);
|
||||
header.Serialize(sink);
|
||||
|
||||
std::set<uint32_t> mwmNameHashes;
|
||||
|
||||
for (auto it = graph.m_mwms.begin(); it != graph.m_mwms.end(); ++it)
|
||||
{
|
||||
auto const & mwmId = it->first;
|
||||
std::string const & mwmName = numMwmIds->GetFile(mwmId).GetName();
|
||||
auto const hash = Hash(mwmName);
|
||||
|
||||
// Triggering of this check during the maps build means that the mwm set has been changed and
|
||||
// current hash function Hash(mwmName) no longer suits it and should be replaced.
|
||||
CHECK(mwmNameHashes.emplace(hash).second, (mwmId, mwmName, hash));
|
||||
}
|
||||
|
||||
CHECK_LESS(mwmNameHashes.size(), std::numeric_limits<NumMwmId>::max(), ());
|
||||
|
||||
for (auto hash : mwmNameHashes)
|
||||
WriteToSink(sink, hash);
|
||||
|
||||
auto writeSegEnding = [&](CrossBorderSegmentEnding const & ending)
|
||||
{
|
||||
auto const & coord = ending.m_point.GetLatLon();
|
||||
WriteToSink(sink, DoubleToUint32(coord.m_lat, ms::LatLon::kMinLat, ms::LatLon::kMaxLat, kBitsForDouble));
|
||||
WriteToSink(sink, DoubleToUint32(coord.m_lon, ms::LatLon::kMinLon, ms::LatLon::kMaxLon, kBitsForDouble));
|
||||
|
||||
auto const & mwmNameHash = Hash(numMwmIds->GetFile(ending.m_numMwmId).GetName());
|
||||
auto it = mwmNameHashes.find(mwmNameHash);
|
||||
CHECK(it != mwmNameHashes.end(), (ending.m_numMwmId, mwmNameHash));
|
||||
|
||||
NumMwmId const id = std::distance(mwmNameHashes.begin(), it);
|
||||
WriteToSink(sink, id);
|
||||
};
|
||||
|
||||
for (auto const & [segId, seg] : graph.m_segments)
|
||||
{
|
||||
WriteVarUint(sink, segId);
|
||||
|
||||
WriteVarUint(sink, static_cast<uint64_t>(std::lround(seg.m_weight * kDouble2Int)));
|
||||
|
||||
writeSegEnding(seg.m_start);
|
||||
writeSegEnding(seg.m_end);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
template <class Source>
|
||||
void CrossBorderGraphSerializer::Deserialize(CrossBorderGraph & graph, Source & src,
|
||||
std::shared_ptr<NumMwmIds> numMwmIds)
|
||||
{
|
||||
Header header;
|
||||
header.Deserialize(src);
|
||||
|
||||
graph.m_mwms.reserve(header.m_numRegions);
|
||||
graph.m_segments.reserve(header.m_numRoads);
|
||||
|
||||
std::map<uint32_t, NumMwmId> hashToMwmId;
|
||||
|
||||
numMwmIds->ForEachId([&](NumMwmId id)
|
||||
{
|
||||
std::string const & region = numMwmIds->GetFile(id).GetName();
|
||||
uint32_t const mwmNameHash = Hash(region);
|
||||
// Triggering of this check in runtime means that the latest built mwm set differs from
|
||||
// the previous one ("classic" mwm set which is constant for many years). The solution is to
|
||||
// replace current hash function Hash() and rebuild World.mwm.
|
||||
CHECK(hashToMwmId.emplace(mwmNameHash, id).second, (id, region, mwmNameHash));
|
||||
});
|
||||
|
||||
std::set<uint32_t> mwmNameHashes;
|
||||
|
||||
for (size_t i = 0; i < header.m_numRegions; ++i)
|
||||
{
|
||||
auto const mwmNameHash = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
mwmNameHashes.emplace(mwmNameHash);
|
||||
}
|
||||
|
||||
auto readSegEnding = [&](CrossBorderSegmentEnding & ending)
|
||||
{
|
||||
double const lat = Uint32ToDouble(ReadPrimitiveFromSource<uint32_t>(src), ms::LatLon::kMinLat, ms::LatLon::kMaxLat,
|
||||
kBitsForDouble);
|
||||
double const lon = Uint32ToDouble(ReadPrimitiveFromSource<uint32_t>(src), ms::LatLon::kMinLon, ms::LatLon::kMaxLon,
|
||||
kBitsForDouble);
|
||||
ending.m_point = LatLonWithAltitude(ms::LatLon(lat, lon), geometry::kDefaultAltitudeMeters);
|
||||
|
||||
NumMwmId index = ReadPrimitiveFromSource<uint16_t>(src);
|
||||
CHECK_LESS(index, mwmNameHashes.size(), ());
|
||||
|
||||
auto it = mwmNameHashes.begin();
|
||||
std::advance(it, index);
|
||||
|
||||
auto const & mwmHash = *it;
|
||||
auto itHash = hashToMwmId.find(mwmHash);
|
||||
CHECK(itHash != hashToMwmId.end(), (mwmHash));
|
||||
|
||||
ending.m_numMwmId = itHash->second;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < header.m_numRoads; ++i)
|
||||
{
|
||||
CrossBorderSegment seg;
|
||||
RegionSegmentId segId;
|
||||
|
||||
if (header.m_version == 0)
|
||||
{
|
||||
segId = ReadPrimitiveFromSource<RegionSegmentId>(src);
|
||||
seg.m_weight = static_cast<double>(ReadPrimitiveFromSource<uint32_t>(src));
|
||||
}
|
||||
else
|
||||
{
|
||||
segId = ReadVarUint<RegionSegmentId>(src);
|
||||
seg.m_weight = static_cast<double>(ReadVarUint<uint64_t>(src));
|
||||
seg.m_weight /= kDouble2Int;
|
||||
}
|
||||
|
||||
readSegEnding(seg.m_start);
|
||||
readSegEnding(seg.m_end);
|
||||
|
||||
graph.AddCrossBorderSegment(segId, seg);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sink>
|
||||
void CrossBorderGraphSerializer::Header::Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, m_version);
|
||||
WriteToSink(sink, m_numRegions);
|
||||
WriteToSink(sink, m_numRoads);
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void CrossBorderGraphSerializer::Header::Deserialize(Source & src)
|
||||
{
|
||||
m_version = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
m_numRegions = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
m_numRoads = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
}
|
||||
} // namespace routing
|
||||
Loading…
Add table
Add a link
Reference in a new issue