From d5c81818727ab2fcd7cc2f659f5c64e250b0955f Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Mon, 25 Apr 2016 16:23:09 +0300 Subject: [PATCH] [bicycle routing] Adding find by geometry funtionality. --- routing/bicycle_directions.cpp | 66 +++++++++++++++++++++++++++++++- routing/osrm_router.cpp | 5 +-- routing/road_graph_router.cpp | 1 + routing/routing.pro | 2 - routing/routing_result_graph.hpp | 10 ++++- routing/turns.hpp | 2 + routing/turns_generator.cpp | 3 +- 7 files changed, 79 insertions(+), 10 deletions(-) diff --git a/routing/bicycle_directions.cpp b/routing/bicycle_directions.cpp index 6d0abc7e36..f38f291eb9 100644 --- a/routing/bicycle_directions.cpp +++ b/routing/bicycle_directions.cpp @@ -1,4 +1,5 @@ #include "routing/bicycle_directions.hpp" +#include "routing/car_model.hpp" #include "routing/router_delegate.hpp" #include "routing/routing_result_graph.hpp" #include "routing/turns_generator.hpp" @@ -6,12 +7,73 @@ #include "geometry/point2d.hpp" #include "indexer/index.hpp" +#include "indexer/scales.hpp" namespace { using namespace routing; using namespace routing::turns; +/*! + * \brief The Point2Geometry class is responsable for looking for all adjacent to junctionPoint + * road network edges. Including the current edge. + */ +class Point2Geometry +{ + m2::PointD const m_junctionPoint, m_ingoingPoint; + TGeomTurnCandidate & m_candidates; /*!< All road feature angles crosses |m_junctionPoint| point. */ + +public: + Point2Geometry(m2::PointD const & junctionPoint, m2::PointD const & ingoingPoint, + TGeomTurnCandidate & candidates) + : m_junctionPoint(junctionPoint), m_ingoingPoint(ingoingPoint), m_candidates(candidates) + { + } + + void operator()(FeatureType const & ft) + { + if (!CarModel::Instance().IsRoad(ft)) + return; + ft.ParseGeometry(FeatureType::BEST_GEOMETRY); + size_t const count = ft.GetPointsCount(); + ASSERT_GREATER(count, 1, ()); + + for (size_t i = 0; i < count; ++i) + { + if (MercatorBounds::DistanceOnEarth(m_junctionPoint, ft.GetPoint(i)) < + kFeaturesNearTurnMeters) + { + if (i > 0) + m_candidates.push_back(my::RadToDeg( + PiMinusTwoVectorsAngle(m_junctionPoint, m_ingoingPoint, ft.GetPoint(i - 1)))); + if (i < count - 1) + m_candidates.push_back(my::RadToDeg( + PiMinusTwoVectorsAngle(m_junctionPoint, m_ingoingPoint, ft.GetPoint(i + 1)))); + return; + } + } + } + + DISALLOW_COPY_AND_MOVE(Point2Geometry); +}; + +/*! + * \brief GetTurnGeometry looks for all the road network edges near ingoingPoint. + * GetTurnGeometry fills candidates with angles of all the incoming and outgoint segments. + * \warning GetTurnGeometry should be used carefully because it's a time-consuming function. + * \warning In multilevel crossroads there is an insignificant possibility that candidates + * is filled with redundant segments of roads of different levels. + */ +void GetTurnGeometry(m2::PointD const & junctionPoint, m2::PointD const & ingoingPoint, + TGeomTurnCandidate & candidates, Index::MwmId const & mwmId, + Index const & index) +{ + Point2Geometry getter(junctionPoint, ingoingPoint, candidates); + index.ForEachInRectForMWM( + getter, MercatorBounds::RectByCenterXYAndSizeInMeters(junctionPoint, kFeaturesNearTurnMeters), + scales::GetUpperScale(), mwmId); +} + class AStarRoutingResultGraph : public IRoutingResultGraph { public: @@ -33,11 +95,11 @@ public: // TODO(bykoianko) Calculate correctly ingoingCount. For the time being // any juction with one outgoing way would not be considered as a turn. ingoingCount = 0; - // Find all roads near junctionPoint. + // Find all roads near junctionPoint using GetTurnGeometry() // } - virtual double GetShortestPathLength() const override { return m_routeLength; } + virtual double GetPathLength() const override { return m_routeLength; } virtual m2::PointD const & GetStartPoint() const override { diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 85990b50d2..392b188e71 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -75,7 +75,6 @@ public: turns::TTurnCandidates & outgoingTurns) const override { double const kReadCrossEpsilon = 1.0E-4; - double const kFeaturesNearTurnMeters = 3.0; // Geting nodes by geometry. vector geomNodes; @@ -143,7 +142,7 @@ public: m2::PointD const outgoingPoint = ft.GetPoint( seg.m_pointStart < seg.m_pointEnd ? seg.m_pointStart + 1 : seg.m_pointStart - 1); ASSERT_LESS(MercatorBounds::DistanceOnEarth(junctionPoint, ft.GetPoint(seg.m_pointStart)), - kFeaturesNearTurnMeters, ()); + turns::kFeaturesNearTurnMeters, ()); double const a = my::RadToDeg(PiMinusTwoVectorsAngle(junctionPoint, ingoingPoint, outgoingPoint)); @@ -157,7 +156,7 @@ public: }); } - virtual double GetShortestPathLength() const override { return m_rawResult.shortestPathLength; } + virtual double GetPathLength() const override { return m_rawResult.shortestPathLength; } virtual m2::PointD const & GetStartPoint() const override { return m_rawResult.sourceEdge.segmentPoint; diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 2f1edb152f..d61bf8de3d 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -252,6 +252,7 @@ void RoadGraphRouter::ReconstructRoute(vector && path, Route & route, Route::TTimes times; Route::TTurns turnsDir; + // @TODO(bykoianko) streetNames is not filled in Generate(). It should be done. Route::TStreets streetNames; if (m_directionsEngine) m_directionsEngine->Generate(*m_roadGraph, path, times, turnsDir, cancellable); diff --git a/routing/routing.pro b/routing/routing.pro index 1c35a14233..0c9579602b 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -48,7 +48,6 @@ SOURCES += \ turns_sound_settings.cpp \ turns_tts_text.cpp \ vehicle_model.cpp \ - turn_helpers.cpp HEADERS += \ async_router.hpp \ @@ -92,4 +91,3 @@ HEADERS += \ turns_sound_settings.hpp \ turns_tts_text.hpp \ vehicle_model.hpp \ - turn_helpers.hpp diff --git a/routing/routing_result_graph.hpp b/routing/routing_result_graph.hpp index 10f71d45f6..ef6f26269b 100644 --- a/routing/routing_result_graph.hpp +++ b/routing/routing_result_graph.hpp @@ -17,13 +17,21 @@ namespace turns class IRoutingResultGraph { public: + /// \returns information about all route segments. virtual TUnpackedPathSegments const & GetSegments() const = 0; + /// \brief for number of a |node|, point of the node (|junctionPoint|) and for a point + /// just before the node (|ingoingPoint|) it fills + /// * |ingoingCount| - number of incomming ways to |junctionPoint|. (|junctionPoint| >= 1) + /// * |outgoingTurns| - vector of ways to leave |junctionPoint|. virtual void GetPossibleTurns(TNodeId node, m2::PointD const & ingoingPoint, m2::PointD const & junctionPoint, size_t & ingoingCount, TTurnCandidates & outgoingTurns) const = 0; - virtual double GetShortestPathLength() const = 0; + /// \returns route length. + virtual double GetPathLength() const = 0; + /// \returns route start point. virtual m2::PointD const & GetStartPoint() const = 0; + /// \returns route finish point. virtual m2::PointD const & GetEndPoint() const = 0; virtual ~IRoutingResultGraph() = default; diff --git a/routing/turns.hpp b/routing/turns.hpp index ece7eb996c..03f21db4de 100644 --- a/routing/turns.hpp +++ b/routing/turns.hpp @@ -21,6 +21,8 @@ namespace turns using TGeomTurnCandidate = vector; +double constexpr kFeaturesNearTurnMeters = 3.0; + /*! * \warning The order of values below shall not be changed. * TurnRight(TurnLeft) must have a minimal value and diff --git a/routing/turns_generator.cpp b/routing/turns_generator.cpp index 2501d4e57a..6d12e1ecc3 100644 --- a/routing/turns_generator.cpp +++ b/routing/turns_generator.cpp @@ -21,7 +21,6 @@ using namespace routing::turns; namespace { -double const kFeaturesNearTurnMeters = 3.0; size_t constexpr kMaxPointsCount = 5; double constexpr kMinDistMeters = 200.; size_t constexpr kNotSoCloseMaxPointsCount = 3; @@ -261,7 +260,7 @@ IRouter::ResultCode MakeTurnAnnotation(turns::IRoutingResultGraph const & result { double estimatedTime = 0; - LOG(LDEBUG, ("Shortest th length:", result.GetShortestPathLength())); + LOG(LDEBUG, ("Shortest th length:", result.GetPathLength())); #ifdef DEBUG size_t lastIdx = 0;