diff --git a/defines.hpp b/defines.hpp index 612169d512..9eb0cd88de 100644 --- a/defines.hpp +++ b/defines.hpp @@ -27,6 +27,7 @@ #define METADATA_FILE_TAG "meta" #define METADATA_INDEX_FILE_TAG "metaidx" #define ALTITUDES_FILE_TAG "altitudes" +#define ROUTING_FILE_TAG "routing" #define FEATURE_OFFSETS_FILE_TAG "offs" #define RANKS_FILE_TAG "ranks" #define REGION_INFO_FILE_TAG "rgninfo" diff --git a/generator/generator_tests/osm_type_test.cpp b/generator/generator_tests/osm_type_test.cpp index de15b240dc..f1b2992005 100644 --- a/generator/generator_tests/osm_type_test.cpp +++ b/generator/generator_tests/osm_type_test.cpp @@ -593,7 +593,7 @@ UNIT_TEST(OsmType_Surface) UNIT_TEST(OsmType_Ferry) { - routing::CarModel const & carModel = routing::CarModel::Instance(); + routing::CarModel const & carModel = routing::CarModel::AllLimitsInstance(); char const * arr[][2] = { { "motorcar", "yes" }, diff --git a/geometry/polyline2d.hpp b/geometry/polyline2d.hpp index 681a4e811b..40b4a99da6 100644 --- a/geometry/polyline2d.hpp +++ b/geometry/polyline2d.hpp @@ -11,23 +11,26 @@ namespace m2 { - template -class PolylineT +class Polyline { vector > m_points; public: - PolylineT() {} - PolylineT(initializer_list > points) : m_points(points) + using Container = vector>; + using Iter = typename Container::const_iterator; + + Polyline() {} + Polyline(initializer_list> const & points) : m_points(points) { ASSERT_GREATER(m_points.size(), 1, ()); } - explicit PolylineT(vector > const & points) : m_points(points) + explicit Polyline(vector> const & points) : m_points(points) { ASSERT_GREATER(m_points.size(), 1, ()); } - template PolylineT(IterT beg, IterT end) : m_points(beg, end) + template + Polyline(Iter beg, Iter end) : m_points(beg, end) { ASSERT_GREATER(m_points.size(), 1, ()); } @@ -46,8 +49,8 @@ public: double res = numeric_limits::max(); m2::DistanceToLineSquare > d; - TIter i = Begin(); - for (TIter j = i + 1; j != End(); ++i, ++j) + Iter i = Begin(); + for (Iter j = i + 1; j != End(); ++i, ++j) { d.SetBounds(*i, *j); res = min(res, d(point)); @@ -67,19 +70,22 @@ public: void Clear() { m_points.clear(); } void Add(Point const & pt) { m_points.push_back(pt); } - void Swap(PolylineT & rhs) + void Append(Polyline const & poly) { - m_points.swap(rhs.m_points); + m_points.insert(m_points.end(), poly.m_points.cbegin(), poly.m_points.cend()); } + void PopBack() + { + ASSERT(!m_points.empty(), ()); + m_points.pop_back(); + } + + void Swap(Polyline & rhs) { m_points.swap(rhs.m_points); } size_t GetSize() const { return m_points.size(); } - - bool operator==(PolylineT const & rhs) const { return m_points == rhs.m_points; } - - typedef vector > TContainer; - typedef typename TContainer::const_iterator TIter; - TIter Begin() const { return m_points.begin(); } - TIter End() const { return m_points.end(); } + bool operator==(Polyline const & rhs) const { return m_points == rhs.m_points; } + Iter Begin() const { return m_points.begin(); } + Iter End() const { return m_points.end(); } Point const & Front() const { return m_points.front(); } Point const & Back() const { return m_points.back(); } @@ -110,13 +116,8 @@ public: } vector > const & GetPoints() const { return m_points; } - - friend string DebugPrint(PolylineT const & p) - { - return ::DebugPrint(p.m_points); - } + friend string DebugPrint(Polyline const & p) { return ::DebugPrint(p.m_points); } }; -typedef PolylineT PolylineD; - -} +using PolylineD = Polyline; +} // namespace m2 diff --git a/map/bookmark.cpp b/map/bookmark.cpp index 58d8b3e4c8..644f91beec 100644 --- a/map/bookmark.cpp +++ b/map/bookmark.cpp @@ -769,7 +769,7 @@ void BookmarkCategory::SaveToKML(ostream & s) s << " "; Track::PolylineD const & poly = track->GetPolyline(); - for (Track::PolylineD::TIter pt = poly.Begin(); pt != poly.End(); ++pt) + for (auto pt = poly.Begin(); pt != poly.End(); ++pt) s << PointToString(*pt) << " "; s << " \n" diff --git a/map/framework.cpp b/map/framework.cpp index 590a46f6fd..5dccfb3db4 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -8,8 +8,8 @@ #include "defines.hpp" #include "private.h" +#include "routing/car_router.hpp" #include "routing/online_absent_fetcher.hpp" -#include "routing/osrm_router.hpp" #include "routing/road_graph_router.hpp" #include "routing/route.hpp" #include "routing/routing_algorithm.hpp" @@ -2421,7 +2421,9 @@ void Framework::SetRouterImpl(RouterType type) return m_model.GetIndex().GetMwmIdByCountryFile(CountryFile(countryFile)).IsAlive(); }; - router.reset(new OsrmRouter(&m_model.GetIndex(), countryFileGetter)); + router.reset( + new CarRouter(m_model.GetIndex(), countryFileGetter, + CreateCarAStarBidirectionalRouter(m_model.GetIndex(), countryFileGetter))); fetcher.reset(new OnlineAbsentCountriesFetcher(countryFileGetter, localFileChecker)); m_routingSession.SetRoutingSettings(routing::GetCarRoutingSettings()); } @@ -2573,8 +2575,8 @@ RouterType Framework::GetBestRouter(m2::PointD const & startPoint, m2::PointD co { return m_infoGetter->GetRegionCountryId(pt); }; - if (!OsrmRouter::CheckRoutingAbility(startPoint, finalPoint, countryFileGetter, - &m_model.GetIndex())) + if (!CarRouter::CheckRoutingAbility(startPoint, finalPoint, countryFileGetter, + m_model.GetIndex())) { return RouterType::Pedestrian; } diff --git a/map/track.cpp b/map/track.cpp index fa9cc3a02e..f521c2ead6 100644 --- a/map/track.cpp +++ b/map/track.cpp @@ -27,7 +27,7 @@ double Track::GetLengthMeters() const { double res = 0.0; - PolylineD::TIter i = m_polyline.Begin(); + auto i = m_polyline.Begin(); double lat1 = MercatorBounds::YToLat(i->y); double lon1 = MercatorBounds::XToLon(i->x); for (++i; i != m_polyline.End(); ++i) diff --git a/routing/base/followed_polyline.hpp b/routing/base/followed_polyline.hpp index ebf2a87d78..4ceaa5a4b2 100644 --- a/routing/base/followed_polyline.hpp +++ b/routing/base/followed_polyline.hpp @@ -20,6 +20,18 @@ public: void Swap(FollowedPolyline & rhs); + void Append(FollowedPolyline const & poly) + { + m_poly.Append(poly.m_poly); + Update(); + } + + void PopBack() + { + m_poly.PopBack(); + Update(); + } + bool IsValid() const { return (m_current.IsValid() && m_poly.GetSize() > 1); } m2::PolylineD const & GetPolyline() const { return m_poly; } diff --git a/routing/bicycle_model.hpp b/routing/bicycle_model.hpp index 9293fcc1cd..9defeda9be 100644 --- a/routing/bicycle_model.hpp +++ b/routing/bicycle_model.hpp @@ -33,12 +33,12 @@ private: uint32_t m_bidirBicycleType = 0; }; -class BicycleModelFactory : public IVehicleModelFactory +class BicycleModelFactory : public VehicleModelFactory { public: BicycleModelFactory(); - /// @name Overrides from IVehicleModelFactory. + /// @name Overrides from VehicleModelFactory. //@{ shared_ptr GetVehicleModel() const override; shared_ptr GetVehicleModelForCountry(string const & country) const override; diff --git a/routing/car_model.cpp b/routing/car_model.cpp index 31a6e4c78b..75b78b93c8 100644 --- a/routing/car_model.cpp +++ b/routing/car_model.cpp @@ -75,10 +75,20 @@ CarModel::CarModel() } // static -CarModel const & CarModel::Instance() +CarModel const & CarModel::AllLimitsInstance() { static CarModel const instance; return instance; } +CarModelFactory::CarModelFactory() { m_model = make_shared(); } +shared_ptr CarModelFactory::GetVehicleModel() const { return m_model; } +shared_ptr CarModelFactory::GetVehicleModelForCountry( + string const & /* country */) const +{ + // @TODO(bykoianko) Different vehicle model for different country should be supported + // according to http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions. + // See pedestrian_model.cpp and bicycle_model.cpp for example. + return m_model; +} } // namespace routing diff --git a/routing/car_model.hpp b/routing/car_model.hpp index 8170df3a75..44378202e7 100644 --- a/routing/car_model.hpp +++ b/routing/car_model.hpp @@ -1,16 +1,29 @@ #pragma once - #include "vehicle_model.hpp" +#include "std/shared_ptr.hpp" + namespace routing { class CarModel : public VehicleModel { +public: CarModel(); -public: - static CarModel const & Instance(); + static CarModel const & AllLimitsInstance(); }; +class CarModelFactory : public VehicleModelFactory +{ +public: + CarModelFactory(); + + // VehicleModelFactory overrides: + shared_ptr GetVehicleModel() const override; + shared_ptr GetVehicleModelForCountry(string const & country) const override; + +private: + shared_ptr m_model; +}; } // namespace routing diff --git a/routing/osrm_router.cpp b/routing/car_router.cpp similarity index 60% rename from routing/osrm_router.cpp rename to routing/car_router.cpp index 3ce50d4db3..4ddd1260ba 100644 --- a/routing/osrm_router.cpp +++ b/routing/car_router.cpp @@ -1,10 +1,12 @@ +#include "routing/car_router.hpp" + #include "routing/cross_mwm_router.hpp" #include "routing/loaded_path_segment.hpp" #include "routing/online_cross_fetcher.hpp" #include "routing/osrm2feature_map.hpp" #include "routing/osrm_helpers.hpp" #include "routing/osrm_path_segment_factory.hpp" -#include "routing/osrm_router.hpp" +#include "routing/road_graph_router.hpp" #include "routing/turns_generator.hpp" #include "platform/country_file.hpp" @@ -15,8 +17,10 @@ #include "geometry/distance_on_sphere.hpp" #include "geometry/mercator.hpp" +#include "indexer/feature_altitude.hpp" #include "indexer/ftypes_matcher.hpp" #include "indexer/index.hpp" +#include "indexer/mwm_set.hpp" #include "indexer/scales.hpp" #include "coding/reader_wrapper.hpp" @@ -30,20 +34,19 @@ #include "std/limits.hpp" #include "std/string.hpp" -#include "3party/osrm/osrm-backend/data_structures/query_edge.hpp" #include "3party/osrm/osrm-backend/data_structures/internal_route_result.hpp" +#include "3party/osrm/osrm-backend/data_structures/query_edge.hpp" #include "3party/osrm/osrm-backend/descriptors/description_factory.hpp" #define INTERRUPT_WHEN_CANCELLED(DELEGATE) \ - do \ - { \ - if (DELEGATE.IsCancelled()) \ - return Cancelled; \ + do \ + { \ + if (DELEGATE.IsCancelled()) \ + return Cancelled; \ } while (false) namespace routing { - namespace { size_t constexpr kMaxNodeCandidatesCount = 10; @@ -52,7 +55,6 @@ double constexpr kMwmLoadedProgress = 10.0f; double constexpr kPointsFoundProgress = 15.0f; double constexpr kCrossPathFoundProgress = 50.0f; double constexpr kPathFoundProgress = 70.0f; -} // namespace using RawRouteData = InternalRouteResult; @@ -61,7 +63,6 @@ class OSRMRoutingResult : public turns::IRoutingResult public: // turns::IRoutingResult overrides: TUnpackedPathSegments const & GetSegments() const override { return m_loadedSegments; } - void GetPossibleTurns(TNodeId node, m2::PointD const & ingoingPoint, m2::PointD const & junctionPoint, size_t & ingoingCount, turns::TurnCandidates & outgoingTurns) const override @@ -145,14 +146,12 @@ public: } sort(outgoingTurns.candidates.begin(), outgoingTurns.candidates.end(), - [](turns::TurnCandidate const & t1, turns::TurnCandidate const & t2) - { - return t1.angle < t2.angle; - }); + [](turns::TurnCandidate const & t1, turns::TurnCandidate const & t2) { + return t1.angle < t2.angle; + }); } double GetPathLength() const override { return m_rawResult.shortestPathLength; } - Junction GetStartPoint() const override { return Junction(m_rawResult.sourceEdge.segmentPoint, feature::kDefaultAltitudeMeters); @@ -176,14 +175,14 @@ public: bool isEndNode = (segmentIndex == numSegments - 1); if (isStartNode || isEndNode) { - OsrmPathSegmentFactory(m_routingMapping, m_index, - pathSegments[segmentIndex], m_rawResult.sourceEdge, - m_rawResult.targetEdge, isStartNode, isEndNode, m_loadedSegments[segmentIndex]); + OsrmPathSegmentFactory(m_routingMapping, m_index, pathSegments[segmentIndex], + m_rawResult.sourceEdge, m_rawResult.targetEdge, isStartNode, + isEndNode, m_loadedSegments[segmentIndex]); } else { - OsrmPathSegmentFactory(m_routingMapping, m_index, - pathSegments[segmentIndex], m_loadedSegments[segmentIndex]); + OsrmPathSegmentFactory(m_routingMapping, m_index, pathSegments[segmentIndex], + m_loadedSegments[segmentIndex]); } } } @@ -196,47 +195,96 @@ private: RoutingMapping & m_routingMapping; }; -// static -bool OsrmRouter::CheckRoutingAbility(m2::PointD const & startPoint, m2::PointD const & finalPoint, - TCountryFileFn const & countryFileFn, Index * index) +IRouter::ResultCode FindSingleOsrmRoute(FeatureGraphNode const & source, + FeatureGraphNode const & target, + RouterDelegate const & delegate, Index const & index, + TRoutingMappingPtr & mapping, Route & route) { - RoutingIndexManager manager(countryFileFn, *index); + vector geometry; + Route::TTurns turns; + Route::TTimes times; + Route::TStreets streets; + + LOG(LINFO, ("OSRM route from", MercatorBounds::ToLatLon(source.segmentPoint), "to", + MercatorBounds::ToLatLon(target.segmentPoint))); + + RawRoutingResult rawRoutingResult; + if (!FindSingleRoute(source, target, mapping->m_dataFacade, rawRoutingResult)) + return routing::IRouter::RouteNotFound; + + OSRMRoutingResult routingResult(index, *mapping, rawRoutingResult); + routing::IRouter::ResultCode const result = + MakeTurnAnnotation(routingResult, delegate, geometry, turns, times, streets); + if (result != routing::IRouter::NoError) + { + LOG(LWARNING, ("Can't load road path data from disk for", mapping->GetCountryName(), + ". Result code =", result)); + return result; + } + + route.SetTurnInstructions(move(turns)); + route.SetSectionTimes(move(times)); + route.SetStreetNames(move(streets)); + + vector mwmPoints; + JunctionsToPoints(geometry, mwmPoints); + route.SetGeometry(mwmPoints.cbegin(), mwmPoints.cend()); + + return routing::IRouter::NoError; +} +} // namespace + +// static +bool CarRouter::CheckRoutingAbility(m2::PointD const & startPoint, m2::PointD const & finalPoint, + TCountryFileFn const & countryFileFn, Index & index) +{ + RoutingIndexManager manager(countryFileFn, index); return manager.GetMappingByPoint(startPoint)->IsValid() && manager.GetMappingByPoint(finalPoint)->IsValid(); } -OsrmRouter::OsrmRouter(Index * index, TCountryFileFn const & countryFileFn) - : m_pIndex(index), m_indexManager(countryFileFn, *index) +CarRouter::CarRouter(Index & index, TCountryFileFn const & countryFileFn, + unique_ptr router) + : m_index(index), m_indexManager(countryFileFn, index), m_router(move(router)) { } -string OsrmRouter::GetName() const -{ - return "vehicle"; -} +string CarRouter::GetName() const { return "mixed-car"; } -void OsrmRouter::ClearState() +void CarRouter::ClearState() { m_cachedTargets.clear(); m_cachedTargetPoint = m2::PointD::Zero(); m_indexManager.Clear(); + + if (m_router) + m_router->ClearState(); + else + LOG(LERROR, ("m_router is not initialized.")); } -bool OsrmRouter::FindRouteFromCases(TFeatureGraphNodeVec const & source, - TFeatureGraphNodeVec const & target, TDataFacade & facade, - RawRoutingResult & rawRoutingResult) +bool CarRouter::FindRouteMSMT(TFeatureGraphNodeVec const & sources, + TFeatureGraphNodeVec const & targets, RouterDelegate const & delegate, + TRoutingMappingPtr & mapping, Route & route) { + ASSERT(mapping, ()); + + Route emptyRoute(GetName()); + route.Swap(emptyRoute); /// @todo (ldargunov) make more complex nearest edge turnaround - for (auto const & targetEdge : target) - for (auto const & sourceEdge : source) - if (FindSingleRoute(sourceEdge, targetEdge, facade, rawRoutingResult)) + for (auto const & targetEdge : targets) + { + for (auto const & sourceEdge : sources) + { + if (FindSingleRouteDispatcher(sourceEdge, targetEdge, delegate, mapping, route) == NoError) return true; + } + } return false; } -void FindGraphNodeOffsets(uint32_t const nodeId, m2::PointD const & point, - Index const * pIndex, TRoutingMappingPtr & mapping, - FeatureGraphNode & graphNode) +void FindGraphNodeOffsets(uint32_t const nodeId, m2::PointD const & point, Index const * pIndex, + TRoutingMappingPtr & mapping, FeatureGraphNode & graphNode) { graphNode.segmentPoint = point; @@ -279,7 +327,7 @@ void FindGraphNodeOffsets(uint32_t const nodeId, m2::PointD const & point, } void CalculatePhantomNodeForCross(TRoutingMappingPtr & mapping, FeatureGraphNode & graphNode, - Index const * pIndex, bool forward) + Index const * pIndex, bool forward) { if (graphNode.segment.IsValid()) return; @@ -297,96 +345,35 @@ void CalculatePhantomNodeForCross(TRoutingMappingPtr & mapping, FeatureGraphNode // TODO (ldragunov) move this function to cross mwm router // TODO (ldragunov) process case when the start and the finish points are placed on the same edge. -OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(TCheckedPath const & path, - RouterDelegate const & delegate, - Route & route) +CarRouter::ResultCode CarRouter::MakeRouteFromCrossesPath(TCheckedPath const & path, + RouterDelegate const & delegate, + Route & route) { - Route::TTurns turnsDir; - Route::TTimes times; - Route::TStreets streets; - vector points; + Route emptyRoute(GetName()); + route.Swap(emptyRoute); + for (RoutePathCross cross : path) { ASSERT_EQUAL(cross.startNode.mwmId, cross.finalNode.mwmId, ()); - RawRoutingResult routingResult; TRoutingMappingPtr mwmMapping = m_indexManager.GetMappingById(cross.startNode.mwmId); ASSERT(mwmMapping->IsValid(), ()); MappingGuard mwmMappingGuard(mwmMapping); UNUSED_VALUE(mwmMappingGuard); - CalculatePhantomNodeForCross(mwmMapping, cross.startNode, m_pIndex, true /* forward */); - CalculatePhantomNodeForCross(mwmMapping, cross.finalNode, m_pIndex, false /* forward */); - if (!FindSingleRoute(cross.startNode, cross.finalNode, mwmMapping->m_dataFacade, routingResult)) - return RouteNotFound; - - if (!points.empty()) - { - // Remove road end point and turn instruction. - points.pop_back(); - turnsDir.pop_back(); - times.pop_back(); - // Streets might not point to the last point of the path. - } - - // Get annotated route. - Route::TTurns mwmTurnsDir; - Route::TTimes mwmTimes; - Route::TStreets mwmStreets; - vector mwmJunctions; - - OSRMRoutingResult resultGraph(*m_pIndex, *mwmMapping, routingResult); - if (MakeTurnAnnotation(resultGraph, delegate, mwmJunctions, mwmTurnsDir, mwmTimes, mwmStreets) != NoError) - { - LOG(LWARNING, ("Can't load road path data from disk for", mwmMapping->GetCountryName())); - return RouteNotFound; - } - - vector mwmPoints; - JunctionsToPoints(mwmJunctions, mwmPoints); - - // Connect annotated route. - auto const pSize = static_cast(points.size()); - for (auto turn : mwmTurnsDir) - { - if (turn.m_index == 0) - continue; - turn.m_index += pSize; - turnsDir.push_back(turn); - } - - if (!mwmStreets.empty() && !streets.empty() && mwmStreets.front().second == streets.back().second) - mwmStreets.erase(mwmStreets.begin()); - for (auto street : mwmStreets) - { - if (street.first == 0) - continue; - street.first += pSize; - streets.push_back(street); - } - - double const estimationTime = times.size() ? times.back().second : 0.0; - for (auto time : mwmTimes) - { - if (time.first == 0) - continue; - time.first += pSize; - time.second += estimationTime; - times.push_back(time); - } - - points.insert(points.end(), mwmPoints.begin(), mwmPoints.end()); + CalculatePhantomNodeForCross(mwmMapping, cross.startNode, &m_index, true /* forward */); + CalculatePhantomNodeForCross(mwmMapping, cross.finalNode, &m_index, false /* forward */); + IRouter::ResultCode const result = + FindSingleRouteDispatcher(cross.startNode, cross.finalNode, delegate, mwmMapping, route); + if (result != NoError) + return result; } - route.SetGeometry(points.begin(), points.end()); - route.SetTurnInstructions(move(turnsDir)); - route.SetSectionTimes(move(times)); - route.SetStreetNames(move(streets)); return NoError; } -OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, - m2::PointD const & startDirection, - m2::PointD const & finalPoint, - RouterDelegate const & delegate, Route & route) +CarRouter::ResultCode CarRouter::CalculateRoute(m2::PointD const & startPoint, + m2::PointD const & startDirection, + m2::PointD const & finalPoint, + RouterDelegate const & delegate, Route & route) { my::HighResTimer timer(true); @@ -433,17 +420,16 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, TFeatureGraphNodeVec startTask; { - ResultCode const code = FindPhantomNodes(startPoint, startDirection, - startTask, kMaxNodeCandidatesCount, startMapping); + ResultCode const code = FindPhantomNodes(startPoint, startDirection, startTask, + kMaxNodeCandidatesCount, startMapping); if (code != NoError) return code; } { if (finalPoint != m_cachedTargetPoint) { - ResultCode const code = - FindPhantomNodes(finalPoint, m2::PointD::Zero(), - m_cachedTargets, kMaxNodeCandidatesCount, targetMapping); + ResultCode const code = FindPhantomNodes(finalPoint, m2::PointD::Zero(), m_cachedTargets, + kMaxNodeCandidatesCount, targetMapping); if (code != NoError) return code; m_cachedTargetPoint = finalPoint; @@ -456,8 +442,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, delegate.OnProgress(kPointsFoundProgress); // 4. Find route. - RawRoutingResult routingResult; - double crossCost = 0; + double crossDistanceM = 0; TCheckedPath finalPath; // Manually load facade to avoid unmaping files we routing on. @@ -467,15 +452,13 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, if (startMapping->GetMwmId() == targetMapping->GetMwmId()) { LOG(LINFO, ("Single mwm routing case")); - m_indexManager.ForEachMapping([](pair const & indexPair) - { - indexPair.second->FreeCrossContext(); - }); - ResultCode crossCode = CalculateCrossMwmPath(startTask, m_cachedTargets, m_indexManager, crossCost, - delegate, finalPath); + m_indexManager.ForEachMapping([](pair const & indexPair) { + indexPair.second->FreeCrossContext(); + }); + ResultCode crossCode = CalculateCrossMwmPath(startTask, m_cachedTargets, m_indexManager, + crossDistanceM, delegate, finalPath); LOG(LINFO, ("Found cross path in", timer.ElapsedNano(), "ns.")); - if (!FindRouteFromCases(startTask, m_cachedTargets, startMapping->m_dataFacade, - routingResult)) + if (!FindRouteMSMT(startTask, m_cachedTargets, delegate, startMapping, route)) { if (crossCode == NoError) { @@ -488,9 +471,10 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, } INTERRUPT_WHEN_CANCELLED(delegate); - if (crossCode == NoError && crossCost < routingResult.shortestPathLength) + if (crossCode == NoError && crossDistanceM < route.GetTotalDistanceMeters()) { - LOG(LINFO, ("Cross mwm path shorter. Cross cost:", crossCost, "single cost:", routingResult.shortestPathLength)); + LOG(LINFO, ("Cross mwm path is shorter than single mwm path. Cross distance:", + crossDistanceM, "single distance:", route.GetTotalDistanceMeters())); auto code = MakeRouteFromCrossesPath(finalPath, delegate, route); LOG(LINFO, ("Made final route in", timer.ElapsedNano(), "ns.")); timer.Reset(); @@ -500,35 +484,13 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, INTERRUPT_WHEN_CANCELLED(delegate); delegate.OnProgress(kPathFoundProgress); - // 5. Restore route. - - Route::TTurns turnsDir; - Route::TTimes times; - Route::TStreets streets; - vector junctions; - - OSRMRoutingResult resultGraph(*m_pIndex, *startMapping, routingResult); - if (MakeTurnAnnotation(resultGraph, delegate, junctions, turnsDir, times, streets) != NoError) - { - LOG(LWARNING, ("Can't load road path data from disk!")); - return RouteNotFound; - } - - vector points; - JunctionsToPoints(junctions, points); - - route.SetGeometry(points.begin(), points.end()); - route.SetTurnInstructions(move(turnsDir)); - route.SetSectionTimes(move(times)); - route.SetStreetNames(move(streets)); - return NoError; } - else //4.2 Multiple mwm case + else // 4.2 Multiple mwm case { LOG(LINFO, ("Multiple mwm routing case")); - ResultCode code = CalculateCrossMwmPath(startTask, m_cachedTargets, m_indexManager, crossCost, - delegate, finalPath); + ResultCode code = CalculateCrossMwmPath(startTask, m_cachedTargets, m_indexManager, + crossDistanceM, delegate, finalPath); timer.Reset(); INTERRUPT_WHEN_CANCELLED(delegate); delegate.OnProgress(kCrossPathFoundProgress); @@ -538,30 +500,29 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, { auto code = MakeRouteFromCrossesPath(finalPath, delegate, route); // Manually free all cross context allocations before geometry unpacking. - m_indexManager.ForEachMapping([](pair const & indexPair) - { - indexPair.second->FreeCrossContext(); - }); + m_indexManager.ForEachMapping([](pair const & indexPair) { + indexPair.second->FreeCrossContext(); + }); LOG(LINFO, ("Made final route in", timer.ElapsedNano(), "ns.")); timer.Reset(); return code; } - return OsrmRouter::RouteNotFound; + return CarRouter::RouteNotFound; } } -IRouter::ResultCode OsrmRouter::FindPhantomNodes(m2::PointD const & point, - m2::PointD const & direction, - TFeatureGraphNodeVec & res, size_t maxCount, - TRoutingMappingPtr const & mapping) +IRouter::ResultCode CarRouter::FindPhantomNodes(m2::PointD const & point, + m2::PointD const & direction, + TFeatureGraphNodeVec & res, size_t maxCount, + TRoutingMappingPtr const & mapping) { ASSERT(mapping, ()); - helpers::Point2PhantomNode getter(*mapping, *m_pIndex, direction); + helpers::Point2PhantomNode getter(*mapping, m_index, direction); getter.SetPoint(point); - m_pIndex->ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters( - point, kFeatureFindingRectSideRadiusMeters), - scales::GetUpperScale(), mapping->GetMwmId()); + m_index.ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters( + point, kFeatureFindingRectSideRadiusMeters), + scales::GetUpperScale(), mapping->GetMwmId()); if (!getter.HasCandidates()) return RouteNotFound; @@ -569,4 +530,62 @@ IRouter::ResultCode OsrmRouter::FindPhantomNodes(m2::PointD const & point, getter.MakeResult(res, maxCount); return NoError; } + +bool CarRouter::DoesEdgeIndexExist(Index::MwmId const & mwmId) +{ + MwmSet::MwmHandle const handle = m_index.GetMwmHandleById(mwmId); + if (!handle.IsAlive()) + { + ASSERT(false, ("Mwm handle is not alive.")); + return false; + } + + MwmValue const * value = handle.GetValue(); + CHECK(value, ()); + if (value->GetHeader().GetFormat() < version::Format::v8) + return false; + + if (!value->m_cont.IsExist(ROUTING_FILE_TAG)) + return false; + + return true; +} + +IRouter::ResultCode CarRouter::FindSingleRouteDispatcher(FeatureGraphNode const & source, + FeatureGraphNode const & target, + RouterDelegate const & delegate, + TRoutingMappingPtr & mapping, + Route & route) +{ + ASSERT_EQUAL(source.mwmId, target.mwmId, ()); + IRouter::ResultCode result = IRouter::InternalError; + Route mwmRoute(GetName()); + + // @TODO It's not the best place for checking availability of edge index section in mwm. + // Probably it's better to keep if mwm has an edge index section in mwmId. + if (DoesEdgeIndexExist(source.mwmId)) + { + if (!m_router) + { + LOG(LERROR, ("m_router is not initialized.")); + return IRouter::InternalError; + } + LOG(LINFO, (m_router->GetName(), "route from", MercatorBounds::ToLatLon(source.segmentPoint), "to", + MercatorBounds::ToLatLon(target.segmentPoint))); + result = m_router->CalculateRoute(source.segmentPoint, m2::PointD(0, 0) /* direction */, + target.segmentPoint, delegate, mwmRoute); + } + else + { + // OSRM Routing + // @TODO This branch is implemented to support old maps with osrm section. When osrm + // section is not supported this branch should be removed. + result = FindSingleOsrmRoute(source, target, delegate, m_index, mapping, mwmRoute); + } + + if (result == IRouter::NoError) + route.AppendRoute(mwmRoute); + + return result; +} } // namespace routing diff --git a/routing/osrm_router.hpp b/routing/car_router.hpp similarity index 60% rename from routing/osrm_router.hpp rename to routing/car_router.hpp index 6c28e3b361..60e4f23946 100644 --- a/routing/osrm_router.hpp +++ b/routing/car_router.hpp @@ -6,7 +6,13 @@ #include "routing/router.hpp" #include "routing/routing_mapping.hpp" -namespace feature { class TypesHolder; } +#include "std/unique_ptr.hpp" +#include "std/vector.hpp" + +namespace feature +{ +class TypesHolder; +} class Index; struct RawRouteData; @@ -16,17 +22,19 @@ class FeatureType; namespace routing { +class RoadGraphRouter; struct RoutePathCross; using TCheckedPath = vector; typedef vector TFeatureGraphNodeVec; -class OsrmRouter : public IRouter +class CarRouter : public IRouter { public: typedef vector GeomTurnCandidateT; - OsrmRouter(Index * index, TCountryFileFn const & countryFileFn); + CarRouter(Index & index, TCountryFileFn const & countryFileFn, + unique_ptr roadGraphRouter); virtual string GetName() const override; @@ -36,26 +44,15 @@ public: virtual void ClearState() override; - /*! Find single shortest path in a single MWM between 2 sets of edges - * \param source: vector of source edges 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 when path exists, false otherwise. - */ - static bool FindRouteFromCases(TFeatureGraphNodeVec const & source, - TFeatureGraphNodeVec const & target, TDataFacade & facade, - RawRoutingResult & rawRoutingResult); - /*! Fast checking ability of route construction * @param startPoint starting road point * @param finalPoint final road point * @param countryFileFn function for getting filename from point - * @oaram index mwmSet index + * @param index mwmSet index * @returns true if we can start routing process with a given data. */ static bool CheckRoutingAbility(m2::PointD const & startPoint, m2::PointD const & finalPoint, - TCountryFileFn const & countryFileFn, Index * index); + TCountryFileFn const & countryFileFn, Index & index); protected: /*! @@ -68,9 +65,9 @@ protected: * \param mapping Reference to routing indexes. * \return NoError if there are any nodes in res. RouteNotFound otherwise. */ - IRouter::ResultCode FindPhantomNodes(m2::PointD const & point, - m2::PointD const & direction, TFeatureGraphNodeVec & res, - size_t maxCount, TRoutingMappingPtr const & mapping); + IRouter::ResultCode FindPhantomNodes(m2::PointD const & point, m2::PointD const & direction, + TFeatureGraphNodeVec & res, size_t maxCount, + TRoutingMappingPtr const & mapping); private: /*! @@ -84,11 +81,39 @@ private: ResultCode MakeRouteFromCrossesPath(TCheckedPath const & path, RouterDelegate const & delegate, Route & route); - Index const * m_pIndex; + // @TODO(bykoianko) When routing section implementation is merged to master + // this method should be moved to routing loader. + bool DoesEdgeIndexExist(Index::MwmId const & mwmId); + + /*! + * \brief Builds a route within one mwm using A* if edge index section is available and osrm + * otherwise. + * Then reconstructs the route and restores all route attributes. + * \param route The found route is added to the |route| if the method returns true. + */ + IRouter::ResultCode FindSingleRouteDispatcher(FeatureGraphNode const & source, + FeatureGraphNode const & target, + RouterDelegate const & delegate, + TRoutingMappingPtr & mapping, Route & route); + + /*! Finds single shortest path in a single MWM between 2 sets of edges. + * It's a route from multiple sources to multiple targets (MSMT). + * \param source: vector of source edges to make path + * \param target: vector of target edges to make path + * \param facade: OSRM routing data facade to recover graph information + * \param rawRoutingResult: routing result store + * \return true when path exists, false otherwise. + */ + bool FindRouteMSMT(TFeatureGraphNodeVec const & source, TFeatureGraphNodeVec const & target, + RouterDelegate const & delegate, TRoutingMappingPtr & mapping, Route & route); + + Index & m_index; TFeatureGraphNodeVec m_cachedTargets; m2::PointD m_cachedTargetPoint; RoutingIndexManager m_indexManager; + + unique_ptr m_router; }; } // namespace routing diff --git a/routing/cross_mwm_road_graph.hpp b/routing/cross_mwm_road_graph.hpp index e0a59911f7..7687c3246f 100644 --- a/routing/cross_mwm_road_graph.hpp +++ b/routing/cross_mwm_road_graph.hpp @@ -1,7 +1,7 @@ #pragma once +#include "car_router.hpp" #include "osrm_engine.hpp" -#include "osrm_router.hpp" #include "router.hpp" #include "indexer/index.hpp" diff --git a/routing/features_road_graph.cpp b/routing/features_road_graph.cpp index 23912ba928..79c61a0a58 100644 --- a/routing/features_road_graph.cpp +++ b/routing/features_road_graph.cpp @@ -46,7 +46,8 @@ FeaturesRoadGraph::Value::Value(MwmSet::MwmHandle handle) : m_mwmHandle(move(han m_altitudeLoader = make_unique(*m_mwmHandle.GetValue()); } -FeaturesRoadGraph::CrossCountryVehicleModel::CrossCountryVehicleModel(unique_ptr && vehicleModelFactory) +FeaturesRoadGraph::CrossCountryVehicleModel::CrossCountryVehicleModel( + unique_ptr vehicleModelFactory) : m_vehicleModelFactory(move(vehicleModelFactory)) , m_maxSpeedKMPH(m_vehicleModelFactory->GetVehicleModel()->GetMaxSpeed()) { @@ -106,12 +107,9 @@ void FeaturesRoadGraph::RoadInfoCache::Clear() { m_cache.clear(); } - FeaturesRoadGraph::FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode, - unique_ptr && vehicleModelFactory) - : m_index(index) - , m_mode(mode) - , m_vehicleModel(move(vehicleModelFactory)) + unique_ptr vehicleModelFactory) + : m_index(index), m_mode(mode), m_vehicleModel(move(vehicleModelFactory)) { } diff --git a/routing/features_road_graph.hpp b/routing/features_road_graph.hpp index 1f99d2f78b..9e21db0d87 100644 --- a/routing/features_road_graph.hpp +++ b/routing/features_road_graph.hpp @@ -26,7 +26,7 @@ private: class CrossCountryVehicleModel : public IVehicleModel { public: - CrossCountryVehicleModel(unique_ptr && vehicleModelFactory); + CrossCountryVehicleModel(unique_ptr vehicleModelFactory); // IVehicleModel overrides: double GetSpeed(FeatureType const & f) const override; @@ -39,7 +39,7 @@ private: private: IVehicleModel * GetVehicleModel(FeatureID const & featureId) const; - unique_ptr const m_vehicleModelFactory; + unique_ptr const m_vehicleModelFactory; double const m_maxSpeedKMPH; mutable map> m_cache; @@ -59,7 +59,7 @@ private: public: FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode, - unique_ptr && vehicleModelFactory); + unique_ptr vehicleModelFactory); static uint32_t GetStreetReadScale(); diff --git a/routing/osrm_engine.hpp b/routing/osrm_engine.hpp index 2d032dde9c..152f984490 100644 --- a/routing/osrm_engine.hpp +++ b/routing/osrm_engine.hpp @@ -88,7 +88,7 @@ using TRawDataFacade = OsrmRawDataFacade; void FindWeightsMatrix(TRoutingNodes const & sources, TRoutingNodes const & targets, TRawDataFacade & facade, vector & result); -/*! Find single shortest path in a single MWM between 2 OSRM nodes +/*! Finds single shortest path in a single MWM between 2 OSRM nodes * \param source Source OSRM graph node to make path. * \param taget Target OSRM graph node to make path. * \param facade OSRM routing data facade to recover graph information. diff --git a/routing/osrm_helpers.cpp b/routing/osrm_helpers.cpp index 2aed745f84..9a5274a75a 100644 --- a/routing/osrm_helpers.cpp +++ b/routing/osrm_helpers.cpp @@ -38,7 +38,7 @@ void Point2PhantomNode::FindNearestSegment(FeatureType const & ft, m2::PointD co void Point2PhantomNode::operator()(FeatureType const & ft) { - if (!CarModel::Instance().IsRoad(ft)) + if (!CarModel::AllLimitsInstance().IsRoad(ft)) return; Candidate res; @@ -280,7 +280,7 @@ void Point2PhantomNode::CalculateWeights(FeatureGraphNode & node) const void Point2Node::operator()(FeatureType const & ft) { - if (!CarModel::Instance().IsRoad(ft)) + if (!CarModel::AllLimitsInstance().IsRoad(ft)) return; uint32_t const featureId = ft.GetID().m_index; for (auto const & n : m_routingMapping.m_segMapping.GetNodeIdByFid(featureId)) diff --git a/routing/pedestrian_model.hpp b/routing/pedestrian_model.hpp index 93ebd6fdb1..bcff1db241 100644 --- a/routing/pedestrian_model.hpp +++ b/routing/pedestrian_model.hpp @@ -28,12 +28,12 @@ private: uint32_t m_yesFootType = 0; }; -class PedestrianModelFactory : public IVehicleModelFactory +class PedestrianModelFactory : public VehicleModelFactory { public: PedestrianModelFactory(); - /// @name Overrides from IVehicleModelFactory. + /// @name Overrides from VehicleModelFactory. //@{ shared_ptr GetVehicleModel() const override; shared_ptr GetVehicleModelForCountry(string const & country) const override; diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 312b466a3c..06409c83ef 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -1,10 +1,12 @@ +#include "routing/road_graph_router.hpp" + #include "routing/bicycle_directions.hpp" #include "routing/bicycle_model.hpp" +#include "routing/car_model.hpp" #include "routing/features_road_graph.hpp" #include "routing/nearest_edge_finder.hpp" #include "routing/pedestrian_directions.hpp" #include "routing/pedestrian_model.hpp" -#include "routing/road_graph_router.hpp" #include "routing/route.hpp" #include "coding/reader_wrapper.hpp" @@ -136,10 +138,9 @@ void FindClosestEdges(IRoadGraph const & graph, m2::PointD const & point, } // namespace RoadGraphRouter::~RoadGraphRouter() {} - RoadGraphRouter::RoadGraphRouter(string const & name, Index const & index, TCountryFileFn const & countryFileFn, IRoadGraph::Mode mode, - unique_ptr && vehicleModelFactory, + unique_ptr && vehicleModelFactory, unique_ptr && algorithm, unique_ptr && directionsEngine) : m_name(name) @@ -280,7 +281,7 @@ void RoadGraphRouter::ReconstructRoute(vector && path, Route & route, unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn) { - unique_ptr vehicleModelFactory(new PedestrianModelFactory()); + unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarRoutingAlgorithm()); unique_ptr directionsEngine(new PedestrianDirectionsEngine()); unique_ptr router(new RoadGraphRouter( @@ -291,7 +292,7 @@ unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn co unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn) { - unique_ptr vehicleModelFactory(new PedestrianModelFactory()); + unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm()); unique_ptr directionsEngine(new PedestrianDirectionsEngine()); unique_ptr router(new RoadGraphRouter( @@ -302,7 +303,7 @@ unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCou unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn) { - unique_ptr vehicleModelFactory(new BicycleModelFactory()); + unique_ptr vehicleModelFactory(new BicycleModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm()); unique_ptr directionsEngine(new BicycleDirectionsEngine(index)); unique_ptr router(new RoadGraphRouter( @@ -310,4 +311,18 @@ unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, TCountr move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } + +unique_ptr CreateCarAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn) +{ + unique_ptr vehicleModelFactory = make_unique(); + unique_ptr algorithm = make_unique(); + // @TODO Bicycle turn generation engine is used now. It's ok for the time being. + // But later a special car turn generation engine should be implemented. + unique_ptr directionsEngine = make_unique(index); + unique_ptr router = make_unique( + "astar-bidirectional-car", index, countryFileFn, IRoadGraph::Mode::ObeyOnewayTag, + move(vehicleModelFactory), move(algorithm), move(directionsEngine)); + return router; +} } // namespace routing diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index 17701bdc7a..14405a38d6 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -24,8 +24,7 @@ class RoadGraphRouter : public IRouter { public: RoadGraphRouter(string const & name, Index const & index, TCountryFileFn const & countryFileFn, - IRoadGraph::Mode mode, - unique_ptr && vehicleModelFactory, + IRoadGraph::Mode mode, unique_ptr && vehicleModelFactory, unique_ptr && algorithm, unique_ptr && directionsEngine); ~RoadGraphRouter() override; @@ -56,4 +55,6 @@ private: unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn); unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn); unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn); +unique_ptr CreateCarAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn); } // namespace routing diff --git a/routing/route.cpp b/routing/route.cpp index 27ed38b71c..7ad678977e 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -354,6 +354,64 @@ void Route::Update() m_currentTime = 0.0; } +void Route::AppendRoute(Route const & route) +{ + if (!route.IsValid()) + return; + + double const estimatedTime = m_times.empty() ? 0.0 : m_times.back().second; + if (m_poly.GetPolyline().GetSize() != 0) + { + ASSERT(!m_turns.empty(), ()); + ASSERT(!m_times.empty(), ()); + if (!m_streets.empty()) + ASSERT_LESS(m_streets.back().first + 1, m_poly.GetPolyline().GetSize(), ()); + + // Remove road end point and turn instruction. + ASSERT_LESS(MercatorBounds::DistanceOnEarth(m_poly.End().m_pt, route.m_poly.Begin().m_pt), + 2 /* meters */, ()); + m_poly.PopBack(); + CHECK(!m_turns.empty(), ()); + ASSERT_EQUAL(m_turns.back().m_turn, turns::TurnDirection::ReachedYourDestination, ()); + m_turns.pop_back(); + CHECK(!m_times.empty(), ()); + m_times.pop_back(); + } + + size_t const indexOffset = m_poly.GetPolyline().GetSize(); + + // Appending turns. + for (auto t : route.m_turns) + { + if (t.m_index == 0) + continue; + t.m_index += indexOffset; + m_turns.push_back(move(t)); + } + + // Appending street names. + for (auto s : route.m_streets) + { + if (s.first == 0) + continue; + s.first += indexOffset; + m_streets.push_back(move(s)); + } + + // Appending times. + for (auto t : route.m_times) + { + if (t.first == 0) + continue; + t.first += indexOffset; + t.second += estimatedTime; + m_times.push_back(move(t)); + } + + m_poly.Append(route.m_poly); + Update(); +} + string DebugPrint(Route const & r) { return DebugPrint(r.m_poly.GetPolyline()); diff --git a/routing/route.hpp b/routing/route.hpp index 634ea55e7a..f364fb747b 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -59,6 +59,16 @@ public: inline void SetSectionTimes(TTimes && v) { m_times = move(v); } inline void SetStreetNames(TStreets && v) { m_streets = move(v); } inline void SetAltitudes(feature::TAltitudes && v) { m_altitudes = move(v); } + /// \brief Glues all |route| attributes to |this| except for |m_altitudes|. + // @TODO In the future this method should append |m_altitudes| as well. + // It's not implemented now because it's not easy to do it and it'll not be used in + // the short future. The problem is routes generated by osrm have empty |m_altitudes|. + // So |m_altitudes| should be filled (with correnct or default values) on osrm route + // reconstruction stage to be added with this method. On the other + // hand it seems this method'll not be not used for bicycle and pedestrian routing + // in short future. And altitude is not used for car routing. + void AppendRoute(Route const & route); + uint32_t GetTotalTimeSec() const; uint32_t GetCurrentTimeToEndSec() const; diff --git a/routing/router.hpp b/routing/router.hpp index bd96dd6dad..1e8e0da7d9 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -19,7 +19,8 @@ class Route; /// Routing engine type. enum class RouterType { - Vehicle = 0, /// For OSRM vehicle routing + // @TODO It's necessary to rename Vehicle value to Car. + Vehicle = 0, /// For Car routing (OSRM or AStar) Pedestrian, /// For A star pedestrian routing Bicycle, /// For A star bicycle routing Taxi, /// For taxi route calculation Vehicle routing is used. diff --git a/routing/routing.pro b/routing/routing.pro index 6d676f711c..8eca9f8dd7 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -18,6 +18,7 @@ SOURCES += \ bicycle_directions.cpp \ bicycle_model.cpp \ car_model.cpp \ + car_router.cpp \ cross_mwm_road_graph.cpp \ cross_mwm_router.cpp \ cross_routing_context.cpp \ @@ -30,7 +31,6 @@ SOURCES += \ osrm_engine.cpp \ osrm_helpers.cpp \ osrm_path_segment_factory.cpp \ - osrm_router.cpp \ pedestrian_directions.cpp \ pedestrian_model.cpp \ road_graph.cpp \ @@ -57,6 +57,7 @@ HEADERS += \ bicycle_directions.hpp \ bicycle_model.hpp \ car_model.hpp \ + car_router.hpp \ cross_mwm_road_graph.hpp \ cross_mwm_router.hpp \ cross_routing_context.hpp \ @@ -71,7 +72,6 @@ HEADERS += \ osrm_engine.hpp \ osrm_helpers.hpp \ osrm_path_segment_factory.hpp \ - osrm_router.hpp \ pedestrian_directions.hpp \ pedestrian_model.hpp \ road_graph.hpp \ diff --git a/routing/routing_benchmarks/bicycle_routing_tests.cpp b/routing/routing_benchmarks/bicycle_routing_tests.cpp index 1d66d22327..3853d10e64 100644 --- a/routing/routing_benchmarks/bicycle_routing_tests.cpp +++ b/routing/routing_benchmarks/bicycle_routing_tests.cpp @@ -30,9 +30,9 @@ protected: return engine; } - unique_ptr CreateModelFactory() override + unique_ptr CreateModelFactory() override { - unique_ptr factory( + unique_ptr factory( new SimplifiedModelFactory()); return factory; } diff --git a/routing/routing_benchmarks/helpers.hpp b/routing/routing_benchmarks/helpers.hpp index bf3a385e7a..9d442d97e1 100644 --- a/routing/routing_benchmarks/helpers.hpp +++ b/routing/routing_benchmarks/helpers.hpp @@ -30,7 +30,7 @@ public: protected: virtual unique_ptr CreateDirectionsEngine() = 0; - virtual unique_ptr CreateModelFactory() = 0; + virtual unique_ptr CreateModelFactory() = 0; template unique_ptr CreateRouter(string const & name) @@ -52,7 +52,7 @@ protected: }; template -class SimplifiedModelFactory : public routing::IVehicleModelFactory +class SimplifiedModelFactory : public routing::VehicleModelFactory { public: // Since for test purposes we compare routes lengths to check @@ -78,8 +78,7 @@ public: }; SimplifiedModelFactory() : m_model(make_shared()) {} - - // IVehicleModelFactory overrides: + // VehicleModelFactory overrides: shared_ptr GetVehicleModel() const override { return m_model; } shared_ptr GetVehicleModelForCountry( string const & /*country*/) const override diff --git a/routing/routing_benchmarks/pedestrian_routing_tests.cpp b/routing/routing_benchmarks/pedestrian_routing_tests.cpp index 144688c857..61cfcefe16 100644 --- a/routing/routing_benchmarks/pedestrian_routing_tests.cpp +++ b/routing/routing_benchmarks/pedestrian_routing_tests.cpp @@ -43,9 +43,9 @@ protected: return engine; } - unique_ptr CreateModelFactory() override + unique_ptr CreateModelFactory() override { - unique_ptr factory( + unique_ptr factory( new SimplifiedModelFactory()); return factory; } diff --git a/routing/routing_helpers.hpp b/routing/routing_helpers.hpp index 98365f39c4..76440a457e 100644 --- a/routing/routing_helpers.hpp +++ b/routing/routing_helpers.hpp @@ -10,7 +10,7 @@ namespace routing template bool IsRoad(TTypes const & types) { - return CarModel::Instance().HasRoadType(types) || + return CarModel::AllLimitsInstance().HasRoadType(types) || PedestrianModel::AllLimitsInstance().HasRoadType(types) || BicycleModel::AllLimitsInstance().HasRoadType(types); } diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index 9447911d3e..378d8513ac 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -74,14 +74,16 @@ namespace integration return storage::CountryInfoReader::CreateCountryInfoReader(platform); } - unique_ptr CreateOsrmRouter(Index & index, - storage::CountryInfoGetter const & infoGetter) + unique_ptr CreateCarRouter(Index & index, + storage::CountryInfoGetter const & infoGetter) { - unique_ptr osrmRouter(new OsrmRouter(&index, [&infoGetter](m2::PointD const & pt) - { + auto const countryFileGetter = [&infoGetter](m2::PointD const & pt) { return infoGetter.GetRegionCountryId(pt); - })); - return osrmRouter; + }; + + auto carRouter = make_unique( + index, countryFileGetter, CreateCarAStarBidirectionalRouter(index, countryFileGetter)); + return carRouter; } unique_ptr CreateAStarRouter(Index & index, @@ -103,14 +105,13 @@ namespace integration public: OsrmRouterComponents(vector const & localFiles) : IRouterComponents(localFiles) - , m_osrmRouter(CreateOsrmRouter(m_featuresFetcher->GetIndex(), *m_infoGetter)) + , m_carRouter(CreateCarRouter(m_featuresFetcher->GetIndex(), *m_infoGetter)) { } - IRouter * GetRouter() const override { return m_osrmRouter.get(); } - + IRouter * GetRouter() const override { return m_carRouter.get(); } private: - unique_ptr m_osrmRouter; + unique_ptr m_carRouter; }; class PedestrianRouterComponents : public IRouterComponents diff --git a/routing/routing_integration_tests/routing_test_tools.hpp b/routing/routing_integration_tests/routing_test_tools.hpp index 4145b18bce..cefa6b314b 100644 --- a/routing/routing_integration_tests/routing_test_tools.hpp +++ b/routing/routing_integration_tests/routing_test_tools.hpp @@ -1,6 +1,6 @@ #pragma once -#include "routing/osrm_router.hpp" +#include "routing/car_router.hpp" #include "storage/country_info_getter.hpp" diff --git a/routing/routing_tests/osrm_router_test.cpp b/routing/routing_tests/osrm_router_test.cpp index c9ac49a9ae..d706cf78a3 100644 --- a/routing/routing_tests/osrm_router_test.cpp +++ b/routing/routing_tests/osrm_router_test.cpp @@ -1,6 +1,6 @@ #include "testing/testing.hpp" -#include "routing/osrm_router.hpp" +#include "routing/car_router.hpp" #include "indexer/features_offsets_table.hpp" #include "geometry/mercator.hpp" diff --git a/routing/vehicle_model.hpp b/routing/vehicle_model.hpp index bd550cc3a0..f0ff71c298 100644 --- a/routing/vehicle_model.hpp +++ b/routing/vehicle_model.hpp @@ -40,11 +40,10 @@ public: virtual bool IsRoad(FeatureType const & f) const = 0; }; -class IVehicleModelFactory +class VehicleModelFactory { public: - virtual ~IVehicleModelFactory() {} - + virtual ~VehicleModelFactory() {} /// @return Default vehicle model which corresponds for all countrines, /// but it may be non optimal for some countries virtual shared_ptr GetVehicleModel() const = 0; diff --git a/xcode/routing/routing.xcodeproj/project.pbxproj b/xcode/routing/routing.xcodeproj/project.pbxproj index d8bcd4f13a..49d99e28b4 100644 --- a/xcode/routing/routing.xcodeproj/project.pbxproj +++ b/xcode/routing/routing.xcodeproj/project.pbxproj @@ -21,6 +21,8 @@ 56555E561D897C90009D786D /* libalohalitics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6742ACE61C68A23B009CB89E /* libalohalitics.a */; }; 56555E581D897C9D009D786D /* liboauthcpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6742ACFA1C68A2D7009CB89E /* liboauthcpp.a */; }; 56555E591D897D28009D786D /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6742ACDE1C68A13F009CB89E /* testingmain.cpp */; }; + 56826BD01DB51C4E00807C62 /* car_router.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56826BCE1DB51C4E00807C62 /* car_router.cpp */; }; + 56826BD11DB51C4E00807C62 /* car_router.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56826BCF1DB51C4E00807C62 /* car_router.hpp */; }; 56EA2FD51D8FD8590083F01A /* routing_helpers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */; }; 56F0D7341D896A5300045886 /* libmap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67BD35DE1C69F198003AA26F /* libmap.a */; }; 56F0D7391D896A5300045886 /* libstorage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67BD35D41C69F155003AA26F /* libstorage.a */; }; @@ -133,8 +135,6 @@ 674F9BD61B0A580E00704FFA /* turns_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 674F9BC61B0A580E00704FFA /* turns_generator.cpp */; }; 674F9BD71B0A580E00704FFA /* turns_generator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 674F9BC71B0A580E00704FFA /* turns_generator.hpp */; }; 675344141A3F644F00A0A8C3 /* osrm_data_facade.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 675344061A3F644F00A0A8C3 /* osrm_data_facade.hpp */; }; - 675344171A3F644F00A0A8C3 /* osrm_router.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 675344091A3F644F00A0A8C3 /* osrm_router.cpp */; }; - 675344181A3F644F00A0A8C3 /* osrm_router.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6753440A1A3F644F00A0A8C3 /* osrm_router.hpp */; }; 675344191A3F644F00A0A8C3 /* osrm2feature_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6753440B1A3F644F00A0A8C3 /* osrm2feature_map.cpp */; }; 6753441A1A3F644F00A0A8C3 /* osrm2feature_map.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6753440C1A3F644F00A0A8C3 /* osrm2feature_map.hpp */; }; 6753441B1A3F644F00A0A8C3 /* route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6753440D1A3F644F00A0A8C3 /* route.cpp */; }; @@ -235,6 +235,8 @@ 56099E321CC9247E00A7772A /* directions_engine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = directions_engine.cpp; sourceTree = ""; }; 563B91C31CC4F1DC00222BC1 /* bicycle_model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bicycle_model.cpp; sourceTree = ""; }; 563B91C41CC4F1DC00222BC1 /* bicycle_model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = bicycle_model.hpp; sourceTree = ""; }; + 56826BCE1DB51C4E00807C62 /* car_router.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = car_router.cpp; sourceTree = ""; }; + 56826BCF1DB51C4E00807C62 /* car_router.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = car_router.hpp; sourceTree = ""; }; 56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_helpers.hpp; sourceTree = ""; }; 56F0D75F1D896A5300045886 /* routing_benchmarks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = routing_benchmarks.app; sourceTree = BUILT_PRODUCTS_DIR; }; 670B84BE1A9381D900CE4492 /* cross_routing_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cross_routing_context.cpp; sourceTree = ""; }; @@ -319,8 +321,6 @@ 674F9BC71B0A580E00704FFA /* turns_generator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = turns_generator.hpp; sourceTree = ""; }; 675343F81A3F640D00A0A8C3 /* librouting.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = librouting.a; sourceTree = BUILT_PRODUCTS_DIR; }; 675344061A3F644F00A0A8C3 /* osrm_data_facade.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = osrm_data_facade.hpp; sourceTree = ""; }; - 675344091A3F644F00A0A8C3 /* osrm_router.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osrm_router.cpp; sourceTree = ""; }; - 6753440A1A3F644F00A0A8C3 /* osrm_router.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = osrm_router.hpp; sourceTree = ""; }; 6753440B1A3F644F00A0A8C3 /* osrm2feature_map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osrm2feature_map.cpp; sourceTree = ""; }; 6753440C1A3F644F00A0A8C3 /* osrm2feature_map.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = osrm2feature_map.hpp; sourceTree = ""; }; 6753440D1A3F644F00A0A8C3 /* route.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = route.cpp; sourceTree = ""; }; @@ -633,6 +633,8 @@ 56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */, 56099E2C1CC8FBDA00A7772A /* osrm_path_segment_factory.cpp */, 56099E2D1CC8FBDA00A7772A /* osrm_path_segment_factory.hpp */, + 56826BCE1DB51C4E00807C62 /* car_router.cpp */, + 56826BCF1DB51C4E00807C62 /* car_router.hpp */, 56099E301CC9247E00A7772A /* bicycle_directions.cpp */, 56099E311CC9247E00A7772A /* bicycle_directions.hpp */, 56099E321CC9247E00A7772A /* directions_engine.cpp */, @@ -694,8 +696,6 @@ 67C7D4261B4EB48F00FE41AA /* turns_sound_settings.hpp */, 670C62111AC5A15700C38A8C /* routing_mapping.cpp */, 675344061A3F644F00A0A8C3 /* osrm_data_facade.hpp */, - 675344091A3F644F00A0A8C3 /* osrm_router.cpp */, - 6753440A1A3F644F00A0A8C3 /* osrm_router.hpp */, 6753440B1A3F644F00A0A8C3 /* osrm2feature_map.cpp */, 6753440C1A3F644F00A0A8C3 /* osrm2feature_map.hpp */, 6753440D1A3F644F00A0A8C3 /* route.cpp */, @@ -741,7 +741,6 @@ 56099E2A1CC7C97D00A7772A /* routing_result_graph.hpp in Headers */, A120B3481B4A7BE5002F3808 /* cross_mwm_router.hpp in Headers */, 674F9BD31B0A580E00704FFA /* road_graph_router.hpp in Headers */, - 675344181A3F644F00A0A8C3 /* osrm_router.hpp in Headers */, 675344141A3F644F00A0A8C3 /* osrm_data_facade.hpp in Headers */, 6753441F1A3F644F00A0A8C3 /* turns.hpp in Headers */, 6753441A1A3F644F00A0A8C3 /* osrm2feature_map.hpp in Headers */, @@ -770,6 +769,7 @@ 670D049F1B0B4A970013A7AC /* nearest_edge_finder.hpp in Headers */, A120B34F1B4A7C0A002F3808 /* online_absent_fetcher.hpp in Headers */, 674F9BD51B0A580E00704FFA /* road_graph.hpp in Headers */, + 56826BD11DB51C4E00807C62 /* car_router.hpp in Headers */, A120B3511B4A7C0A002F3808 /* routing_algorithm.hpp in Headers */, 675344211A3F644F00A0A8C3 /* vehicle_model.hpp in Headers */, 56099E2B1CC7C97D00A7772A /* turn_candidate.hpp in Headers */, @@ -991,6 +991,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 56826BD01DB51C4E00807C62 /* car_router.cpp in Sources */, 56099E2E1CC8FBDA00A7772A /* osrm_path_segment_factory.cpp in Sources */, 675344201A3F644F00A0A8C3 /* vehicle_model.cpp in Sources */, 56099E351CC9247E00A7772A /* directions_engine.cpp in Sources */, @@ -1004,7 +1005,6 @@ 675344191A3F644F00A0A8C3 /* osrm2feature_map.cpp in Sources */, 670D049E1B0B4A970013A7AC /* nearest_edge_finder.cpp in Sources */, 674F9BD61B0A580E00704FFA /* turns_generator.cpp in Sources */, - 675344171A3F644F00A0A8C3 /* osrm_router.cpp in Sources */, A17B42981BCFBD0E00A1EAE4 /* osrm_helpers.cpp in Sources */, 563B91C51CC4F1DC00222BC1 /* bicycle_model.cpp in Sources */, 674F9BD21B0A580E00704FFA /* road_graph_router.cpp in Sources */,