mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 21:13:35 +00:00
committed by
Konstantin Pastbin
parent
c9cbb64f12
commit
76ffc99abd
403
libs/map/routing_manager.hpp
Normal file
403
libs/map/routing_manager.hpp
Normal file
@@ -0,0 +1,403 @@
|
||||
#pragma once
|
||||
|
||||
#include "map/bookmark_manager.hpp"
|
||||
#include "map/extrapolation/extrapolator.hpp"
|
||||
#include "map/routing_mark.hpp"
|
||||
#include "map/transit/transit_display.hpp"
|
||||
#include "map/transit/transit_reader.hpp"
|
||||
|
||||
#include "routing/following_info.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/router.hpp"
|
||||
#include "routing/routing_callbacks.hpp"
|
||||
#include "routing/routing_session.hpp"
|
||||
#include "routing/speed_camera_manager.hpp"
|
||||
|
||||
#include "storage/storage_defines.hpp"
|
||||
|
||||
#include "drape_frontend/drape_engine_safe_ptr.hpp"
|
||||
|
||||
#include "drape/pointers.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
#include "geometry/point_with_altitude.hpp"
|
||||
|
||||
#include "base/thread_checker.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace storage
|
||||
{
|
||||
class CountryInfoGetter;
|
||||
}
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class NumMwmIds;
|
||||
}
|
||||
|
||||
class DataSource;
|
||||
|
||||
namespace power_management
|
||||
{
|
||||
class PowerManager;
|
||||
}
|
||||
|
||||
struct RoutePointInfo
|
||||
{
|
||||
std::string m_name;
|
||||
RouteMarkType m_markType = RouteMarkType::Start;
|
||||
size_t m_intermediateIndex = 0;
|
||||
bool m_isPassed = false;
|
||||
bool m_isMyPosition = false;
|
||||
m2::PointD m_position;
|
||||
};
|
||||
|
||||
class RoutingManager final
|
||||
{
|
||||
public:
|
||||
class Delegate
|
||||
{
|
||||
public:
|
||||
virtual void OnRouteFollow(routing::RouterType type) = 0;
|
||||
virtual void RegisterCountryFilesOnRoute(std::shared_ptr<routing::NumMwmIds> ptr) const = 0;
|
||||
|
||||
virtual ~Delegate() = default;
|
||||
};
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
using DataSourceGetterFn = std::function<DataSource &()>;
|
||||
using CountryInfoGetterFn = std::function<storage::CountryInfoGetter const &()>;
|
||||
using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;
|
||||
using GetStringsBundleFn = std::function<StringsBundle const &()>;
|
||||
using PowerManagerGetter = std::function<power_management::PowerManager const &()>;
|
||||
|
||||
template <typename DataSourceGetter, typename CountryInfoGetter,
|
||||
typename CountryParentNameGetter, typename StringsBundleGetter,
|
||||
typename PowerManagerGetter>
|
||||
Callbacks(DataSourceGetter && dataSourceGetter, CountryInfoGetter && countryInfoGetter,
|
||||
CountryParentNameGetter && countryParentNameGetter,
|
||||
StringsBundleGetter && stringsBundleGetter, PowerManagerGetter && powerManagerGetter)
|
||||
: m_dataSourceGetter(std::forward<DataSourceGetter>(dataSourceGetter))
|
||||
, m_countryInfoGetter(std::forward<CountryInfoGetter>(countryInfoGetter))
|
||||
, m_countryParentNameGetterFn(std::forward<CountryParentNameGetter>(countryParentNameGetter))
|
||||
, m_stringsBundleGetter(std::forward<StringsBundleGetter>(stringsBundleGetter))
|
||||
, m_powerManagerGetter(std::forward<PowerManagerGetter>(powerManagerGetter))
|
||||
{
|
||||
}
|
||||
|
||||
DataSourceGetterFn m_dataSourceGetter;
|
||||
CountryInfoGetterFn m_countryInfoGetter;
|
||||
CountryParentNameGetterFn m_countryParentNameGetterFn;
|
||||
GetStringsBundleFn m_stringsBundleGetter;
|
||||
PowerManagerGetter m_powerManagerGetter;
|
||||
};
|
||||
|
||||
using RouteBuildingCallback =
|
||||
std::function<void(routing::RouterResultCode, storage::CountriesSet const &)>;
|
||||
using RouteSpeedCamShowCallback =
|
||||
std::function<void(m2::PointD const &, double)>;
|
||||
using RouteSpeedCamsClearCallback =
|
||||
std::function<void()>;
|
||||
|
||||
using RouteStartBuildCallback = std::function<void(std::vector<RouteMarkData> const & points)>;
|
||||
|
||||
enum class Recommendation
|
||||
{
|
||||
// It can be recommended if location is found almost immediately
|
||||
// after restoring route points from file. In this case we can
|
||||
// rebuild route using "my position".
|
||||
RebuildAfterPointsLoading = 0,
|
||||
};
|
||||
using RouteRecommendCallback = std::function<void(Recommendation)>;
|
||||
|
||||
RoutingManager(Callbacks && callbacks, Delegate & delegate);
|
||||
|
||||
void SetBookmarkManager(BookmarkManager * bmManager);
|
||||
void SetTransitManager(TransitReadManager * transitManager);
|
||||
|
||||
routing::RoutingSession const & RoutingSession() const { return m_routingSession; }
|
||||
routing::RoutingSession & RoutingSession() { return m_routingSession; }
|
||||
void SetRouter(routing::RouterType type);
|
||||
routing::RouterType GetRouter() const { return m_currentRouterType; }
|
||||
bool IsRoutingActive() const { return m_routingSession.IsActive(); }
|
||||
bool IsRouteBuilt() const { return m_routingSession.IsBuilt(); }
|
||||
bool IsRouteBuilding() const { return m_routingSession.IsBuilding(); }
|
||||
bool IsRouteRebuildingOnly() const { return m_routingSession.IsRebuildingOnly(); }
|
||||
bool IsRouteFinished() const { return m_routingSession.IsFinished(); }
|
||||
bool IsOnRoute() const { return m_routingSession.IsOnRoute(); }
|
||||
bool IsRoutingFollowing() const { return m_routingSession.IsFollowing(); }
|
||||
bool IsRouteValid() const { return m_routingSession.IsRouteValid(); }
|
||||
void BuildRoute(uint32_t timeoutSec = routing::RouterDelegate::kNoTimeout);
|
||||
void SetUserCurrentPosition(m2::PointD const & position);
|
||||
void ResetRoutingSession() { m_routingSession.Reset(); }
|
||||
// FollowRoute has a bug where the router follows the route even if the method hads't been called.
|
||||
// This method was added because we do not want to break the behaviour that is familiar to our
|
||||
// users.
|
||||
bool DisableFollowMode();
|
||||
kml::TrackId SaveRoute();
|
||||
|
||||
void SetRouteBuildingListener(RouteBuildingCallback const & buildingCallback)
|
||||
{
|
||||
m_routingBuildingCallback = buildingCallback;
|
||||
}
|
||||
|
||||
void SetRouteSpeedCamShowListener(RouteSpeedCamShowCallback const & speedCamShowCallback)
|
||||
{
|
||||
m_routeSpeedCamShowCallback = speedCamShowCallback;
|
||||
}
|
||||
|
||||
void SetRouteSpeedCamsClearListener(RouteSpeedCamsClearCallback const & speedCamsClearCallback)
|
||||
{
|
||||
m_routeSpeedCamsClearCallback = speedCamsClearCallback;
|
||||
}
|
||||
|
||||
/// See warning above.
|
||||
void SetRouteProgressListener(routing::ProgressCallback const & progressCallback)
|
||||
{
|
||||
m_routingSession.SetProgressCallback(progressCallback);
|
||||
}
|
||||
void SetRouteRecommendationListener(RouteRecommendCallback const & recommendCallback)
|
||||
{
|
||||
m_routeRecommendCallback = recommendCallback;
|
||||
}
|
||||
void FollowRoute();
|
||||
void CloseRouting(bool removeRoutePoints);
|
||||
void GetRouteFollowingInfo(routing::FollowingInfo & info) const
|
||||
{
|
||||
m_routingSession.GetRouteFollowingInfo(info);
|
||||
}
|
||||
|
||||
TransitRouteInfo GetTransitRouteInfo() const;
|
||||
|
||||
m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); }
|
||||
/// Returns the most situable router engine type.
|
||||
routing::RouterType GetBestRouter(m2::PointD const & startPoint,
|
||||
m2::PointD const & finalPoint) const;
|
||||
routing::RouterType GetLastUsedRouter() const;
|
||||
void SetLastUsedRouter(routing::RouterType type);
|
||||
// Sound notifications for turn instructions.
|
||||
void EnableTurnNotifications(bool enable) { m_routingSession.EnableTurnNotifications(enable); }
|
||||
bool AreTurnNotificationsEnabled() const
|
||||
{
|
||||
return m_routingSession.AreTurnNotificationsEnabled();
|
||||
}
|
||||
/// \brief Sets a locale for TTS.
|
||||
/// \param locale is a string with locale code. For example "en", "ru", "zh-Hant" and so on.
|
||||
/// \note See sound/tts/languages.txt for the full list of available locales.
|
||||
void SetTurnNotificationsLocale(std::string const & locale)
|
||||
{
|
||||
m_routingSession.SetTurnNotificationsLocale(locale);
|
||||
}
|
||||
/// @return current TTS locale. For example "en", "ru", "zh-Hant" and so on.
|
||||
/// In case of error returns an empty string.
|
||||
/// \note The method returns correct locale after SetTurnNotificationsLocale has been called.
|
||||
/// If not, it returns an empty string.
|
||||
std::string GetTurnNotificationsLocale() const
|
||||
{
|
||||
return m_routingSession.GetTurnNotificationsLocale();
|
||||
}
|
||||
// @return polyline of the route.
|
||||
routing::FollowedPolyline const & GetRoutePolyline() const
|
||||
{
|
||||
return m_routingSession.GetRouteForTests()->GetFollowedPolyline();
|
||||
}
|
||||
// @return generated turns on the route.
|
||||
std::vector<routing::turns::TurnItem> GetTurnsOnRouteForTests() const
|
||||
{
|
||||
std::vector<routing::turns::TurnItem> turns;
|
||||
m_routingSession.GetRouteForTests()->GetTurnsForTesting(turns);
|
||||
return turns;
|
||||
}
|
||||
|
||||
Callbacks & GetCallbacksForTests() { return m_callbacks; }
|
||||
/// \brief Adds to @param notifications strings - notifications, which are ready to be
|
||||
/// pronounced to end user right now.
|
||||
/// Adds notifications about turns and speed camera on the road.
|
||||
/// \param announceStreets is true when TTS street names should be pronounced
|
||||
///
|
||||
/// \note Current notifications will be deleted after call and second call
|
||||
/// will not return previous data, only newer.
|
||||
void GenerateNotifications(std::vector<std::string> & notifications, bool announceStreets);
|
||||
|
||||
void AddRoutePoint(RouteMarkData && markData, bool reorderIntermediatePoints = true);
|
||||
void ContinueRouteToPoint(RouteMarkData && markData);
|
||||
std::vector<RouteMarkData> GetRoutePoints() const;
|
||||
size_t GetRoutePointsCount() const;
|
||||
void RemoveRoutePoint(RouteMarkType type, size_t intermediateIndex = 0);
|
||||
void RemoveRoutePoints();
|
||||
void RemoveIntermediateRoutePoints();
|
||||
void MoveRoutePoint(size_t currentIndex, size_t targetIndex);
|
||||
void MoveRoutePoint(RouteMarkType currentType, size_t currentIntermediateIndex,
|
||||
RouteMarkType targetType, size_t targetIntermediateIndex);
|
||||
void HideRoutePoint(RouteMarkType type, size_t intermediateIndex = 0);
|
||||
bool CouldAddIntermediatePoint() const;
|
||||
bool IsMyPosition(RouteMarkType type, size_t intermediateIndex = 0);
|
||||
|
||||
void SetRouterImpl(routing::RouterType type);
|
||||
void RemoveRoute(bool deactivateFollowing);
|
||||
|
||||
void CheckLocationForRouting(location::GpsInfo const & info);
|
||||
void CallRouteBuilded(routing::RouterResultCode code,
|
||||
storage::CountriesSet const & absentCountries);
|
||||
void OnBuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
|
||||
void OnRebuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
|
||||
void OnNeedMoreMaps(uint64_t routeId, storage::CountriesSet const & absentCountries);
|
||||
void OnRemoveRoute(routing::RouterResultCode code);
|
||||
void OnRoutePointPassed(RouteMarkType type, size_t intermediateIndex);
|
||||
void OnLocationUpdate(location::GpsInfo const & info);
|
||||
|
||||
routing::SpeedCameraManager & GetSpeedCamManager() { return m_routingSession.GetSpeedCamManager(); }
|
||||
bool IsSpeedCamLimitExceeded() const;
|
||||
|
||||
void SetTurnNotificationsUnits(measurement_utils::Units const units)
|
||||
{
|
||||
m_routingSession.SetTurnNotificationsUnits(units);
|
||||
}
|
||||
void SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAllowed);
|
||||
/// \returns true if altitude information along |m_route| is available and
|
||||
/// false otherwise.
|
||||
bool HasRouteAltitude() const;
|
||||
|
||||
struct DistanceAltitude
|
||||
{
|
||||
std::vector<double> m_distances;
|
||||
geometry::Altitudes m_altitudes;
|
||||
|
||||
size_t GetSize() const
|
||||
{
|
||||
ASSERT_EQUAL(m_distances.size(), m_altitudes.size(), ());
|
||||
return m_distances.size();
|
||||
}
|
||||
|
||||
// Default altitudeDeviation ~ sqrt(2).
|
||||
void Simplify(double altitudeDeviation = 1.415);
|
||||
|
||||
/// \brief Generates 4 bytes per point image (RGBA) and put the data to |imageRGBAData|.
|
||||
/// \param width is width of chart shall be generated in pixels.
|
||||
/// \param height is height of chart shall be generated in pixels.
|
||||
/// \param imageRGBAData is bits of result image in RGBA.
|
||||
/// \returns If there is valid route info and the chart was generated returns true
|
||||
/// and false otherwise. If the method returns true it is guaranteed that the size of
|
||||
/// |imageRGBAData| is not zero.
|
||||
bool GenerateRouteAltitudeChart(uint32_t width, uint32_t height, std::vector<uint8_t> & imageRGBAData) const;
|
||||
|
||||
/// \param totalAscent is total ascent of the route in meters.
|
||||
/// \param totalDescent is total descent of the route in meters.
|
||||
void CalculateAscentDescent(uint32_t & totalAscentM, uint32_t & totalDescentM) const;
|
||||
|
||||
friend std::string DebugPrint(DistanceAltitude const & da);
|
||||
};
|
||||
|
||||
/// \brief Fills altitude of current route points and distance in meters form the beginning
|
||||
/// of the route point based on the route in RoutingSession.
|
||||
/// \return False if current route is invalid or doesn't have altitudes.
|
||||
bool GetRouteAltitudesAndDistancesM(DistanceAltitude & da) const;
|
||||
|
||||
uint32_t OpenRoutePointsTransaction();
|
||||
void ApplyRoutePointsTransaction(uint32_t transactionId);
|
||||
void CancelRoutePointsTransaction(uint32_t transactionId);
|
||||
static uint32_t InvalidRoutePointsTransactionId();
|
||||
|
||||
/// \returns true if there are route points saved in file and false otherwise.
|
||||
bool HasSavedRoutePoints() const;
|
||||
/// \brief It loads road points from file and delete file after loading.
|
||||
/// The result of the loading will be sent via SafeCallback.
|
||||
using LoadRouteHandler = platform::SafeCallback<void(bool success)>;
|
||||
void LoadRoutePoints(LoadRouteHandler const & handler);
|
||||
/// \brief It saves route points to file.
|
||||
void SaveRoutePoints();
|
||||
/// \brief It deletes file with saved route points if it exists.
|
||||
void DeleteSavedRoutePoints();
|
||||
|
||||
void UpdatePreviewMode();
|
||||
void CancelPreviewMode();
|
||||
|
||||
routing::RouterType GetCurrentRouterType() const { return m_currentRouterType; }
|
||||
|
||||
private:
|
||||
/// \returns true if the route has warnings.
|
||||
bool InsertRoute(routing::Route const & route);
|
||||
|
||||
struct RoadInfo
|
||||
{
|
||||
RoadInfo() = default;
|
||||
|
||||
explicit RoadInfo(m2::PointD const & pt, FeatureID const & featureId)
|
||||
: m_startPoint(pt)
|
||||
, m_featureId(featureId)
|
||||
{}
|
||||
|
||||
m2::PointD m_startPoint;
|
||||
FeatureID m_featureId;
|
||||
double m_distance = 0.0;
|
||||
};
|
||||
using RoadWarningsCollection = std::map<routing::RoutingOptions::Road, std::vector<RoadInfo>>;
|
||||
|
||||
using GetMwmIdFn = std::function<MwmSet::MwmId (routing::NumMwmId numMwmId)>;
|
||||
void CollectRoadWarnings(std::vector<routing::RouteSegment> const & segments, m2::PointD const & startPt,
|
||||
double baseDistance, GetMwmIdFn const & getMwmIdFn, RoadWarningsCollection & roadWarnings);
|
||||
void CreateRoadWarningMarks(RoadWarningsCollection && roadWarnings);
|
||||
|
||||
/// \returns false if the location could not be matched to the route and should be matched to the
|
||||
/// road graph. Otherwise returns true.
|
||||
void MatchLocationToRoute(location::GpsInfo & info,
|
||||
location::RouteMatchingInfo & routeMatchingInfo);
|
||||
location::RouteMatchingInfo GetRouteMatchingInfo(location::GpsInfo & info);
|
||||
uint32_t GenerateRoutePointsTransactionId() const;
|
||||
|
||||
void SetPointsFollowingMode(bool enabled);
|
||||
|
||||
void ReorderIntermediatePoints();
|
||||
|
||||
m2::RectD ShowPreviewSegments(std::vector<RouteMarkData> const & routePoints);
|
||||
void HidePreviewSegments();
|
||||
|
||||
void SetSubroutesVisibility(bool visible);
|
||||
|
||||
void CancelRecommendation(Recommendation recommendation);
|
||||
|
||||
std::vector<RouteMarkData> GetRoutePointsToSave() const;
|
||||
|
||||
void OnExtrapolatedLocationUpdate(location::GpsInfo const & info);
|
||||
|
||||
RouteBuildingCallback m_routingBuildingCallback;
|
||||
RouteSpeedCamShowCallback m_routeSpeedCamShowCallback;
|
||||
RouteSpeedCamsClearCallback m_routeSpeedCamsClearCallback;
|
||||
RouteRecommendCallback m_routeRecommendCallback;
|
||||
Callbacks m_callbacks;
|
||||
df::DrapeEngineSafePtr m_drapeEngine;
|
||||
routing::RouterType m_currentRouterType = routing::RouterType::Count;
|
||||
bool m_loadAltitudes = false;
|
||||
routing::RoutingSession m_routingSession;
|
||||
Delegate & m_delegate;
|
||||
|
||||
BookmarkManager * m_bmManager = nullptr;
|
||||
extrapolation::Extrapolator m_extrapolator;
|
||||
|
||||
std::vector<dp::DrapeID> m_drapeSubroutes;
|
||||
mutable std::mutex m_drapeSubroutesMutex;
|
||||
|
||||
std::unique_ptr<location::GpsInfo> m_gpsInfoCache;
|
||||
|
||||
TransitRouteInfo m_transitRouteInfo;
|
||||
|
||||
struct RoutePointsTransaction
|
||||
{
|
||||
std::vector<RouteMarkData> m_routeMarks;
|
||||
};
|
||||
std::map<uint32_t, RoutePointsTransaction> m_routePointsTransactions;
|
||||
std::chrono::steady_clock::time_point m_loadRoutePointsTimestamp;
|
||||
std::map<std::string, m2::PointF> m_transitSymbolSizes;
|
||||
|
||||
TransitReadManager * m_transitReadManager = nullptr;
|
||||
|
||||
DECLARE_THREAD_CHECKER(m_threadChecker);
|
||||
};
|
||||
Reference in New Issue
Block a user