mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
[drape] Base zoom level on distance to next turn
This commit changes the auto zoom level behaviour during navigation to be based off the distance to the next turn, rather than naively coupling it to the current speed. This will improve the navigation experience during driving. Signed-off-by: Leonardo Bishop <me@leonardobishop.net>
This commit is contained in:
@@ -441,12 +441,13 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
|
|||||||
MessagePriority::Normal);
|
MessagePriority::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
|
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||||
location::RouteMatchingInfo const & routeInfo)
|
location::RouteMatchingInfo const & routeInfo)
|
||||||
{
|
{
|
||||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
m_threadCommutator->PostMessage(
|
||||||
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo),
|
ThreadsCommutator::RenderThread,
|
||||||
MessagePriority::Normal);
|
make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
|
||||||
|
MessagePriority::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrapeEngine::SwitchMyPositionNextMode()
|
void DrapeEngine::SwitchMyPositionNextMode()
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ public:
|
|||||||
void UpdateMapStyle();
|
void UpdateMapStyle();
|
||||||
|
|
||||||
void SetCompassInfo(location::CompassInfo const & info);
|
void SetCompassInfo(location::CompassInfo const & info);
|
||||||
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo);
|
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||||
|
location::RouteMatchingInfo const & routeInfo);
|
||||||
void SwitchMyPositionNextMode();
|
void SwitchMyPositionNextMode();
|
||||||
void LoseLocation();
|
void LoseLocation();
|
||||||
void StopLocationFollow();
|
void StopLocationFollow();
|
||||||
|
|||||||
@@ -438,7 +438,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
ref_ptr<GpsInfoMessage> msg = message;
|
ref_ptr<GpsInfoMessage> msg = message;
|
||||||
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen());
|
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
|
||||||
|
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
|
||||||
|
|
||||||
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
|
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
|
||||||
if (info.HasDistanceFromBegin())
|
if (info.HasDistanceFromBegin())
|
||||||
|
|||||||
@@ -481,9 +481,12 @@ private:
|
|||||||
class GpsInfoMessage : public Message
|
class GpsInfoMessage : public Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo)
|
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||||
|
location::RouteMatchingInfo const & routeInfo)
|
||||||
: m_info(info)
|
: m_info(info)
|
||||||
, m_isNavigable(isNavigable)
|
, m_isNavigable(isNavigable)
|
||||||
|
, m_distToNextTurn(distToNextTurn)
|
||||||
|
, m_speedLimit(speedLimit)
|
||||||
, m_routeInfo(routeInfo)
|
, m_routeInfo(routeInfo)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -491,11 +494,15 @@ public:
|
|||||||
|
|
||||||
location::GpsInfo const & GetInfo() const { return m_info; }
|
location::GpsInfo const & GetInfo() const { return m_info; }
|
||||||
bool IsNavigable() const { return m_isNavigable; }
|
bool IsNavigable() const { return m_isNavigable; }
|
||||||
|
double const & GetSpeedLimit() const { return m_speedLimit; }
|
||||||
|
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
|
||||||
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
|
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location::GpsInfo const m_info;
|
location::GpsInfo const m_info;
|
||||||
bool const m_isNavigable;
|
bool const m_isNavigable;
|
||||||
|
double const m_distToNextTurn;
|
||||||
|
double const m_speedLimit;
|
||||||
location::RouteMatchingInfo const m_routeInfo;
|
location::RouteMatchingInfo const m_routeInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,32 +56,18 @@ inline double GetVisualScale()
|
|||||||
return df::VisualParams::Instance().GetVisualScale();
|
return df::VisualParams::Instance().GetVisualScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate zoom value in meters per pixel
|
double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
|
||||||
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
|
|
||||||
{
|
{
|
||||||
using TSpeedScale = std::pair<double, double>;
|
using TSpeedScale = std::pair<double, double>;
|
||||||
static std::array<TSpeedScale, 6> const scales3d = {{
|
static std::array<TSpeedScale, 2> const scales2d = {{
|
||||||
{20.0, 0.25},
|
{0.0, 1.75}, {77.0, 4.50} // 48 mph
|
||||||
{40.0, 0.75},
|
|
||||||
{60.0, 1.50},
|
|
||||||
{75.0, 2.50},
|
|
||||||
{85.0, 3.75},
|
|
||||||
{95.0, 6.00},
|
|
||||||
}};
|
}};
|
||||||
|
static std::array<TSpeedScale, 2> const scales3d = {{{0.0, 1.00}, {77.0, 4.50}}};
|
||||||
|
|
||||||
static std::array<TSpeedScale, 6> const scales2d = {{
|
std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
||||||
{20.0, 0.70},
|
|
||||||
{40.0, 1.25},
|
|
||||||
{60.0, 2.25},
|
|
||||||
{75.0, 3.00},
|
|
||||||
{85.0, 3.75},
|
|
||||||
{95.0, 6.00},
|
|
||||||
}};
|
|
||||||
|
|
||||||
std::array<TSpeedScale, 6> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
double constexpr kDefaultSpeedLimitKmpH = 50.0;
|
||||||
|
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
|
||||||
double constexpr kDefaultSpeedKmpH = 80.0;
|
|
||||||
double const speedKmpH = speedMpS >= 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedKmpH;
|
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (size_t sz = scales.size(); i < sz; ++i)
|
for (size_t sz = scales.size(); i < sz; ++i)
|
||||||
@@ -92,20 +78,64 @@ double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
|
|||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return scales.front().second / vs;
|
return scales.front().second / vs;
|
||||||
if (i == scales.size())
|
|
||||||
return scales.back().second / vs;
|
|
||||||
|
|
||||||
double const minSpeed = scales[i - 1].first;
|
return scales[i - 1].second / vs;
|
||||||
double const maxSpeed = scales[i].first;
|
}
|
||||||
double const k = (speedKmpH - minSpeed) / (maxSpeed - minSpeed);
|
|
||||||
|
|
||||||
double const minScale = scales[i - 1].second;
|
double CalculateZoomByDistanceToTurn(double distance, bool isPerspectiveAllowed)
|
||||||
double const maxScale = scales[i].second;
|
{
|
||||||
|
using TSpeedScale = std::pair<double, double>;
|
||||||
|
static std::array<TSpeedScale, 5> const scales2d = {{
|
||||||
|
{200, 0.50},
|
||||||
|
{500, 0.80}, // 0.3 mi
|
||||||
|
{1200, 1.75}, // 0.75 mi
|
||||||
|
{2000, 3.50}, // 1.2 mi
|
||||||
|
{5000, 6.50} // 3 mi
|
||||||
|
}};
|
||||||
|
static std::array<TSpeedScale, 5> const scales3d = {{
|
||||||
|
{200, 0.25},
|
||||||
|
{500, 0.60}, // 0.3 mi
|
||||||
|
{1200, 1.25}, // 0.75 mi
|
||||||
|
{2000, 3.50}, // 1.2 mi
|
||||||
|
{5000, 6.50} // 3 mi
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::array<TSpeedScale, 5> const & scale = isPerspectiveAllowed ? scales3d : scales2d;
|
||||||
|
|
||||||
|
double constexpr kDefaultDistance = 2000;
|
||||||
|
double const distanceM = distance >= 0 ? distance : kDefaultDistance;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (size_t sz = scale.size(); i < sz; ++i)
|
||||||
|
if (scale[i].first >= distanceM)
|
||||||
|
break;
|
||||||
|
|
||||||
|
double const vs = GetVisualScale();
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
return scale.front().second / vs;
|
||||||
|
if (i == scale.size())
|
||||||
|
return scale.back().second / vs;
|
||||||
|
|
||||||
|
double const minDist = scale[i - 1].first;
|
||||||
|
double const maxDist = scale[i].first;
|
||||||
|
double const k = (distanceM - minDist) / (maxDist - minDist);
|
||||||
|
|
||||||
|
double const minScale = scale[i - 1].second;
|
||||||
|
double const maxScale = scale[i].second;
|
||||||
double const zoom = minScale + k * (maxScale - minScale);
|
double const zoom = minScale + k * (maxScale - minScale);
|
||||||
|
|
||||||
return zoom / vs;
|
return zoom / vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double CalculateAutoZoom(double speedMpS, double distanceToTurn, bool isPerspectiveAllowed)
|
||||||
|
{
|
||||||
|
double const zoomByDistance = CalculateZoomByDistanceToTurn(distanceToTurn, isPerspectiveAllowed);
|
||||||
|
double const zoomByMaxSpeed = CalculateZoomByMaxSpeed(speedMpS, isPerspectiveAllowed);
|
||||||
|
|
||||||
|
return std::min(zoomByDistance, zoomByMaxSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
void ResetNotification(uint64_t & notifyId)
|
void ResetNotification(uint64_t & notifyId)
|
||||||
{
|
{
|
||||||
notifyId = DrapeNotifier::kInvalidId;
|
notifyId = DrapeNotifier::kInvalidId;
|
||||||
@@ -395,7 +425,8 @@ void MyPositionController::NextMode(ScreenBase const & screen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen)
|
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
|
||||||
|
double speedLimit, ScreenBase const & screen)
|
||||||
{
|
{
|
||||||
m2::PointD const oldPos = GetDrawablePosition();
|
m2::PointD const oldPos = GetDrawablePosition();
|
||||||
double const oldAzimut = GetDrawableAzimut();
|
double const oldAzimut = GetDrawableAzimut();
|
||||||
@@ -407,11 +438,13 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
|
|||||||
m_errorRadius = rect.SizeX() * 0.5;
|
m_errorRadius = rect.SizeX() * 0.5;
|
||||||
m_horizontalAccuracy = info.m_horizontalAccuracy;
|
m_horizontalAccuracy = info.m_horizontalAccuracy;
|
||||||
|
|
||||||
if (info.m_speed > 0.0)
|
if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
|
||||||
{
|
{
|
||||||
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
|
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
|
||||||
m_autoScale2d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, false /* isPerspectiveAllowed */);
|
m_autoScale2d =
|
||||||
m_autoScale3d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, true /* isPerspectiveAllowed */);
|
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
|
||||||
|
m_autoScale3d =
|
||||||
|
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ public:
|
|||||||
void OnEnterBackground();
|
void OnEnterBackground();
|
||||||
|
|
||||||
void OnCompassTapped();
|
void OnCompassTapped();
|
||||||
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen);
|
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
|
||||||
|
ScreenBase const & screen);
|
||||||
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
|
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
|
||||||
|
|
||||||
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
|
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
|
||||||
|
|||||||
@@ -1171,6 +1171,7 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
|
|||||||
{
|
{
|
||||||
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
|
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
|
||||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
|
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
|
||||||
|
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
||||||
routeMatchingInfo);
|
routeMatchingInfo);
|
||||||
m_gpsInfoCache.reset();
|
m_gpsInfoCache.reset();
|
||||||
}
|
}
|
||||||
@@ -1515,7 +1516,9 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
|
|||||||
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
|
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
|
||||||
|
|
||||||
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
|
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
|
||||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(), routeMatchingInfo);
|
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
|
||||||
|
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
||||||
|
routeMatchingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoutingManager::DeleteSavedRoutePoints()
|
void RoutingManager::DeleteSavedRoutePoints()
|
||||||
|
|||||||
@@ -363,6 +363,32 @@ void GetFullRoadName(RouteSegment::RoadNameInfo & road, std::string & name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double RoutingSession::GetDistanceToNextTurn() const
|
||||||
|
{
|
||||||
|
if (!m_route->IsValid())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
double distanceToTurnMeters = 0.;
|
||||||
|
turns::TurnItem turn;
|
||||||
|
m_route->GetNearestTurn(distanceToTurnMeters, turn);
|
||||||
|
return distanceToTurnMeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
double RoutingSession::GetCurrentSpeedLimit() const
|
||||||
|
{
|
||||||
|
if (!m_route->IsValid())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SpeedInUnits speedLimit;
|
||||||
|
m_route->GetCurrentSpeedLimit(speedLimit);
|
||||||
|
if (speedLimit.IsNumeric())
|
||||||
|
return measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
||||||
|
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
||||||
{
|
{
|
||||||
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
||||||
@@ -392,14 +418,7 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
|||||||
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
|
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
|
||||||
info.m_turn = turn.m_turn;
|
info.m_turn = turn.m_turn;
|
||||||
|
|
||||||
SpeedInUnits speedLimit;
|
info.m_speedLimitMps = GetCurrentSpeedLimit();
|
||||||
m_route->GetCurrentSpeedLimit(speedLimit);
|
|
||||||
if (speedLimit.IsNumeric())
|
|
||||||
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
|
||||||
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
|
||||||
info.m_speedLimitMps = 0;
|
|
||||||
else
|
|
||||||
info.m_speedLimitMps = -1.0;
|
|
||||||
|
|
||||||
// The turn after the next one.
|
// The turn after the next one.
|
||||||
if (m_routingSettings.m_showTurnAfterNext)
|
if (m_routingSettings.m_showTurnAfterNext)
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ public:
|
|||||||
|
|
||||||
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
|
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
|
||||||
void GetRouteFollowingInfo(FollowingInfo & info) const;
|
void GetRouteFollowingInfo(FollowingInfo & info) const;
|
||||||
|
double GetDistanceToNextTurn() const;
|
||||||
|
double GetCurrentSpeedLimit() const;
|
||||||
|
|
||||||
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
|
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
|
||||||
void MatchLocationToRoadGraph(location::GpsInfo & location);
|
void MatchLocationToRoadGraph(location::GpsInfo & location);
|
||||||
|
|||||||
Reference in New Issue
Block a user