From c942cfaa0beafafac1c312abee52e61f529fef82 Mon Sep 17 00:00:00 2001 From: Denis Koronchik Date: Thu, 18 Sep 2014 13:01:32 +0300 Subject: [PATCH] [routing] Compress node to feature id index. --- defines.hpp | 2 + generator/generator_tool/generator_tool.pro | 2 +- generator/routing_generator.cpp | 17 +- routing/osrm2feature_map.cpp | 248 ++++++++++++++++++++ routing/osrm2feature_map.hpp | 113 +++++++++ routing/osrm_data_facade_types.hpp | 242 ------------------- routing/osrm_router.cpp | 22 +- routing/osrm_router.hpp | 2 +- routing/routing.pro | 3 +- routing/routing_tests/osrm_router_test.cpp | 179 +++++++++++++- 10 files changed, 559 insertions(+), 271 deletions(-) create mode 100644 routing/osrm2feature_map.cpp create mode 100644 routing/osrm2feature_map.hpp delete mode 100644 routing/osrm_data_facade_types.hpp diff --git a/defines.hpp b/defines.hpp index ef4b9b8989..6c45396574 100644 --- a/defines.hpp +++ b/defines.hpp @@ -16,7 +16,9 @@ #define ROUTING_EDGEDATA_FILE_TAG "edgedata" #define ROUTING_EDGEID_FILE_TAG "edgeid" #define ROUTING_SHORTCUTS_FILE_TAG "shortcuts" + #define ROUTING_FTSEG_FILE_TAG "ftseg" +#define ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG "node2ftseg" #define READY_FILE_EXTENSION ".ready" #define RESUME_FILE_EXTENSION ".resume3" diff --git a/generator/generator_tool/generator_tool.pro b/generator/generator_tool/generator_tool.pro index 60b626f5b7..7a131662a2 100644 --- a/generator/generator_tool/generator_tool.pro +++ b/generator/generator_tool/generator_tool.pro @@ -1,7 +1,7 @@ # Generator binary ROOT_DIR = ../.. -DEPENDENCIES = generator storage indexer platform geometry coding base \ +DEPENDENCIES = generator routing storage indexer platform geometry coding base \ osrm gflags expat sgitess jansson protobuf tomcrypt include($$ROOT_DIR/common.pri) diff --git a/generator/routing_generator.cpp b/generator/routing_generator.cpp index 5496acdda5..b5f7f659b9 100644 --- a/generator/routing_generator.cpp +++ b/generator/routing_generator.cpp @@ -11,7 +11,7 @@ #include "../geometry/distance_on_sphere.hpp" -#include "../routing/osrm_data_facade_types.hpp" +#include "../routing/osrm2feature_map.hpp" #include "../platform/platform.hpp" @@ -50,7 +50,7 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) string nodeFileName = osrmName + ".nodeData"; - OsrmFtSegMapping mapping; + OsrmFtSegMappingBuilder mapping; ifstream input; input.open(nodeFileName); @@ -67,13 +67,13 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) return; } - uint32_t found = 0, all = 0, multiple = 0, equal = 0, moreThan1Seg = 0; + uint32_t found = 0, all = 0, multiple = 0, equal = 0, moreThan1Seg = 0, stored = 0; for (size_t nodeId = 0; nodeId < nodeData.size(); ++nodeId) { auto const & data = nodeData[nodeId]; - OsrmFtSegMapping::FtSegVectorT vec; + OsrmFtSegMappingBuilder::FtSegVectorT vec; for (auto const & seg : data.m_segments) { @@ -163,7 +163,10 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) // Emit segment. OsrmFtSegMapping::FtSeg ftSeg(fID, ind1, ind2); if (vec.empty() || !vec.back().Merge(ftSeg)) + { vec.push_back(ftSeg); + ++stored; + } continue; } @@ -190,8 +193,7 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) LOG(LINFO, ("All:", all, "Found:", found, "Not found:", all - found, "More that one segs in node:", moreThan1Seg, "Multiple:", multiple, "Equal:", equal)); - - mapping.Save(osrmName + "." + ROUTING_FTSEG_FILE_TAG); + LOG(LINFO, ("Stored:", stored)); LOG(LINFO, ("Collect all data into one file...")); @@ -199,6 +201,8 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) { FilesContainerW writer(mwmName + ROUTING_FILE_EXTENSION); + mapping.Save(writer); + auto appendFile = [&] (string const & tag) { string const fileName = osrmName + "." + tag; @@ -210,7 +214,6 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName) appendFile(ROUTING_EDGEDATA_FILE_TAG); appendFile(ROUTING_MATRIX_FILE_TAG); appendFile(ROUTING_EDGEID_FILE_TAG); - appendFile(ROUTING_FTSEG_FILE_TAG); writer.Finish(); } diff --git a/routing/osrm2feature_map.cpp b/routing/osrm2feature_map.cpp new file mode 100644 index 0000000000..05e98c97b2 --- /dev/null +++ b/routing/osrm2feature_map.cpp @@ -0,0 +1,248 @@ +#include "osrm2feature_map.hpp" + +#include "../defines.hpp" + +#include "../base/assert.hpp" +#include "../base/logging.hpp" +#include "../base/math.hpp" + +#include "../std/fstream.hpp" +#include "../std/sstream.hpp" + + +namespace routing +{ + +OsrmFtSegMapping::FtSeg::FtSeg(uint32_t fid, uint32_t ps, uint32_t pe) + : m_fid(fid), + m_pointStart(static_cast(ps)), + m_pointEnd(static_cast(pe)) +{ + CHECK_NOT_EQUAL(ps, pe, ()); + CHECK_EQUAL(m_pointStart, ps, ()); + CHECK_EQUAL(m_pointEnd, pe, ()); +} + +bool OsrmFtSegMapping::FtSeg::Merge(FtSeg const & other) +{ + if (other.m_fid != m_fid) + return false; + + bool const dir = other.m_pointEnd > other.m_pointStart; + if (dir != (m_pointEnd > m_pointStart)) + return false; + + auto const s1 = min(m_pointStart, m_pointEnd); + auto const e1 = max(m_pointStart, m_pointEnd); + auto const s2 = min(other.m_pointStart, other.m_pointEnd); + auto const e2 = max(other.m_pointStart, other.m_pointEnd); + + if (my::IsIntersect(s1, e1, s2, e2)) + { + m_pointStart = min(s1, s2); + m_pointEnd = max(e1, e2); + if (!dir) + swap(m_pointStart, m_pointEnd); + + return true; + } + else + return false; +} + +bool OsrmFtSegMapping::FtSeg::IsIntersect(FtSeg const & other) const +{ + if (other.m_fid != m_fid) + return false; + + auto const s1 = min(m_pointStart, m_pointEnd); + auto const e1 = max(m_pointStart, m_pointEnd); + auto const s2 = min(other.m_pointStart, other.m_pointEnd); + auto const e2 = max(other.m_pointStart, other.m_pointEnd); + + return my::IsIntersect(s1, e1, s2, e2); +} + +string DebugPrint(OsrmFtSegMapping::FtSeg const & seg) +{ + stringstream ss; + ss << "{ fID = " << seg.m_fid << + "; pStart = " << seg.m_pointStart << + "; pEnd = " << seg.m_pointEnd << " }"; + return ss.str(); +} + + +OsrmFtSegMapping::~OsrmFtSegMapping() +{ + if (m_handle.IsValid()) + m_handle.Unmap(); +} + +void OsrmFtSegMapping::Clear() +{ + m_offsets.clear(); + + if (m_handle.IsValid()) + m_handle.Unmap(); +} + +void OsrmFtSegMapping::Load(FilesMappingContainer & cont) +{ + Clear(); + + FilesMappingContainer::Handle h = cont.Map(ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG); + + SegOffset const * p = reinterpret_cast(h.GetData()); + + ASSERT_EQUAL(h.GetSize() % sizeof(SegOffset), 0, ()); + m_offsets.assign(p, p + h.GetSize() / sizeof(SegOffset)); + + h.Unmap(); + + m_handle = cont.Map(ROUTING_FTSEG_FILE_TAG); +} + +size_t OsrmFtSegMapping::GetSegmentsCount() const +{ + ASSERT_EQUAL(m_handle.GetSize() % sizeof(FtSeg), 0, ()); + return m_handle.GetSize() / sizeof(FtSeg); +} + +pair OsrmFtSegMapping::GetSegVector(OsrmNodeIdT nodeId) const +{ + pair const r = GetSegmentsRange(nodeId); + FtSeg const * p = GetSegments() + r.first; + return make_pair(p, p->m_fid == -1 ? 0 : r.second); +} + +void OsrmFtSegMapping::DumpSegmentsByFID(uint32_t fID) const +{ +#ifdef DEBUG + for (size_t i = 0; i < GetSegmentsCount(); ++i) + { + FtSeg const * p = GetSegments() + i; + if (p->m_fid == fID) + LOG(LDEBUG, (*p)); + } +#endif +} + +void OsrmFtSegMapping::DumpSegmentByNode(uint32_t nodeId) const +{ +#ifdef DEBUG + auto const range = GetSegVector(nodeId); + for (size_t i = 0; i < range.second; ++i) + LOG(LDEBUG, (range.first[i])); +#endif +} + +void OsrmFtSegMapping::GetOsrmNode(FtSeg const & seg, OsrmNodeIdT & forward, OsrmNodeIdT & reverse) const +{ + ASSERT_LESS(seg.m_pointStart, seg.m_pointEnd, ()); + + OsrmNodeIdT const INVALID = -1; + + forward = reverse = INVALID; + + size_t const count = GetSegmentsCount(); + for (size_t i = 0; i < count; ++i) + { + FtSeg const & s = GetSegments()[i]; + if (s.m_fid != seg.m_fid) + continue; + + if (s.m_pointStart <= s.m_pointEnd) + { + if (seg.m_pointStart >= s.m_pointStart && seg.m_pointEnd <= s.m_pointEnd) + { + ASSERT_EQUAL(forward, INVALID, ()); + forward = GetNodeId(i); + if (reverse != INVALID) + break; + } + } + else + { + if (seg.m_pointStart >= s.m_pointEnd && seg.m_pointEnd <= s.m_pointStart) + { + ASSERT_EQUAL(reverse, INVALID, ()); + reverse = GetNodeId(i); + if (forward != INVALID) + break; + } + } + } +} + +pair OsrmFtSegMapping::GetSegmentsRange(OsrmNodeIdT nodeId) const +{ + SegOffsetsT::const_iterator it = lower_bound(m_offsets.begin(), m_offsets.end(), SegOffset(nodeId, 0), + [] (SegOffset const & o, SegOffset const & val) + { + return (o.m_nodeId < val.m_nodeId); + }); + + size_t const index = distance(m_offsets.begin(), it); + size_t const start = (index > 0 ? m_offsets[index - 1].m_offset + nodeId : nodeId); + + if (index < m_offsets.size() && m_offsets[index].m_nodeId == nodeId) + return make_pair(start, m_offsets[index].m_offset + nodeId - start + 1); + else + return make_pair(start, 1); +} + +OsrmNodeIdT OsrmFtSegMapping::GetNodeId(size_t segInd) const +{ + SegOffsetsT::const_iterator it = lower_bound(m_offsets.begin(), m_offsets.end(), SegOffset(segInd, 0), + [] (SegOffset const & o, SegOffset const & val) + { + return (o.m_nodeId + o.m_offset < val.m_nodeId); + }); + + size_t const index = distance(m_offsets.begin(), it); + uint32_t const prevOffset = index > 0 ? m_offsets[index-1].m_offset : 0; + + if ((index < m_offsets.size()) && + (segInd >= prevOffset + m_offsets[index].m_nodeId) && + (segInd <= m_offsets[index].m_offset + m_offsets[index].m_nodeId)) + { + return m_offsets[index].m_nodeId; + } + + return (segInd - prevOffset); +} + +OsrmFtSegMappingBuilder::OsrmFtSegMappingBuilder() + : m_lastOffset(0) +{ +} + +void OsrmFtSegMappingBuilder::Append(OsrmNodeIdT osrmNodeId, FtSegVectorT const & data) +{ + if (data.empty()) + m_segments.push_back(FtSeg(-1, 0, 1)); + else + m_segments.insert(m_segments.end(), data.begin(), data.end()); + + if (data.size() > 1) + { + m_lastOffset += (data.size() - 1); + + uint32_t const off = static_cast(m_lastOffset); + CHECK_EQUAL(m_lastOffset, off, ()); + + m_offsets.push_back(SegOffset(osrmNodeId, off)); + } +} + +void OsrmFtSegMappingBuilder::Save(FilesContainerW & cont) const +{ + cont.GetWriter(ROUTING_FTSEG_FILE_TAG).Write( + m_segments.data(), sizeof(FtSeg) * m_segments.size()); + + cont.GetWriter(ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG).Write( + m_offsets.data(), sizeof(SegOffset) * m_offsets.size()); +} + +} diff --git a/routing/osrm2feature_map.hpp b/routing/osrm2feature_map.hpp new file mode 100644 index 0000000000..0ddf3240f6 --- /dev/null +++ b/routing/osrm2feature_map.hpp @@ -0,0 +1,113 @@ +#pragma once + +#include "../coding/file_container.hpp" + +#include "../std/string.hpp" +#include "../std/vector.hpp" +#include "../std/utility.hpp" + + +namespace routing +{ + +typedef uint32_t OsrmNodeIdT; + +class OsrmFtSegMapping +{ +public: + +#pragma pack (push, 1) + struct FtSeg + { + uint32_t m_fid; + uint16_t m_pointStart; + uint16_t m_pointEnd; + + FtSeg() + : m_fid(-1), m_pointStart(-1), m_pointEnd(-1) + { + } + + FtSeg(uint32_t fid, uint32_t ps, uint32_t pe); + + bool Merge(FtSeg const & other); + + bool operator == (FtSeg const & other) const + { + return (other.m_fid == m_fid) + && (other.m_pointEnd == m_pointEnd) + && (other.m_pointStart == m_pointStart); + } + + bool IsIntersect(FtSeg const & other) const; + + friend string DebugPrint(FtSeg const & seg); + }; + + struct SegOffset + { + OsrmNodeIdT m_nodeId; + uint32_t m_offset; + + SegOffset() + : m_nodeId(0), m_offset(0) + { + } + + SegOffset(uint32_t nodeId, uint32_t offset) + : m_nodeId(nodeId), m_offset(offset) + { + } + }; +#pragma pack (pop) + + ~OsrmFtSegMapping(); + + void Clear(); + void Load(FilesMappingContainer & cont); + + pair GetSegVector(OsrmNodeIdT nodeId) const; + void GetOsrmNode(FtSeg const & seg, OsrmNodeIdT & forward, OsrmNodeIdT & reverse) const; + + /// @name For debug purpose only. + //@{ + void DumpSegmentsByFID(uint32_t fID) const; + void DumpSegmentByNode(uint32_t nodeId) const; + //@} + + /// @name For unit test purpose only. + //@{ + pair GetSegmentsRange(uint32_t nodeId) const; + OsrmNodeIdT GetNodeId(size_t segInd) const; + + FtSeg const * GetSegments() const { return reinterpret_cast(m_handle.GetData()); } + size_t GetSegmentsCount() const; + //@} + +protected: + typedef vector SegOffsetsT; + SegOffsetsT m_offsets; + +private: + FilesMappingContainer::Handle m_handle; + +}; + + +class OsrmFtSegMappingBuilder : public OsrmFtSegMapping +{ +public: + OsrmFtSegMappingBuilder(); + + typedef vector FtSegVectorT; + + void Append(OsrmNodeIdT osrmNodeId, FtSegVectorT const & data); + void Save(FilesContainerW & cont) const; + +private: + FtSegVectorT m_segments; + + uint64_t m_lastOffset; +}; + +} diff --git a/routing/osrm_data_facade_types.hpp b/routing/osrm_data_facade_types.hpp deleted file mode 100644 index 4ed566e267..0000000000 --- a/routing/osrm_data_facade_types.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -#include "../base/assert.hpp" -#include "../base/logging.hpp" - -#include "../coding/file_container.hpp" - -#include "../std/string.hpp" -#include "../std/vector.hpp" -#include "../std/fstream.hpp" -#include "../std/unordered_map.hpp" -#include "../std/sstream.hpp" - - -namespace routing -{ - -#define SPECIAL_OSRM_NODE_ID -1 -typedef uint32_t OsrmNodeIdT; - -class OsrmFtSegMapping -{ -public: - - OsrmFtSegMapping() - { - } - -#pragma pack (push, 1) - struct FtSeg - { - uint32_t m_fid; - uint32_t m_pointStart; - uint32_t m_pointEnd; - - FtSeg() - : m_fid(-1), m_pointStart(-1), m_pointEnd(-1) - { - - } - - FtSeg(uint32_t fid, uint32_t ps, uint32_t pe) - : m_fid(fid), m_pointStart(ps), m_pointEnd(pe) - { - } - - bool Merge(FtSeg const & other) - { - if (other.m_fid != m_fid) - return false; - - if (other.m_pointEnd > other.m_pointStart) - { - if (m_pointStart >= other.m_pointEnd) - return false; - - if (other.m_pointStart == m_pointEnd) - { - m_pointEnd = other.m_pointEnd; - return true; - } - }else - { - if (m_pointEnd >= other.m_pointStart) - return false; - - if (other.m_pointEnd == m_pointStart) - { - m_pointStart = other.m_pointStart; - return true; - } - } - - return false; - } - - bool operator == (FtSeg const & other) const - { - return (other.m_fid == m_fid) - && (other.m_pointEnd == m_pointEnd) - && (other.m_pointStart == m_pointStart); - } - - bool IsIntersect(FtSeg const & other) const - { - if (other.m_fid != m_fid) - return false; - - auto s1 = min(m_pointStart, m_pointEnd); - auto e1 = max(m_pointStart, m_pointEnd); - auto s2 = min(other.m_pointStart, other.m_pointEnd); - auto e2 = max(other.m_pointStart, other.m_pointEnd); - - return (s1 >= s2 && s1 <= e2) || - (e1 <= e2 && e1 >= s2) || - (s2 >= s1 && s2 <= e1) || - (e2 <= e1 && e2 >= s1); - } - - friend string DebugPrint(FtSeg const & seg) - { - stringstream ss; - ss << "{ fID = " << seg.m_fid << - "; pStart = " << seg.m_pointStart << - "; pEnd = " << seg.m_pointEnd << " }"; - return ss.str(); - } - }; -#pragma pack (pop) - - typedef vector FtSegVectorT; - - void Save(string const & filename) - { - ofstream stream; - stream.open(filename); - - if (!stream.is_open()) - return; - - uint32_t const count = m_osrm2FtSeg.size(); - stream.write((char*)&count, sizeof(count)); - - for (uint32_t i = 0; i < count; ++i) - { - auto it = m_osrm2FtSeg.find(i); - CHECK(it != m_osrm2FtSeg.end(), ()); - FtSegVectorT const & v = it->second; - - uint32_t const vc = v.size(); - stream.write((char*)&vc, sizeof(vc)); - stream.write((char*)v.data(), sizeof(FtSeg) * vc); - } - - stream.close(); - } - - void Load(FilesMappingContainer & container) - { - FilesMappingContainer::Handle handle = container.Map(ROUTING_FTSEG_FILE_TAG); - - char const * data = handle.GetData(); - - uint32_t const count = *reinterpret_cast(data); - data += sizeof(count); - - for (uint32_t i = 0; i < count; ++i) - { - uint32_t const vc = *reinterpret_cast(data); - data += sizeof(vc); - - FtSeg const * seg = reinterpret_cast(data); - FtSegVectorT v(seg, seg + vc); - m_osrm2FtSeg[i].swap(v); - - data += sizeof(FtSeg) * vc; - } - - handle.Unmap(); - } - - void Append(OsrmNodeIdT osrmNodeId, FtSegVectorT & data) - { - ASSERT(m_osrm2FtSeg.find(osrmNodeId) == m_osrm2FtSeg.end(), ()); - m_osrm2FtSeg[osrmNodeId] = data; - } - - FtSegVectorT const & GetSegVector(OsrmNodeIdT nodeId) const - { - auto it = m_osrm2FtSeg.find(nodeId); - if (it != m_osrm2FtSeg.end()) - return it->second; - else - return m_empty; - } - - void DumpSegmentsByFID(uint32_t fID) const - { - LOG(LINFO, ("Dump segments for feature:", fID)); - - for (auto it = m_osrm2FtSeg.begin(); it != m_osrm2FtSeg.end(); ++it) - for (auto const & s : it->second) - if (s.m_fid == fID) - LOG(LINFO, (s)); - } - - void DumpSgementByNode(uint32_t nodeId) - { - LOG(LINFO, ("Dump segments for node:", nodeId)); - - auto it = m_osrm2FtSeg.find(nodeId); - if (it == m_osrm2FtSeg.end()) - return; - - for (auto const & s : it->second) - LOG(LINFO, (s)); - } - - void GetOsrmNode(FtSeg const & seg, OsrmNodeIdT & forward, OsrmNodeIdT & reverse) const - { - ASSERT_LESS(seg.m_pointStart, seg.m_pointEnd, ()); - - forward = SPECIAL_OSRM_NODE_ID; - reverse = SPECIAL_OSRM_NODE_ID; - - for (auto it = m_osrm2FtSeg.begin(); it != m_osrm2FtSeg.end(); ++it) - { - /// @todo Do break in production here when both are found. - - for (auto const & s : it->second) - { - if (s.m_fid != seg.m_fid) - continue; - - if (s.m_pointStart <= s.m_pointEnd) - { - if (seg.m_pointStart >= s.m_pointStart && seg.m_pointEnd <= s.m_pointEnd) - { - ASSERT_EQUAL(forward, SPECIAL_OSRM_NODE_ID, ()); - forward = it->first; - } - } - else - { - if (seg.m_pointStart >= s.m_pointEnd && seg.m_pointEnd <= s.m_pointStart) - { - ASSERT_EQUAL(reverse, SPECIAL_OSRM_NODE_ID, ()); - reverse = it->first; - } - } - } - } - } - -private: - unordered_map m_osrm2FtSeg; - FtSegVectorT m_empty; -}; - -} diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 37612f4afb..800c216d5f 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -65,7 +65,7 @@ public: m2::ProjectionToSection segProj; segProj.SetBounds(ft.GetPoint(i - 1), ft.GetPoint(i)); - m2::PointD pt = segProj(m_point); + m2::PointD const pt = segProj(m_point); double const d = m_point.SquareLength(pt); if (d < res.m_dist) { @@ -116,7 +116,7 @@ public: // ---------------- OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn) - : m_pIndex(index), m_countryFn(fn) + : m_countryFn(fn), m_pIndex(index) { } @@ -206,7 +206,7 @@ void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback con if (mwmIdEnd != mwmIdStart || mwmIdEnd == -1 || mwmIdStart == -1) { - resGuard.SetErrorMsg("Founded features are in different MWMs"); + resGuard.SetErrorMsg("Found features are in different MWMs"); return; } @@ -231,22 +231,22 @@ void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback con for (size_t j = 0; j < n; ++j) { PathData const & path_data = rawRoute.unpacked_path_segments[i][j]; - auto const & v = m_mapping.GetSegVector(path_data.node); + pair const range = m_mapping.GetSegVector(path_data.node); - auto correctFn = [&v] (OsrmFtSegMapping::FtSeg const & seg, size_t & ind) + auto correctFn = [&range] (OsrmFtSegMapping::FtSeg const & seg, size_t & ind) { - auto it = find_if(v.begin(), v.end(), [&] (OsrmFtSegMapping::FtSeg const & s) + auto it = find_if(range.first, range.first + range.second, [&] (OsrmFtSegMapping::FtSeg const & s) { return s.IsIntersect(seg); }); - ASSERT(it != v.end(), ()); - ind = distance(v.begin(), it); + ASSERT(it != range.first + range.second, ()); + ind = distance(range.first, it); }; - //m_mapping.DumpSgementByNode(path_data.node); + //m_mapping.DumpSegmentByNode(path_data.node); - size_t startK = 0, endK = v.size(); + size_t startK = 0, endK = range.second; if (j == 0) correctFn(segBegin, startK); else if (j == n - 1) @@ -257,7 +257,7 @@ void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback con for (size_t k = startK; k < endK; ++k) { - auto const & seg = v[k]; + auto const & seg = range.first[k]; FeatureType ft; Index::FeaturesLoaderGuard loader(*m_pIndex, mwmIdStart); diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index 00673319f4..6d0110786a 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -1,7 +1,7 @@ #pragma once #include "router.hpp" -#include "osrm_data_facade_types.hpp" +#include "osrm2feature_map.hpp" #include "../std/function.hpp" diff --git a/routing/routing.pro b/routing/routing.pro index 8172926e15..f052e24279 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -18,6 +18,7 @@ SOURCES += \ helicopter_router.cpp \ osrm_router.cpp \ osrm_online_router.cpp \ + osrm2feature_map.cpp \ road_graph_router.cpp \ dijkstra_router.cpp \ features_road_graph.cpp \ @@ -32,7 +33,7 @@ HEADERS += \ osrm_router.hpp \ osrm_online_router.hpp \ osrm_data_facade.hpp \ - osrm_data_facade_types.hpp \ + osrm2feature_map.hpp \ road_graph_router.hpp \ dijkstra_router.hpp \ features_road_graph.hpp \ diff --git a/routing/routing_tests/osrm_router_test.cpp b/routing/routing_tests/osrm_router_test.cpp index decd00d34b..4736352228 100644 --- a/routing/routing_tests/osrm_router_test.cpp +++ b/routing/routing_tests/osrm_router_test.cpp @@ -2,21 +2,184 @@ #include "../osrm_router.hpp" #include "../../indexer/mercator.hpp" +#include "../../defines.hpp" + + using namespace routing; namespace { -void Callback(Route const & r) +typedef vector InputDataT; +typedef vector< vector > NodeIdDataT; +typedef pair PR; +typedef vector RangeDataT; + + +void TestNodeId(OsrmFtSegMapping const & mapping, NodeIdDataT const & test) { - + for (OsrmNodeIdT nodeId = 0; nodeId < test.size(); ++nodeId) + { + for (auto idx : test[nodeId]) + TEST_EQUAL(nodeId, mapping.GetNodeId(idx), ()); + } } -} - -UNIT_TEST(OsrmRouter_Test) +void TestSegmentRange(OsrmFtSegMapping const & mapping, RangeDataT const & test) { - /*OsrmRouter router; - router.SetFinalPoint(m2::PointD(MercatorBounds::LonToX(27.54334), MercatorBounds::LatToY(53.899338))); // офис Немига - router.CalculateRoute(m2::PointD(MercatorBounds::LonToX(27.6704144), MercatorBounds::LatToY(53.9456243)), Callback); // Городецкая*/ + for (OsrmNodeIdT nodeId = 0; nodeId < test.size(); ++nodeId) + TEST_EQUAL(mapping.GetSegmentsRange(nodeId), test[nodeId], ()); +} + +void TestMapping(InputDataT const & data, + NodeIdDataT const & nodeIds, + RangeDataT const & ranges) +{ + OsrmFtSegMappingBuilder builder; + for (OsrmNodeIdT nodeId = 0; nodeId < data.size(); ++nodeId) + builder.Append(nodeId, data[nodeId]); + + TestNodeId(builder, nodeIds); + TestSegmentRange(builder, ranges); + + string const fName = "test1.tmp"; + { + FilesContainerW w(fName); + builder.Save(w); + } + + { + FilesMappingContainer cont(fName); + OsrmFtSegMapping mapping; + mapping.Load(cont); + + TestNodeId(mapping, nodeIds); + TestSegmentRange(mapping, ranges); + + for (size_t i = 0; i < mapping.GetSegmentsCount(); ++i) + { + OsrmNodeIdT const node = mapping.GetNodeId(i); + auto const v = mapping.GetSegVector(node); + TEST_EQUAL(v.second, data[node].size(), ()); + for (size_t j = 0; j < v.second; ++j) + TEST_EQUAL(v.first[j], data[node][j], ()); + } + } + + FileWriter::DeleteFileX(fName); +} + +} + +UNIT_TEST(OsrmFtSegMappingBuilder_Smoke) +{ + { + InputDataT data = + { + { {0, 0, 1} }, + { {1, 0, 1} }, + { {2, 0, 1}, {3, 0, 1} }, + { {4, 0, 1} }, + { {5, 0, 1}, {6, 0, 1}, {7, 0, 1} }, + { {8, 0, 1}, {9, 0, 1}, {10, 0, 1}, {11, 0, 1} }, + { {12, 0, 1} } + }; + + NodeIdDataT nodeIds = + { + { 0 }, + { 1 }, + { 2, 3 }, + { 4 }, + { 5, 6, 7 }, + { 8, 9, 10, 11 }, + { 12 } + }; + + RangeDataT ranges = + { + PR(0, 1), + PR(1, 1), + PR(2, 2), + PR(4, 1), + PR(5, 3), + PR(8, 4), + PR(12, 1) + }; + + TestMapping(data, nodeIds, ranges); + } + + + { + InputDataT data = + { + { {0, 0, 1} }, + { {1, 0, 1} }, + { {2, 0, 1} }, + { {3, 0, 1} }, + { {4, 0, 1} }, + { {5, 0, 1}, {6, 0, 1} }, + { {7, 0, 1} }, + { {8, 0, 1}, {9, 0, 1}, {10, 0, 1} }, + { {11, 0, 1}, {12, 0, 1}, {13, 0, 1} } + }; + + NodeIdDataT nodeIds = + { + { 0 }, + { 1 }, + { 2 }, + { 3 }, + { 4 }, + { 5, 6 }, + { 7 }, + { 8, 9, 10 }, + { 11, 12, 13 } + }; + + RangeDataT ranges = + { + PR(0, 1), + PR(1, 1), + PR(2, 1), + PR(3, 1), + PR(4, 1), + PR(5, 2), + PR(7, 1), + PR(8, 3), + PR(11, 3) + }; + + TestMapping(data, nodeIds, ranges); + } + + + { + InputDataT data = + { + { {0, 0, 1}, {1, 2, 3} }, + { }, + { {3, 6, 7} }, + { {4, 8, 9}, {5, 10, 11} }, + }; + + NodeIdDataT nodeIds = + { + { 0, 1 }, + { }, + { 3 }, + { 4, 5 }, + }; + + RangeDataT ranges = + { + PR(0, 2), + PR(2, 1), + PR(3, 1), + PR(4, 2), + }; + + TestMapping(data, nodeIds, ranges); + } }