From 355ea19a30cc6536f33d1e5914979a5a61c54d7a Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Thu, 15 Jan 2015 14:35:17 +0300 Subject: [PATCH] First cross mwm routes --- generator/routing_generator.cpp | 60 +++- generator/routing_generator.cpp.autosave | 299 ++++++++++++++++++ generator/routing_generator.hpp | 16 + indexer/index.hpp | 13 +- routing/osrm_data_facade.hpp | 10 +- routing/osrm_router.cpp | 381 ++++++++++++++++++----- routing/osrm_router.hpp | 72 +++-- 7 files changed, 738 insertions(+), 113 deletions(-) create mode 100644 generator/routing_generator.cpp.autosave diff --git a/generator/routing_generator.cpp b/generator/routing_generator.cpp index ba8d0cf40f..d4fd906873 100644 --- a/generator/routing_generator.cpp +++ b/generator/routing_generator.cpp @@ -31,7 +31,6 @@ namespace routing static double const EQUAL_POINT_RADIUS_M = 2.0; - void BuildRoutingIndex(string const & baseDir, string const & countryName, string const & osrmFile) { classificator::Load(); @@ -46,7 +45,7 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin } vector regionBorders; - vector outgoingNodes; + OutgoingVectorT outgoingNodes; LOG(LINFO, ("Loading countries borders")); { vector tmpRegionBorders; @@ -94,8 +93,14 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin for (m2::RegionD const& border: regionBorders) { - if (border.atBorder(pts[0], 0.0001) || border.atBorder(pts[1], 0.0001)) - outgoingNodes.push_back(seg.wayId); + if (border.atBorder(pts[0], 0.001) || border.atBorder(pts[1], 0.001)) + { + outgoingNodes.push_back(nodeId); + //outgoingNodes.push_back({nodeId, pts[0].x, pts[0].y}); + //outgoingNodes.push_back(pts[0].x); //seg.wayId); + //outgoingNodes.push_back(pts[0].y); + //LOG(LINFO, ("PUSH TO OUTGOINF",pts[0].x,pts[0].y)); + } } ++all; @@ -206,7 +211,18 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin if (vec.size() > 1) ++moreThan1Seg; - +/* + if (vec.size()) + for (m2::RegionD const& border: regionBorders) + { + m2::PointD pts[2] = { { data.m_segments.front().lon1, data.m_segments.front().lat1 }, { data.m_segments.back().lon2, data.m_segments.back().lat2 } }; + if (border.atBorder(pts[0], 0.0001) || border.atBorder(pts[1], 0.0001)) + for (auto v: vec) + { + outgoingNodes.push_back(v.Store()); //nodeId); //seg.wayId); + } + } +*/ mapping.Append(nodeId, vec); } @@ -245,7 +261,14 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin appendFile(ROUTING_EDGEID_FILE_TAG); { + //LOG(LINFO, ("OUTGOING NODES DUMP")); + //for (auto n: outgoingNodes) + // LOG(LINFO, ("Node: ", n)); // Write outs information + sort(outgoingNodes.begin(), outgoingNodes.end()); + outgoingNodes.erase( + unique(outgoingNodes.begin(), outgoingNodes.end()), + outgoingNodes.end()); FileWriter w = routingCont.GetWriter(ROUTING_OUTGOING_FILE_TAG); rw::WriteVectorOfPOD(w, outgoingNodes); w.WritePadding(4); @@ -258,4 +281,31 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin LOG(LINFO, ("Nodes stored:", stored, "Routing index file size:", sz)); } + +void BuildCrossesRoutingIndex(string const & baseDir) +{ + vector outgoingNodes1; + vector outgoingNodes2; + vector result; + const string file1_path = baseDir+"Russia_central.mwm.routing"; + const string file2_path = baseDir+"Belarus.mwm.routing"; + FilesMappingContainer f1Cont(file1_path); + FilesMappingContainer f2Cont(file2_path); + ReaderSource r1(f1Cont.GetReader(ROUTING_OUTGOING_FILE_TAG)); + ReaderSource r2(f2Cont.GetReader(ROUTING_OUTGOING_FILE_TAG)); + + LOG(LINFO, ("Loading mwms")); + /*ReaderPtr r1 = f1Cont.GetReader(ROUTING_OUTGOING_FILE_TAG); + ReaderPtr r2 = f2Cont.GetReader(ROUTING_OUTGOING_FILE_TAG);*/ + rw::ReadVectorOfPOD(r1,outgoingNodes1); + rw::ReadVectorOfPOD(r2,outgoingNodes2); + + LOG(LINFO, ("Have outgoing lengthes", outgoingNodes1.size(), outgoingNodes2.size())); + sort(outgoingNodes1.begin(), outgoingNodes1.end()); + sort(outgoingNodes2.begin(), outgoingNodes2.end()); + set_intersection(outgoingNodes1.begin(),outgoingNodes1.end(),outgoingNodes2.begin(),outgoingNodes2.end(),back_inserter(result)); + LOG(LINFO, ("Have nodes after intersection", result.size())); + +} + } diff --git a/generator/routing_generator.cpp.autosave b/generator/routing_generator.cpp.autosave new file mode 100644 index 0000000000..0c25bcf71f --- /dev/null +++ b/generator/routing_generator.cpp.autosave @@ -0,0 +1,299 @@ +#include "routing_generator.hpp" +#include "gen_mwm_info.hpp" +#include "borders_generator.hpp" +#include "borders_loader.hpp" + +#include "../routing/osrm2feature_map.hpp" + +#include "../indexer/index.hpp" +#include "../indexer/classificator_loader.hpp" +#include "../indexer/feature.hpp" +#include "../indexer/ftypes_matcher.hpp" +#include "../indexer/mercator.hpp" + +#include "../coding/file_container.hpp" +#include "../coding/internal/file_data.hpp" +#include "../coding/read_write_utils.hpp" + +#include "../geometry/distance_on_sphere.hpp" + +#include "../base/logging.hpp" + +#include "../std/fstream.hpp" + +#include "../3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h" + +#define BORDERS_DIR "borders/" +#define BORDERS_EXTENSION ".borders" + +namespace routing +{ + +static double const EQUAL_POINT_RADIUS_M = 2.0; + +void BuildRoutingIndex(string const & baseDir, string const & countryName, string const & osrmFile) +{ + classificator::Load(); + + string const mwmFile = baseDir + countryName + DATA_FILE_EXTENSION; + Index index; + m2::RectD rect; + if (!index.Add(mwmFile, rect)) + { + LOG(LCRITICAL, ("MWM file not found")); + return; + } + + vector regionBorders; + OutgoingVectorT outgoingNodes; + LOG(LINFO, ("Loading countries borders")); + { + vector tmpRegionBorders; + if (osm::LoadBorders(baseDir + BORDERS_DIR + countryName + BORDERS_EXTENSION, tmpRegionBorders)) + { + LOG(LINFO, ("Found",tmpRegionBorders.size(),"region borders")); + for (m2::RegionD const& border: tmpRegionBorders) + { + m2::RegionD finalBorder; + finalBorder.Data().reserve(border.Data().size()); + for (auto p = tmpRegionBorders.data()->Begin(); pEnd(); ++p) + finalBorder.AddPoint(m2::PointD(MercatorBounds::XToLon(p->x), MercatorBounds::YToLat(p->y))); + regionBorders.push_back(finalBorder); + } + } + } + + gen::OsmID2FeatureID osm2ft; + { + FileReader reader(mwmFile + OSM2FEATURE_FILE_EXTENSION); + ReaderSource src(reader); + osm2ft.Read(src); + } + + osrm::NodeDataVectorT nodeData; + if (!osrm::LoadNodeDataFromFile(osrmFile + ".nodeData", nodeData)) + { + LOG(LCRITICAL, ("Can't load node data")); + return; + } + + OsrmFtSegMappingBuilder mapping; + + 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]; + + OsrmFtSegMappingBuilder::FtSegVectorT vec; + + for (auto const & seg : data.m_segments) + { + m2::PointD pts[2] = { { seg.lon1, seg.lat1 }, { seg.lon2, seg.lat2 } }; + + for (m2::RegionD const& border: regionBorders) + { + if (border.atBorder(pts[0], 0.001) || border.atBorder(pts[1], 0.001)) + { + outgoingNodes.push_back(nodeId); + //outgoingNodes.push_back({nodeId, pts[0].x, pts[0].y}); + //outgoingNodes.push_back(pts[0].x); //seg.wayId); + //outgoingNodes.push_back(pts[0].y); + //LOG(LINFO, ("PUSH TO OUTGOINF",pts[0].x,pts[0].y)); + } + } + + ++all; + + // now need to determine feature id and segments in it + uint32_t const fID = osm2ft.GetFeatureID(seg.wayId); + if (fID == 0) + { + LOG(LWARNING, ("No feature id for way:", seg.wayId)); + continue; + } + + FeatureType ft; + Index::FeaturesLoaderGuard loader(index, 0); + loader.GetFeature(fID, ft); + + ft.ParseGeometry(FeatureType::BEST_GEOMETRY); + + typedef pair IndexT; + vector indices[2]; + + // Match input segment points on feature points. + for (int j = 0; j < ft.GetPointsCount(); ++j) + { + double const lon = MercatorBounds::XToLon(ft.GetPoint(j).x); + double const lat = MercatorBounds::YToLat(ft.GetPoint(j).y); + for (int k = 0; k < 2; ++k) + { + double const dist = ms::DistanceOnEarth(pts[k].y, pts[k].x, lat, lon); + if (dist <= EQUAL_POINT_RADIUS_M) + indices[k].push_back(make_pair(j, dist)); + } + } + + if (!indices[0].empty() && !indices[1].empty()) + { + for (int k = 0; k < 2; ++k) + { + sort(indices[k].begin(), indices[k].end(), [] (IndexT const & r1, IndexT const & r2) + { + return (r1.second < r2.second); + }); + } + + // Show warnings for multiple or equal choices. + if (indices[0].size() != 1 && indices[1].size() != 1) + { + ++multiple; + //LOG(LWARNING, ("Multiple index choices for way:", seg.wayId, indices[0], indices[1])); + } + + { + size_t const count = min(indices[0].size(), indices[1].size()); + size_t i = 0; + for (; i < count; ++i) + if (indices[0][i].first != indices[1][i].first) + break; + + if (i == count) + { + ++equal; + LOG(LWARNING, ("Equal choices for way:", seg.wayId, indices[0], indices[1])); + } + } + + // Find best matching for multiple choices. + int ind1 = -1, ind2 = -1, dist = numeric_limits::max(); + for (auto i1 : indices[0]) + for (auto i2 : indices[1]) + { + int const d = abs(i1.first - i2.first); + if (d < dist && i1.first != i2.first) + { + ind1 = i1.first; + ind2 = i2.first; + dist = d; + } + } + + if (ind1 != -1 && ind2 != -1) + { + ++found; + + // Emit segment. + OsrmFtSegMapping::FtSeg ftSeg(fID, ind1, ind2); + if (vec.empty() || !vec.back().Merge(ftSeg)) + { + vec.push_back(ftSeg); + ++stored; + } + + continue; + } + } + + // Matching error. + LOG(LWARNING, ("!!!!! Match not found:", seg.wayId)); + LOG(LWARNING, ("(Lat, Lon):", pts[0].y, pts[0].x, "; (Lat, Lon):", pts[1].y, pts[1].x)); + for (uint32_t j = 0; j < ft.GetPointsCount(); ++j) + { + double lon = MercatorBounds::XToLon(ft.GetPoint(j).x); + double lat = MercatorBounds::YToLat(ft.GetPoint(j).y); + double const dist1 = ms::DistanceOnEarth(pts[0].y, pts[0].x, lat, lon); + double const dist2 = ms::DistanceOnEarth(pts[1].y, pts[1].x, lat, lon); + LOG(LWARNING, ("p", j, ":", lat, lon, "Dist1:", dist1, "Dist2:", dist2)); + } + } + + if (vec.size() > 1) + ++moreThan1Seg; + mapping.Append(nodeId, vec); + } + + LOG(LINFO, ("All:", all, "Found:", found, "Not found:", all - found, "More that one segs in node:", moreThan1Seg, + "Multiple:", multiple, "Equal:", equal)); + + LOG(LINFO, ("At border", outgoingNodes.size())); + + LOG(LINFO, ("Collect all data into one file...")); + string const fPath = mwmFile + ROUTING_FILE_EXTENSION; + + FilesContainerW routingCont(fPath); + + { + // Write version for routing file that is equal to correspondent mwm file. + FilesContainerR mwmCont(mwmFile); + + FileWriter w = routingCont.GetWriter(VERSION_FILE_TAG); + ReaderSource src(mwmCont.GetReader(VERSION_FILE_TAG)); + rw::ReadAndWrite(src, w); + w.WritePadding(4); + } + + mapping.Save(routingCont); + + auto appendFile = [&] (string const & tag) + { + string const fileName = osrmFile + "." + tag; + LOG(LINFO, ("Append file", fileName, "with tag", tag)); + routingCont.Write(fileName, tag); + }; + + appendFile(ROUTING_SHORTCUTS_FILE_TAG); + appendFile(ROUTING_EDGEDATA_FILE_TAG); + appendFile(ROUTING_MATRIX_FILE_TAG); + appendFile(ROUTING_EDGEID_FILE_TAG); + + { + //LOG(LINFO, ("OUTGOING NODES DUMP")); + //for (auto n: outgoingNodes) + // LOG(LINFO, ("Node: ", n)); + // Write outs information + sort(outgoingNodes.begin(), outgoingNodes.end()); + outgoingNodes.erase( + unique(outgoingNodes.begin(), outgoingNodes.end()), + outgoingNodes.end()); + FileWriter w = routingCont.GetWriter(ROUTING_OUTGOING_FILE_TAG); + rw::WriteVectorOfPOD(w, outgoingNodes); + w.WritePadding(4); + } + + routingCont.Finish(); + + uint64_t sz; + VERIFY(my::GetFileSize(fPath, sz), ()); + LOG(LINFO, ("Nodes stored:", stored, "Routing index file size:", sz)); +} + + +void BuildCrossesRoutingIndex(string const & baseDir) +{ + vector outgoingNodes1; + vector outgoingNodes2; + vector result; + const string file1_path = baseDir+"Russia_central.mwm.routing"; + const string file2_path = baseDir+"Belarus.mwm.routing"; + FilesMappingContainer f1Cont(file1_path); + FilesMappingContainer f2Cont(file2_path); + ReaderSource r1(f1Cont.GetReader(ROUTING_OUTGOING_FILE_TAG)); + ReaderSource r2(f2Cont.GetReader(ROUTING_OUTGOING_FILE_TAG)); + + LOG(LINFO, ("Loading mwms")); + /*ReaderPtr r1 = f1Cont.GetReader(ROUTING_OUTGOING_FILE_TAG); + ReaderPtr r2 = f2Cont.GetReader(ROUTING_OUTGOING_FILE_TAG);*/ + rw::ReadVectorOfPOD(r1,outgoingNodes1); + rw::ReadVectorOfPOD(r2,outgoingNodes2); + + LOG(LINFO, ("Have outgoing lengthes", outgoingNodes1.size(), outgoingNodes2.size())); + sort(outgoingNodes1.begin(), outgoingNodes1.end()); + sort(outgoingNodes2.begin(), outgoingNodes2.end()); + set_intersection(outgoingNodes1.begin(),outgoingNodes1.end(),outgoingNodes2.begin(),outgoingNodes2.end(),back_inserter(result)); + LOG(LINFO, ("Have nodes after intersection", result.size())); + +} + +} diff --git a/generator/routing_generator.hpp b/generator/routing_generator.hpp index d337866441..827fada573 100644 --- a/generator/routing_generator.hpp +++ b/generator/routing_generator.hpp @@ -3,12 +3,28 @@ #include "../std/string.hpp" #include "../std/vector.hpp" +#include "../std/set.hpp" namespace routing { + +/*! + * \brief The OutgoungNodeT struct. Contains node identifier and it's coordinate to calculate same nodes at different mwm's + */ +/*struct OutgoungNodeT { + size_t node_id; + double x; + double y; +};*/ +typedef size_t OutgoingNodeT; + +typedef std::vector OutgoingVectorT; + /// @param[in] baseDir Full path to .mwm files directory. /// @param[in] countryName Country name same with .mwm and .border file name. /// @param[in] osrmFile Full path to .osrm file (all prepared osrm files should be there). void BuildRoutingIndex(string const & baseDir, string const & countryName, string const & osrmFile); +/// @param[in] baseDir Full path to .mwm files directory. +void BuildCrossesRoutingIndex(string const & baseDir); } diff --git a/indexer/index.hpp b/indexer/index.hpp index ebec6b4545..6c4f02cbb9 100644 --- a/indexer/index.hpp +++ b/indexer/index.hpp @@ -242,18 +242,19 @@ public: void GetFeature(uint32_t offset, FeatureType & ft); }; - template - void ForEachInRectForMWM(F & f, m2::RectD const & rect, uint32_t scale, string const & name) const + MwmId getMwmIdByName(string const & name) const { - MwmId id; - { Index * p = const_cast(this); threads::MutexGuard guard(p->m_lock); UNUSED_VALUE(guard); - id = p->GetIdByName(name); - } + ASSERT(p->GetIdByName(name) != INVALID_MWM_ID, ("Can't get mwm identefier")); + return p->GetIdByName(name); + } + template + void ForEachInRectForMWM(F & f, m2::RectD const & rect, uint32_t scale, MwmId const id) const + { if (id != INVALID_MWM_ID) { MwmLock lock(*this, id); diff --git a/routing/osrm_data_facade.hpp b/routing/osrm_data_facade.hpp index be977ccc97..b16f9bd9c2 100644 --- a/routing/osrm_data_facade.hpp +++ b/routing/osrm_data_facade.hpp @@ -18,12 +18,12 @@ #include "../3party/osrm/osrm-backend/Server/DataStructures/BaseDataFacade.h" #include "../3party/osrm/osrm-backend/DataStructures/TravelMode.h" +#include "../generator/routing_generator.hpp" + namespace routing { -typedef vector NodeIdVectorT; - template class OsrmDataFacade : public BaseDataFacade { typedef BaseDataFacade super; @@ -32,7 +32,7 @@ template class OsrmDataFacade : public BaseDataFacade::max()) + if (m_mwmId == numeric_limits::max()) return; vector segments; @@ -306,7 +312,7 @@ public: // Filter income nodes by direction mode OsrmFtSegMapping::FtSeg const & node_seg = segments[idx]; FeatureType feature; - Index::FeaturesLoaderGuard loader(*m_pIndex, mwmId); + Index::FeaturesLoaderGuard loader(*m_pIndex, m_mwmId); loader.GetFeature(node_seg.m_fid, feature); feature.ParseGeometry(FeatureType::BEST_GEOMETRY); m2::PointD const featureDirection = feature.GetPoint(node_seg.m_pointEnd) - feature.GetPoint(node_seg.m_pointStart); @@ -340,25 +346,119 @@ public: } // namespace -void GenerateBorderTask(NodeIdVectorT const & borderNodes, RoutingMappingPtrT & mapping, MultiroutingTaskPointT & outgoingTask) +void OsrmRouter::GenerateBorderTask(NodeIdVectorT const & borderNodes, RoutingMappingPtrT & mapping, MultiroutingTaskPointT & outgoingTask, uint32_t mwmid) { for (auto node: borderNodes) { - FeatureGraphNodeVecT taskNode(1); - + FeatureGraphNodeVecT taskNode(2); taskNode[0].m_node.forward_node_id = node; - taskNode[0].m_node.reverse_node_id = node; + taskNode[0].m_node.reverse_node_id = INVALID_NODE_ID; + taskNode[0].m_node.forward_weight = 0; + taskNode[0].m_node.reverse_weight = 0; + taskNode[1].m_node.forward_node_id = INVALID_NODE_ID; + taskNode[1].m_node.reverse_node_id = node; + taskNode[1].m_node.forward_weight = 0; + taskNode[1].m_node.reverse_weight = 0; outgoingTask.push_back(taskNode); } + return; + FeatureGraphNodeVecT taskNode(1); + + taskNode[0].m_node.forward_node_id = 12372; + //taskNode[0].m_node.forward_offset = 659; + //taskNode[0].m_node.reverse_offset = 1; + taskNode[0].m_node.reverse_node_id = 12376; + taskNode[0].m_node.forward_weight = 0; + taskNode[0].m_node.reverse_weight = 0; + //taskNode[0].m_node.forward_travel_mode = '\0'; + //taskNode[0].m_node.backward_travel_mode = '\0'; + //taskNode[0].m_node.fwd_segment_position = 0; + //taskNode[0].m_node.name_id = 4294967295; + //taskNode[0].m_node.packed_geometry_id = 4294967295; + /*taskNode[0].m_seg.m_fid=77366; + taskNode[0].m_seg.m_pointStart=27; + taskNode[0].m_seg.m_pointEnd=28; + taskNode[0].m_segPt.x = 23.2725689; + taskNode[0].m_segPt.y = 68.5672581834;*/ + outgoingTask.push_back(taskNode); + return; + auto curD =borderNodes.cbegin(); + + while (curD!= borderNodes.cend()) + { + m2::PointD task; + task.x = MercatorBounds::LonToX(*curD); + ++curD; + task.y = MercatorBounds::LatToY(*curD); + ++curD; + FeatureGraphNodeVecT res; + ResultCode const code = FindPhantomNodes(mapping->GetName(), task, m2::PointD::Zero(), res, MAX_NODE_CANDIDATES, mapping); + if (code == NoError) + { + res.erase(++res.begin(), res.end()); + outgoingTask.push_back(res); + return; + } + } + return; + + OsrmFtSegMapping::FtSegSetT segmentSet; + vector all_nodes(borderNodes.size()); + for (int i= 0; i< borderNodes.size(); ++i) + { + OsrmFtSegMapping::FtSeg node(borderNodes[i]); + all_nodes[i] = node; + /*all_nodes[i].m_fid = node.m_fid; + all_nodes[i].m_pointStart = node.m_pointStart; + all_nodes[i].m_pointEnd = node.m_pointStart+1;*/ + LOG(LINFO, ("!!!ON",all_nodes[i].m_fid, " ", all_nodes[i].m_pointStart, " ", all_nodes[i].m_pointEnd)); + segmentSet.insert(&(all_nodes[i])); + } + + /*FeatureGraphNodeVecT taskNode(2); + + taskNode[0].m_node.forward_node_id = mapping->mapping.GetNodeId(node); + taskNode[0].m_node.forward_offset = 1; + taskNode[0].m_node.reverse_offset = 1; + taskNode[0].m_node.reverse_node_id = INVALID_NODE_ID; + taskNode[1].m_node.forward_node_id = INVALID_NODE_ID; + taskNode[1].m_node.reverse_node_id = mapping->mapping.GetNodeId(node); + outgoingTask.push_back(taskNode); + }*/ + + OsrmFtSegMapping::OsrmNodesT nodes; + volatile bool cancel=false; + mapping->mapping.GetOsrmNodes(segmentSet, nodes, cancel); + + FeatureGraphNodeVecT res; + res.clear(); + res.resize(borderNodes.size()); + + for (size_t j = 0; j < borderNodes.size(); ++j) + { + size_t const idx = j; + + if (!all_nodes[idx].IsValid()) + continue; + + auto it = nodes.find(all_nodes[idx].Store()); + if (it != nodes.end()) + { + FeatureGraphNode & node = res[idx]; + + node.m_node.forward_node_id = it->second.first; + node.m_node.reverse_node_id = it->second.second; + } + } + outgoingTask.push_back(res); } -RoutingMapping::RoutingMapping(string fName): map_counter(0), facade_counter(0), m_base_name(fName+DATA_FILE_EXTENSION) +RoutingMapping::RoutingMapping(string const & fName, Index const * pIndex): map_counter(0), facade_counter(0), m_base_name(fName+DATA_FILE_EXTENSION) { Platform & pl = GetPlatform(); - fName += DATA_FILE_EXTENSION; - string const fPath = pl.WritablePathForFile(fName + ROUTING_FILE_EXTENSION); + string const fPath = pl.WritablePathForFile(m_base_name + ROUTING_FILE_EXTENSION); if (!pl.IsFileExistsByFullPath(fPath)) throw IRouter::ResultCode::RouteFileNotExist; // Open new container and check that mwm and routing have equal timestamp. @@ -367,7 +467,7 @@ RoutingMapping::RoutingMapping(string fName): map_counter(0), facade_counter(0), { FileReader r1 = m_container.GetReader(VERSION_FILE_TAG); ReaderSrc src1(r1); - ModelReaderPtr r2 = FilesContainerR(pl.GetReader(fName)).GetReader(VERSION_FILE_TAG); + ModelReaderPtr r2 = FilesContainerR(pl.GetReader(m_base_name)).GetReader(VERSION_FILE_TAG); ReaderSrc src2(r2.GetPtr()); if (ver::ReadTimestamp(src1) != ver::ReadTimestamp(src2)) @@ -377,6 +477,8 @@ RoutingMapping::RoutingMapping(string fName): map_counter(0), facade_counter(0), } mapping.Load(m_container); } + + m_mwmId = pIndex->getMwmIdByName(m_base_name); } OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn) @@ -466,7 +568,7 @@ void OsrmRouter::CalculateRouteAsync(ReadyCallback const & callback) switch (code) { case StartPointNotFound: - LOG(LWARNING, ("Can't find start point node")); + LOG(LWARNING, ("Can't find start or end node")); break; case EndPointNotFound: LOG(LWARNING, ("Can't find end point node")); @@ -508,47 +610,83 @@ bool IsRouteExist(RawRouteData const & r) } +/* +bool OsrmRouter::FindMultipleRoutes(FeatureGraphNodeVecT const & source, FeatureGraphNodeVecT const & target, DataFacadeT & facade, + RawRouteData& outputPath, FeatureGraphNodeVecT::const_iterator & sourceEdge, FeatureGraphNodeVecT::const_iterator & targetEdge) +{ + +} +*/ + bool OsrmRouter::FindSingleRoute(FeatureGraphNodeVecT const & source, FeatureGraphNodeVecT const & target, DataFacadeT & facade, - RawRouteData& outputPath, FeatureGraphNodeVecT::const_iterator & sourceEdge, FeatureGraphNodeVecT::const_iterator & targetEdge) + RawRoutingResultT& rawRoutingResult) { SearchEngineData engineData; ShortestPathRouting pathFinder(&facade, engineData); - sourceEdge = source.cbegin(); - targetEdge = target.cbegin(); - while (sourceEdge < source.cend() && targetEdge < target.cend()) + rawRoutingResult.m_sourceEdge = source.cbegin(); + rawRoutingResult.m_targetEdge = target.cbegin(); + while (rawRoutingResult.m_sourceEdge < source.cend() && rawRoutingResult.m_targetEdge < target.cend()) { PhantomNodes nodes; - nodes.source_phantom = sourceEdge->m_node; - nodes.target_phantom = targetEdge->m_node; + nodes.source_phantom = rawRoutingResult.m_sourceEdge->m_node; + nodes.target_phantom = rawRoutingResult.m_targetEdge->m_node; - outputPath = RawRouteData(); + rawRoutingResult.m_routePath = RawRouteData(); if ((nodes.source_phantom.forward_node_id != INVALID_NODE_ID || nodes.source_phantom.reverse_node_id != INVALID_NODE_ID) && (nodes.target_phantom.forward_node_id != INVALID_NODE_ID || nodes.target_phantom.reverse_node_id != INVALID_NODE_ID)) { - outputPath.segment_end_coordinates.push_back(nodes); + rawRoutingResult.m_routePath.segment_end_coordinates.push_back(nodes); - pathFinder({nodes}, {}, outputPath); + pathFinder({nodes}, {}, rawRoutingResult.m_routePath); } /// @todo: make more complex nearest edge turnaround - if (!IsRouteExist(outputPath)) + if (!IsRouteExist(rawRoutingResult.m_routePath)) { - ++sourceEdge; - if (sourceEdge == source.cend()) + ++rawRoutingResult.m_sourceEdge; + if (rawRoutingResult.m_sourceEdge == source.cend()) { - ++targetEdge; - sourceEdge = source.cbegin(); + ++rawRoutingResult.m_targetEdge; + rawRoutingResult.m_sourceEdge = source.cbegin(); } } else return true; } - return IsRouteExist(outputPath); + return IsRouteExist(rawRoutingResult.m_routePath); +} + +m2::PointD OsrmRouter::GetPointByNodeId(const size_t node_id, RoutingMappingPtrT const & routingMapping, bool use_start) +{ + auto nSegs = routingMapping->mapping.GetSegmentsRange(node_id); + + ASSERT_GREATER(nSegs.second, 0, ()); + //LOG(LINFO, ("!!! LOL", nSegs.first, nSegs.second)); + + OsrmFtSegMapping::FtSeg seg; + if (use_start) + routingMapping->mapping.GetSegmentByIndex(nSegs.first, seg); + else + routingMapping->mapping.GetSegmentByIndex(nSegs.second - 1, seg); + + if (seg.m_fid == OsrmFtSegMapping::FtSeg::INVALID_FID) + return m2::PointD::Zero(); + + //LOG(LINFO, ("!!! СOL", seg.m_fid)); + FeatureType ft; + Index::FeaturesLoaderGuard loader(*m_pIndex, routingMapping->GetMwmId()); + loader.GetFeature(seg.m_fid, ft); + ft.ParseGeometry(FeatureType::BEST_GEOMETRY); + + if (use_start) + return ft.GetPoint(seg.m_pointStart); + else + return ft.GetPoint(seg.m_pointEnd); } OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, Route & route) @@ -557,8 +695,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt RoutingMappingPtrT finalMapping; try { - startMapping = m_indexManager.GetMappingByPoint(startPt); - finalMapping = m_indexManager.GetMappingByPoint(finalPt); + startMapping = m_indexManager.GetMappingByPoint(startPt, m_pIndex); + finalMapping = m_indexManager.GetMappingByPoint(finalPt, m_pIndex); } catch (OsrmRouter::ResultCode e) { @@ -568,11 +706,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt // 3. Find start/end nodes. MultiroutingTaskPointT startTask(1); - uint32_t startMwmId = -1, targetMwmId = -1; - { startMapping->Map(); - ResultCode const code = FindPhantomNodes(startMapping->GetName(), startPt, startDr, startTask[0], MAX_NODE_CANDIDATES, startMwmId, startMapping->mapping); + ResultCode const code = FindPhantomNodes(startMapping->GetName(), startPt, startDr, startTask[0], MAX_NODE_CANDIDATES, startMapping); if (code != NoError) return code; startMapping->Unmap(); @@ -582,7 +718,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { m_CachedTargetTask.resize(1); finalMapping->Map(); - ResultCode const code = FindPhantomNodes(finalMapping->GetName(), finalPt, m2::PointD::Zero(), m_CachedTargetTask[0], MAX_NODE_CANDIDATES, targetMwmId, finalMapping->mapping); + ResultCode const code = FindPhantomNodes(finalMapping->GetName(), finalPt, m2::PointD::Zero(), m_CachedTargetTask[0], MAX_NODE_CANDIDATES, finalMapping); if (code != NoError) return code; m_CachedTargetPoint = finalPt; @@ -593,23 +729,24 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt return Cancelled; // 4. Find route. - RawRouteData rawRoute; - FeatureGraphNodeVecT::const_iterator sourceEdge; - FeatureGraphNodeVecT::const_iterator targetEdge; + RawRoutingResultT routingResult; if (startMapping->GetName() == finalMapping->GetName()) { LOG(LINFO, ("Single mwm routing case")); startMapping->LoadFacade(); - if (!FindSingleRoute(startTask[0], m_CachedTargetTask[0], startMapping->dataFacade, rawRoute, sourceEdge, targetEdge)) + if (!FindSingleRoute(startTask[0], m_CachedTargetTask[0], startMapping->dataFacade, routingResult)) return RouteNotFound; } else { LOG(LINFO, ("Different mwm routing case")); - NodeIdVectorT borderNodes; + //NodeIdVectorT startBorderNodes; + //NodeIdVectorT finalBorderNodes; + startMapping->Map(); startMapping->LoadFacade(); finalMapping->LoadFacade(); + /* set_intersection(startMapping->dataFacade.GetOutgoingBegin(), startMapping->dataFacade.GetOutgoingEnd(), finalMapping->dataFacade.GetOutgoingBegin(), finalMapping->dataFacade.GetOutgoingEnd(), back_inserter(borderNodes)); @@ -617,11 +754,105 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { LOG(LINFO, ("There is no same outgoing nodes at mwm borders")); return PointsInDifferentMWM; + }*/ + RawRoutingResultT tmpRoutingResult; + RawRoutingResultT startRoutingResult; + RawRoutingResultT finalRoutingResult; + double finalCost = numeric_limits::max(); + + startMapping->Map(); + finalMapping->Map(); + + std::map pointCache; + for (auto sit = startMapping->dataFacade.GetOutgoingBegin(); sit!= startMapping->dataFacade.GetOutgoingEnd(); ++sit) + { + m2::PointD point1 = GetPointByNodeId(*sit, startMapping, false); + point1 = m2::PointD(MercatorBounds::XToLon(point1.x), MercatorBounds::YToLat(point1.y)); + for (auto fit = finalMapping->dataFacade.GetOutgoingBegin(); fit!= finalMapping->dataFacade.GetOutgoingEnd(); ++fit) + { + m2::PointD point2; + auto cache = pointCache.find(*fit); + if (cache == pointCache.end()) + { + point2 = GetPointByNodeId(*fit, finalMapping, true); + point2 = m2::PointD(MercatorBounds::XToLon(point2.x), MercatorBounds::YToLat(point2.y)); + pointCache.insert(std::make_pair(*fit, point2)); + } + else + point2 = cache->second; + //const m2::PointD point2 = GetPointByNodeId(*fit, finalMapping, true); + if (point1.IsAlmostZero() || point2.IsAlmostZero()) + continue; + //double const dist = ms::DistanceOnEarth(MercatorBounds::YToLat(point1.y), MercatorBounds::XToLon(point1.x), MercatorBounds::YToLat(point2.y), MercatorBounds::XToLon(point2.x)); + double const dist = ms::DistanceOnEarth((point1.y), (point1.x), (point2.y), (point2.x)); + + LOG(LINFO, ("!!!! DIST", dist," ID ", *sit)); + if (dist <= 1000.0) //TODO Make constant + { + LOG(LINFO, ("!!!! DIST", dist," ID ", *sit)); + //startBorderNodes.push_back(sit->node_id); + //finalBorderNodes.push_back(fit->node_id); + FeatureGraphNodeVecT taskNode(2); + taskNode[0].m_node.forward_node_id = *sit; + taskNode[0].m_node.reverse_node_id = INVALID_NODE_ID; + taskNode[0].m_node.forward_weight = 0; + taskNode[0].m_node.reverse_weight = 0; + taskNode[1].m_node.forward_node_id = INVALID_NODE_ID; + taskNode[1].m_node.reverse_node_id = *sit; + taskNode[1].m_node.forward_weight = 0; + taskNode[1].m_node.reverse_weight = 0; + FeatureGraphNodeVecT ftaskNode(2); + ftaskNode[0].m_node.forward_node_id = *fit; + ftaskNode[0].m_node.reverse_node_id = INVALID_NODE_ID; + ftaskNode[0].m_node.forward_weight = 0; + ftaskNode[0].m_node.reverse_weight = 0; + ftaskNode[1].m_node.forward_node_id = INVALID_NODE_ID; + ftaskNode[1].m_node.reverse_node_id = *fit; + ftaskNode[1].m_node.forward_weight = 0; + ftaskNode[1].m_node.reverse_weight = 0; + routingResult = RawRoutingResultT(); + if (FindSingleRoute(startTask[0], taskNode, startMapping->dataFacade, routingResult)) + { + LOG(LINFO, ("START FOUND")); + if (FindSingleRoute(ftaskNode, m_CachedTargetTask[0], finalMapping->dataFacade, tmpRoutingResult)) + { + LOG(LINFO, ("!!! CHECK LEN")); + const double finalLength = routingResult.m_routePath.shortest_path_length + tmpRoutingResult.m_routePath.shortest_path_length; + if(finalLength < finalCost) + { + LOG(LINFO, ("!!! FINAL OUT DIST ", dist, " COST ", finalLength)); + finalCost = finalLength; + startRoutingResult = routingResult; + finalRoutingResult = tmpRoutingResult; + } + } + } + } + } } - MultiroutingTaskPointT startBorderTask; - GenerateBorderTask(borderNodes, startMapping, startBorderTask); - if (!FindSingleRoute(startTask[0], m_CachedTargetTask[0], startMapping->dataFacade, rawRoute, sourceEdge, targetEdge)) + + if (finalCost==numeric_limits::max()) return RouteNotFound; + routingResult = startRoutingResult; + + Route::TurnsT startTurnsDir; + Route::TimesT startTimes; + vector startPoints; + turns::TurnsGeomT startTurnsGeom; + MakeTurnAnnotation(startRoutingResult, startMapping, startPoints, startTurnsDir, startTimes, startTurnsGeom); + + Route::TurnsT finalTurnsDir; + Route::TimesT finalTimes; + vector finalPoints; + turns::TurnsGeomT finalTurnsGeom; + MakeTurnAnnotation(finalRoutingResult, finalMapping, finalPoints, finalTurnsDir, finalTimes, finalTurnsGeom); + + startPoints.pop_back(); + startPoints.insert(startPoints.end(), ++finalPoints.begin(), finalPoints.end()); + route.SetGeometry(startPoints.begin(), startPoints.end()); + route.SetTurnInstructions(startTurnsDir); + route.SetSectionTimes(startTimes); + return NoError; } if (m_requestCancel) @@ -630,16 +861,15 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt // 5. Restore route. startMapping->Map(); - ASSERT(sourceEdge != startTask[0].cend(), ()); - ASSERT(targetEdge != m_CachedTargetTask[0].cend(), ()); + ASSERT(routingResult.m_sourceEdge != startTask[0].cend(), ()); + ASSERT(routingResult.m_targetEdge != m_CachedTargetTask[0].cend(), ()); - typedef OsrmFtSegMapping::FtSeg SegT; Route::TurnsT turnsDir; Route::TimesT times; vector points; turns::TurnsGeomT turnsGeom; - MakeTurnAnnotation(rawRoute, startMwmId, startMapping, points, turnsDir, times, sourceEdge, targetEdge, turnsGeom); + MakeTurnAnnotation(routingResult, startMapping, points, turnsDir, times, turnsGeom); route.SetGeometry(points.begin(), points.end()); route.SetTurnInstructions(turnsDir); @@ -675,45 +905,44 @@ m2::PointD OsrmRouter::GetPointForTurnAngle(OsrmFtSegMapping::FtSeg const &seg, return nextPnt; } - -OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRouteData const & rawRoute, uint32_t const mwmId, RoutingMappingPtrT const & mapping, vector & points, Route::TurnsT & turnsDir,Route::TimesT & times, FeatureGraphNodeVecT::const_iterator & sourceEdge, FeatureGraphNodeVecT::const_iterator & targetEdge, turns::TurnsGeomT & turnsGeom) +OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRoutingResultT const & routingResult, RoutingMappingPtrT const & mapping, vector & points, Route::TurnsT & turnsDir,Route::TimesT & times, turns::TurnsGeomT & turnsGeom) { typedef OsrmFtSegMapping::FtSeg SegT; - SegT const & segBegin = sourceEdge->m_seg; - SegT const & segEnd = targetEdge->m_seg; + //SegT const & segBegin = sourceEdge->m_seg; + //SegT const & segEnd = targetEdge->m_seg; - ASSERT(segBegin.IsValid(), ()); - ASSERT(segEnd.IsValid(), ()); + //ASSERT(segBegin.IsValid(), ()); + //ASSERT(segEnd.IsValid(), ()); double estimateTime = 0; - LOG(LDEBUG, ("Length:", rawRoute.shortest_path_length)); + LOG(LDEBUG, ("Length:", routingResult.m_routePath.shortest_path_length)); //! @todo: Improve last segment time calculation CarModel carModel; #ifdef _DEBUG size_t lastIdx = 0; #endif - for (auto i : osrm::irange(0, rawRoute.unpacked_path_segments.size())) + for (auto i : osrm::irange(0, routingResult.m_routePath.unpacked_path_segments.size())) { if (m_requestCancel) return Cancelled; // Get all the coordinates for the computed route - size_t const n = rawRoute.unpacked_path_segments[i].size(); + size_t const n = routingResult.m_routePath.unpacked_path_segments[i].size(); for (size_t j = 0; j < n; ++j) { - PathData const & path_data = rawRoute.unpacked_path_segments[i][j]; + PathData const & path_data = routingResult.m_routePath.unpacked_path_segments[i][j]; if (j > 0) { Route::TurnItem t; t.m_index = points.size() - 1; - GetTurnDirection(rawRoute.unpacked_path_segments[i][j - 1], - rawRoute.unpacked_path_segments[i][j], + /*GetTurnDirection(routingResult.m_routePath.unpacked_path_segments[i][j - 1], + routingResult.m_routePath.unpacked_path_segments[i][j], mwmId, mapping, t); if (t.m_turn != turns::NoTurn) - turnsDir.push_back(t); + turnsDir.push_back(t);*/ // osrm multiple seconds to 10, so we need to divide it back @@ -746,20 +975,20 @@ OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRouteData const & rawRo //m_mapping.DumpSegmentByNode(path_data.node); size_t startK = 0, endK = buffer.size(); - if (j == 0) + /*if (j == 0) correctFn(segBegin, startK); if (j == n - 1) { correctFn(segEnd, endK); ++endK; - } + }*/ for (size_t k = startK; k < endK; ++k) { SegT const & seg = buffer[k]; FeatureType ft; - Index::FeaturesLoaderGuard loader(*m_pIndex, mwmId); + Index::FeaturesLoaderGuard loader(*m_pIndex, mapping->GetMwmId()); loader.GetFeature(seg.m_fid, ft); ft.ParseGeometry(FeatureType::BEST_GEOMETRY); @@ -767,10 +996,10 @@ OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRouteData const & rawRo auto endIdx = seg.m_pointEnd; bool const needTime = (j == 0) || (j == n - 1); - if (j == 0 && k == startK) + /*if (j == 0 && k == startK) startIdx = (seg.m_pointEnd > seg.m_pointStart) ? segBegin.m_pointStart : segBegin.m_pointEnd; if (j == n - 1 && k == endK - 1) - endIdx = (seg.m_pointEnd > seg.m_pointStart) ? segEnd.m_pointEnd : segEnd.m_pointStart; + endIdx = (seg.m_pointEnd > seg.m_pointStart) ? segEnd.m_pointEnd : segEnd.m_pointStart;*/ if (seg.m_pointEnd > seg.m_pointStart) { @@ -795,8 +1024,8 @@ OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRouteData const & rawRo } } - points.front() = sourceEdge->m_segPt; - points.back() = targetEdge->m_segPt; + points.front() = routingResult.m_sourceEdge->m_segPt; + points.back() = routingResult.m_targetEdge->m_segPt; if (points.size() < 2) return RouteNotFound; @@ -930,11 +1159,11 @@ void OsrmRouter::GetPossibleTurns(NodeID node, } void OsrmRouter::GetTurnGeometry(m2::PointD const & p, m2::PointD const & p1, - OsrmRouter::GeomTurnCandidateT & candidates, string const & fName) const + OsrmRouter::GeomTurnCandidateT & candidates, RoutingMappingPtrT const & mapping) const { Point2Geometry getter(p, p1, candidates); m_pIndex->ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(p, FEATURES_NEAR_TURN_M), - scales::GetUpperScale(), fName); + scales::GetUpperScale(), mapping->GetMwmId()); } turns::TurnDirection OsrmRouter::InvertDirection(turns::TurnDirection dir) const @@ -1017,7 +1246,7 @@ turns::TurnDirection OsrmRouter::IntermediateDirection(const double angle) const } bool OsrmRouter::KeepOnewayOutgoingTurnIncomingEdges(TurnCandidatesT const & nodes, Route::TurnItem const & turn, - m2::PointD const & p, m2::PointD const & p1OneSeg, string const & fName) const + m2::PointD const & p, m2::PointD const & p1OneSeg, RoutingMappingPtrT const & mapping) const { size_t const outgoingNotesCount = 1; if (turns::IsGoStraightOrSlightTurn(turn.m_turn)) @@ -1025,7 +1254,7 @@ bool OsrmRouter::KeepOnewayOutgoingTurnIncomingEdges(TurnCandidatesT const & nod else { GeomTurnCandidateT geoNodes; - GetTurnGeometry(p, p1OneSeg, geoNodes, fName); + GetTurnGeometry(p, p1OneSeg, geoNodes, mapping); if (geoNodes.size() <= outgoingNotesCount) return false; return true; @@ -1102,7 +1331,7 @@ void OsrmRouter::GetTurnDirection(PathData const & node1, #ifdef _DEBUG GeomTurnCandidateT geoNodes; - GetTurnGeometry(p, p1OneSeg, geoNodes, routingMapping->GetName()); + GetTurnGeometry(p, p1OneSeg, geoNodes, routingMapping); m2::PointD const p2OneSeg = ft2.GetPoint(seg2.m_pointStart < seg2.m_pointEnd ? seg2.m_pointStart + 1 : seg2.m_pointStart - 1); @@ -1135,7 +1364,7 @@ void OsrmRouter::GetTurnDirection(PathData const & node1, bool const isRound2 = ftypes::IsRoundAboutChecker::Instance()(ft2); if (!hasMultiTurns - && !KeepOnewayOutgoingTurnIncomingEdges(nodes, turn, p, p1OneSeg, routingMapping->GetName()) + && !KeepOnewayOutgoingTurnIncomingEdges(nodes, turn, p, p1OneSeg, routingMapping) && !KeepOnewayOutgoingTurnRoundabout(isRound1, isRound2)) { turn.m_turn = turns::NoTurn; @@ -1266,19 +1495,19 @@ void OsrmRouter::FixupTurns(vector const & points, Route::TurnsT & t } IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fName, m2::PointD const & point, m2::PointD const & direction, - FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId, OsrmFtSegMapping const & mapping) + FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping) { - Point2PhantomNode getter(mapping, m_pIndex, direction); + Point2PhantomNode getter(mapping->mapping, m_pIndex, direction); getter.SetPoint(point); m_pIndex->ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(point, FEATURE_BY_POINT_RADIUS_M), - scales::GetUpperScale(), fName); + scales::GetUpperScale(), mapping->GetMwmId()); if (!getter.HasCandidates()) return StartPointNotFound; - getter.MakeResult(res, maxCount, mwmId, m_requestCancel); + getter.MakeResult(res, maxCount, m_requestCancel); return NoError; } diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index 0486ab7805..0c12b2f71d 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -5,6 +5,7 @@ #include "osrm2feature_map.hpp" #include "osrm_data_facade.hpp" +#include "../indexer/index.hpp" #include "../base/mutex.hpp" #include "../std/function.hpp" @@ -14,12 +15,10 @@ namespace feature { class TypesHolder; } -class Index; struct PhantomNode; struct PathData; class FeatureType; -class RawRouteData; - +struct RawRouteData; namespace routing { @@ -38,6 +37,15 @@ typedef vector FeatureGraphNodeVecT; /// Points vector to calculate several routes typedef vector MultiroutingTaskPointT; +/*! + * \brief The OSRM routing result struct. Contains raw routing result and iterators to source and target edges. + * \property routePath: result path data + * \property sourceEdge: iterator to src edge from source vector + * \property targetEdge: iterator to target edge from target vector + */ +struct RawRoutingResultT; + +typedef vector MultipleRoutingResultT; ///Datamapping and facade for single MWM and MWM.routing file @@ -47,7 +55,7 @@ struct RoutingMapping OsrmFtSegMapping mapping; ///@param fName: mwm file path - RoutingMapping(string fName); + RoutingMapping(string const & fName, Index const * pIndex); ~RoutingMapping() { @@ -87,11 +95,14 @@ struct RoutingMapping string GetName() {return m_base_name;} + Index::MwmId GetMwmId() {return m_mwmId;} + private: size_t map_counter; size_t facade_counter; string m_base_name; FilesMappingContainer m_container; + Index::MwmId m_mwmId; }; typedef shared_ptr RoutingMappingPtrT; @@ -108,7 +119,7 @@ class RoutingIndexManager public: RoutingIndexManager(CountryFileFnT const & fn): m_countryFn(fn) {} - RoutingMappingPtrT GetMappingByPoint(m2::PointD point) + RoutingMappingPtrT GetMappingByPoint(m2::PointD point, Index const * pIndex) { string fName = m_countryFn(point); //Check if we have already load this file @@ -116,7 +127,7 @@ public: if (mapIter != m_mapping.end()) return mapIter->second; //Or load and check file - RoutingMappingPtrT new_mapping = RoutingMappingPtrT(new RoutingMapping(fName)); + RoutingMappingPtrT new_mapping = RoutingMappingPtrT(new RoutingMapping(fName, pIndex)); m_mapping.insert(std::make_pair(fName, new_mapping)); return new_mapping; @@ -146,6 +157,8 @@ public: }; typedef vector TurnCandidatesT; + typedef vector NodeIdVectorT; + typedef vector GeomTurnCandidateT; OsrmRouter(Index const * index, CountryFileFnT const & fn); @@ -156,29 +169,46 @@ public: virtual void CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback, m2::PointD const & direction = m2::PointD::Zero()); protected: - IRouter::ResultCode FindPhantomNodes(string const & fName, m2::PointD const & point, const m2::PointD &direction, - FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId, OsrmFtSegMapping const & mapping); + IRouter::ResultCode FindPhantomNodes(string const & fName, m2::PointD const & point, m2::PointD const & direction, + FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping); + + /*! + * \brief GetPointByNodeId finds geographical points for outgoing nodes to test linkage + * \param node_id + * \param routingMapping + * \param use_start + * \return point coordinates + */ + m2::PointD GetPointByNodeId(const size_t node_id, RoutingMappingPtrT const & routingMapping, bool use_start=true); /*! Find single shortest path in single MWM between 2 sets of edges - * @param source: vector of source edgest to make path - * @param taget: vector of target edges to make path - * @param facade: OSRM routing data facade to recover graph information - * @param outputPath: result path data - * @param sourceEdge: iterator to src edge from source vector - * @param sourceEdge: iterator to target edge from target vector - * @return true if path exists. False otherwise + * \param source: vector of source edgest to make path + * \param taget: vector of target edges to make path + * \param facade: OSRM routing data facade to recover graph information + * \param rawRoutingResult: routing result store + * \return true if path exists. False otherwise */ bool FindSingleRoute(FeatureGraphNodeVecT const & source, FeatureGraphNodeVecT const & target, DataFacadeT & facade, - RawRouteData& outputPath, - FeatureGraphNodeVecT::const_iterator & sourceEdge, - FeatureGraphNodeVecT::const_iterator & targetEdge); + RawRoutingResultT& rawRoutingResult); - ResultCode MakeTurnAnnotation(RawRouteData const & rawRoute, uint32_t const mwmId, RoutingMappingPtrT const & mapping, vector & points, Route::TurnsT & turnsDir, Route::TimesT & times, FeatureGraphNodeVecT::const_iterator & sourceEdge, FeatureGraphNodeVecT::const_iterator & targetEdge, turns::TurnsGeomT &turnsGeom); + /*! + * \brief Compute turn and time estimation structs for OSRM raw route. + * \param routingResult OSRM routing result structure to annotate + * \param mapping Feature mappings + * \param points Unpacked point pathes + * \param turnsDir output turns annotation storage + * \param times output times annotation storage + * \param turnsGeom output turns geometry + * \return OSRM routing errors if any exists + */ + ResultCode MakeTurnAnnotation(RawRoutingResultT const & routingResult, RoutingMappingPtrT const & mapping, + vector & points, Route::TurnsT & turnsDir,Route::TimesT & times, turns::TurnsGeomT & turnsGeom); void CalculateRouteAsync(ReadyCallback const & callback); ResultCode CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, Route & route); private: + void GenerateBorderTask(NodeIdVectorT const & borderNodes, RoutingMappingPtrT & mapping, MultiroutingTaskPointT & outgoingTask, uint32_t mwmid); NodeID GetTurnTargetNode(NodeID src, NodeID trg, QueryEdge::EdgeData const & edgeData, RoutingMappingPtrT const & routingMapping); void GetPossibleTurns(NodeID node, m2::PointD const & p1, @@ -201,9 +231,9 @@ private: turns::TurnDirection MostLeftDirection(double angle) const; turns::TurnDirection IntermediateDirection(double angle) const; void GetTurnGeometry(m2::PointD const & p, m2::PointD const & p1, - OsrmRouter::GeomTurnCandidateT & candidates, string const & fName) const; + OsrmRouter::GeomTurnCandidateT & candidates, RoutingMappingPtrT const & mapping) const; bool KeepOnewayOutgoingTurnIncomingEdges(TurnCandidatesT const & nodes, Route::TurnItem const & turn, - m2::PointD const & p, m2::PointD const & p1, string const & fName) const; + m2::PointD const & p, m2::PointD const & p1, RoutingMappingPtrT const & mapping) const; bool KeepOnewayOutgoingTurnRoundabout(bool isRound1, bool isRound2) const; turns::TurnDirection RoundaboutDirection(bool isRound1, bool isRound2, bool hasMultiTurns, Route::TurnItem const & turn) const;