forked from organicmaps/organicmaps
moved location handling from Framework into location::State and added "follow compass" mode.
This commit is contained in:
parent
96c0658a68
commit
a164270834
15 changed files with 451 additions and 209 deletions
|
@ -35,9 +35,8 @@ size_t BasicTilingRenderPolicy::CalculateTileSize(size_t screenWidth, size_t scr
|
|||
}
|
||||
|
||||
BasicTilingRenderPolicy::BasicTilingRenderPolicy(Params const & p,
|
||||
bool doSupportRotation,
|
||||
bool doUseQueuedRenderer)
|
||||
: RenderPolicy(p, doSupportRotation, GetPlatform().CpuCores()),
|
||||
: RenderPolicy(p, true, GetPlatform().CpuCores()),
|
||||
m_DrawScale(0),
|
||||
m_IsEmptyModel(false),
|
||||
m_DoRecreateCoverage(false),
|
||||
|
@ -73,7 +72,7 @@ void BasicTilingRenderPolicy::DrawFrame(shared_ptr<PaintEvent> const & e, Screen
|
|||
if (doForceUpdate)
|
||||
m_CoverageGenerator->InvalidateTiles(GetInvalidRect(), scales::GetUpperWorldScale() + 1);
|
||||
|
||||
if (!m_IsNavigating)
|
||||
if (!m_IsNavigating && (!IsAnimating()))
|
||||
m_CoverageGenerator->AddCoverScreenTask(s,
|
||||
m_DoRecreateCoverage || (doForceUpdate && doIntersectInvalidRect));
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ protected:
|
|||
public:
|
||||
|
||||
BasicTilingRenderPolicy(Params const & p,
|
||||
bool doSupportRotation,
|
||||
bool doUseQueuedRenderer);
|
||||
|
||||
void BeginFrame(shared_ptr<PaintEvent> const & ev, ScreenBase const & s);
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "../indexer/feature.hpp"
|
||||
#include "../indexer/scales.hpp"
|
||||
|
||||
#include "../anim/controller.hpp"
|
||||
|
||||
#include "../gui/controller.hpp"
|
||||
|
||||
#include "../platform/settings.hpp"
|
||||
|
@ -63,89 +65,25 @@ void Framework::RemoveMap(string const & datFile)
|
|||
|
||||
void Framework::SkipLocationCentering()
|
||||
{
|
||||
m_centeringMode = ESkipLocationCentering;
|
||||
m_locationState.SkipLocationCentering();
|
||||
}
|
||||
|
||||
void Framework::OnLocationStatusChanged(location::TLocationStatus newStatus)
|
||||
{
|
||||
switch (newStatus)
|
||||
{
|
||||
case location::EStarted:
|
||||
case location::EFirstEvent:
|
||||
if (m_centeringMode != ESkipLocationCentering)
|
||||
{
|
||||
// set centering mode for the first location
|
||||
m_centeringMode = ECenterAndScale;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
m_centeringMode = EDoNothing;
|
||||
m_locationState.TurnOff();
|
||||
Invalidate();
|
||||
}
|
||||
m_locationState.OnLocationStatusChanged(newStatus);
|
||||
}
|
||||
|
||||
void Framework::OnGpsUpdate(location::GpsInfo const & info)
|
||||
{
|
||||
double lon = info.m_longitude;
|
||||
double lat = info.m_latitude;
|
||||
|
||||
#ifdef FIXED_LOCATION
|
||||
m_fixedPos.GetLon(lon);
|
||||
m_fixedPos.GetLat(lat);
|
||||
location::GpsInfo rInfo(info);
|
||||
m_fixedPos.GetLon(rInfo.m_longitude);
|
||||
m_fixedPos.GetLat(rInfo.m_latitude);
|
||||
#else
|
||||
location::GpsInfo const & rInfo = info;
|
||||
#endif
|
||||
|
||||
m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
|
||||
m2::PointD const center = rect.Center();
|
||||
|
||||
m_locationState.UpdateGps(rect);
|
||||
|
||||
switch (m_centeringMode)
|
||||
{
|
||||
case ECenterAndScale:
|
||||
{
|
||||
int const rectScale = scales::GetScaleLevel(rect);
|
||||
int setScale = -1;
|
||||
|
||||
// correct rect scale if country isn't downloaded
|
||||
int const upperScale = scales::GetUpperWorldScale();
|
||||
if (rectScale > upperScale && !IsCountryLoaded(center))
|
||||
{
|
||||
setScale = upperScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
// correct rect scale for best user experience
|
||||
int const bestScale = scales::GetUpperScale() - 1;
|
||||
if (rectScale > bestScale)
|
||||
setScale = bestScale;
|
||||
}
|
||||
|
||||
if (setScale != -1)
|
||||
rect = scales::GetRectForLevel(setScale, center, 1.0);
|
||||
|
||||
double a = m_navigator.Screen().GetAngle();
|
||||
double dx = rect.SizeX();
|
||||
double dy = rect.SizeY();
|
||||
|
||||
ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
|
||||
|
||||
m_centeringMode = ECenterOnly;
|
||||
break;
|
||||
}
|
||||
|
||||
case ECenterOnly:
|
||||
SetViewportCenter(center);
|
||||
break;
|
||||
|
||||
case ESkipLocationCentering:
|
||||
m_centeringMode = EDoNothing;
|
||||
break;
|
||||
|
||||
case EDoNothing:
|
||||
break;
|
||||
}
|
||||
m_locationState.OnGpsUpdate(rInfo);
|
||||
}
|
||||
|
||||
void Framework::OnCompassUpdate(location::CompassInfo const & info)
|
||||
|
@ -157,8 +95,7 @@ void Framework::OnCompassUpdate(location::CompassInfo const & info)
|
|||
location::CompassInfo const & rInfo = info;
|
||||
#endif
|
||||
|
||||
m_locationState.UpdateCompass(rInfo);
|
||||
Invalidate();
|
||||
m_locationState.OnCompassUpdate(rInfo);
|
||||
}
|
||||
|
||||
InformationDisplay & Framework::GetInformationDisplay()
|
||||
|
@ -193,7 +130,7 @@ Framework::Framework()
|
|||
#endif
|
||||
m_width(0),
|
||||
m_height(0),
|
||||
m_centeringMode(EDoNothing),
|
||||
m_locationState(this),
|
||||
m_informationDisplay(&m_storage),
|
||||
m_lowestMapVersion(-1),
|
||||
m_benchmarkEngine(0)
|
||||
|
@ -212,6 +149,8 @@ Framework::Framework()
|
|||
m_stringsBundle.SetDefaultString("try_again", "Try Again");
|
||||
m_stringsBundle.SetDefaultString("not_enough_free_space_on_sdcard", "Not enough space\nfor downloading");
|
||||
|
||||
m_animController.reset(new anim::Controller());
|
||||
|
||||
// Init GUI controller.
|
||||
m_guiController.reset(new gui::Controller());
|
||||
m_guiController->SetStringsBundle(&m_stringsBundle);
|
||||
|
@ -646,7 +585,7 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
|
|||
|
||||
m_informationDisplay.doDraw(pDrawer);
|
||||
|
||||
m_locationState.DrawMyPosition(*pDrawer, m_navigator);
|
||||
m_locationState.Draw(*pDrawer);
|
||||
|
||||
if (m_drawPlacemark)
|
||||
m_informationDisplay.drawPlacemark(pDrawer, "placemark", m_navigator.GtoP(m_placemark));
|
||||
|
@ -845,6 +784,8 @@ void Framework::StartDrag(DragEvent const & e)
|
|||
|
||||
if (m_renderPolicy)
|
||||
m_renderPolicy->StartDrag();
|
||||
|
||||
m_dragCompassProcessMode = m_locationState.CompassProcessMode();
|
||||
}
|
||||
|
||||
void Framework::DoDrag(DragEvent const & e)
|
||||
|
@ -856,6 +797,9 @@ void Framework::DoDrag(DragEvent const & e)
|
|||
#endif
|
||||
|
||||
m_navigator.DoDrag(pt, ElapsedSeconds());
|
||||
|
||||
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
|
||||
|
||||
if (m_renderPolicy)
|
||||
m_renderPolicy->DoDrag();
|
||||
}
|
||||
|
@ -870,12 +814,17 @@ void Framework::StopDrag(DragEvent const & e)
|
|||
m_informationDisplay.setDebugPoint(0, pt);
|
||||
#endif
|
||||
|
||||
if (m_centeringMode != EDoNothing)
|
||||
if (m_locationState.LocationProcessMode() != location::ELocationDoNothing)
|
||||
{
|
||||
// reset GPS centering mode if we have dragged far from current location
|
||||
ScreenBase const & s = m_navigator.Screen();
|
||||
if (GetPixelCenter().Length(s.GtoP(m_locationState.Position())) >= s.GetMinPixelRectSize() / 2.0)
|
||||
m_centeringMode = EDoNothing;
|
||||
{
|
||||
m_locationState.SetLocationProcessMode(location::ELocationDoNothing);
|
||||
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
|
||||
}
|
||||
else
|
||||
m_locationState.SetCompassProcessMode(m_dragCompassProcessMode);
|
||||
}
|
||||
|
||||
if (m_renderPolicy)
|
||||
|
@ -921,7 +870,7 @@ void Framework::Move(double azDir, double factor)
|
|||
//@{
|
||||
void Framework::ScaleToPoint(ScaleToPointEvent const & e)
|
||||
{
|
||||
m2::PointD const pt = (m_centeringMode == EDoNothing) ?
|
||||
m2::PointD const pt = (m_locationState.LocationProcessMode() == location::ELocationDoNothing) ?
|
||||
m_navigator.ShiftPoint(e.Pt()) : GetPixelCenter();
|
||||
|
||||
m_navigator.ScaleToPoint(pt, e.ScaleFactor(), ElapsedSeconds());
|
||||
|
@ -946,7 +895,7 @@ void Framework::CalcScalePoints(ScaleEvent const & e, m2::PointD & pt1, m2::Poin
|
|||
pt1 = m_navigator.ShiftPoint(e.Pt1());
|
||||
pt2 = m_navigator.ShiftPoint(e.Pt2());
|
||||
|
||||
if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly))
|
||||
if (m_locationState.HasPosition() && (m_locationState.LocationProcessMode() == location::ELocationCenterOnly))
|
||||
{
|
||||
m2::PointD const ptC = (pt1 + pt2) / 2;
|
||||
m2::PointD const ptDiff = GetPixelCenter() - ptC;
|
||||
|
@ -978,6 +927,12 @@ void Framework::DoScale(ScaleEvent const & e)
|
|||
m_navigator.DoScale(pt1, pt2, ElapsedSeconds());
|
||||
if (m_renderPolicy)
|
||||
m_renderPolicy->DoScale();
|
||||
|
||||
if (m_navigator.IsRotatingDuringScale() && (m_locationState.CompassProcessMode() == location::ECompassFollow))
|
||||
{
|
||||
m_locationState.StopAnimation();
|
||||
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
|
||||
}
|
||||
}
|
||||
|
||||
void Framework::StopScale(ScaleEvent const & e)
|
||||
|
@ -1031,23 +986,12 @@ void Framework::PrepareSearch(bool hasPt, double lat, double lon)
|
|||
|
||||
bool Framework::Search(search::SearchParams const & params)
|
||||
{
|
||||
#ifdef FIXED_LOCATION
|
||||
search::SearchParams rParams(params);
|
||||
if (params.m_validPos)
|
||||
{
|
||||
m_fixedPos.GetLat(rParams.m_lat);
|
||||
m_fixedPos.GetLon(rParams.m_lon);
|
||||
}
|
||||
#else
|
||||
search::SearchParams const & rParams = params;
|
||||
#endif
|
||||
|
||||
return GetSearchEngine()->Search(rParams, GetCurrentViewport());
|
||||
return GetSearchEngine()->Search(params, GetCurrentViewport());
|
||||
}
|
||||
|
||||
bool Framework::GetCurrentPosition(double & lat, double & lon) const
|
||||
{
|
||||
if (m_locationState.IsValidPosition())
|
||||
if (m_locationState.HasPosition())
|
||||
{
|
||||
m2::PointD const pos = m_locationState.Position();
|
||||
lat = MercatorBounds::YToLat(pos.y);
|
||||
|
@ -1081,12 +1025,6 @@ void Framework::GetDistanceAndAzimut(search::Result const & res,
|
|||
double lat, double lon, double north,
|
||||
string & distance, double & azimut)
|
||||
{
|
||||
#ifdef FIXED_LOCATION
|
||||
m_fixedPos.GetLat(lat);
|
||||
m_fixedPos.GetLon(lon);
|
||||
m_fixedPos.GetNorth(north);
|
||||
#endif
|
||||
|
||||
m2::PointD const center = res.GetFeatureCenter();
|
||||
|
||||
double const d = ms::DistanceOnEarth(lat, lon,
|
||||
|
@ -1152,22 +1090,6 @@ void Framework::SetRenderPolicy(RenderPolicy * renderPolicy)
|
|||
|
||||
if (m_benchmarkEngine)
|
||||
m_benchmarkEngine->Start();
|
||||
|
||||
/*
|
||||
if (m_hasPendingInvalidate)
|
||||
{
|
||||
m_renderPolicy->SetForceUpdate(m_doForceUpdate);
|
||||
m_renderPolicy->SetInvalidRect(m_invalidRect);
|
||||
m_renderPolicy->GetWindowHandle()->invalidate();
|
||||
m_hasPendingInvalidate = false;
|
||||
}
|
||||
|
||||
if (m_hasPendingShowRectFixed)
|
||||
{
|
||||
ShowRectFixed(m_pendingFixedRect);
|
||||
m_hasPendingShowRectFixed = false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1221,6 +1143,11 @@ gui::Controller * Framework::GetGuiController() const
|
|||
return m_guiController.get();
|
||||
}
|
||||
|
||||
anim::Controller * Framework::GetAnimController() const
|
||||
{
|
||||
return m_animController.get();
|
||||
}
|
||||
|
||||
bool Framework::SetViewportByURL(string const & url)
|
||||
{
|
||||
using namespace url_scheme;
|
||||
|
@ -1272,3 +1199,8 @@ void Framework::SaveFacebookDialogResult(int result)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Navigator & Framework::GetNavigator()
|
||||
{
|
||||
return m_navigator;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
namespace search { class Result; }
|
||||
namespace gui { class Controller; }
|
||||
namespace anim { class Controller; }
|
||||
|
||||
class CountryStatusDisplay;
|
||||
class BenchmarkEngine;
|
||||
|
@ -95,21 +96,14 @@ protected:
|
|||
int m_width;
|
||||
int m_height;
|
||||
|
||||
enum TGpsCenteringMode
|
||||
{
|
||||
EDoNothing,
|
||||
ECenterAndScale,
|
||||
ECenterOnly,
|
||||
ESkipLocationCentering
|
||||
};
|
||||
|
||||
TGpsCenteringMode m_centeringMode;
|
||||
location::State m_locationState;
|
||||
location::ECompassProcessMode m_dragCompassProcessMode;
|
||||
|
||||
//mutable threads::Mutex m_modelSyn;
|
||||
|
||||
storage::Storage m_storage;
|
||||
scoped_ptr<gui::Controller> m_guiController;
|
||||
scoped_ptr<anim::Controller> m_animController;
|
||||
InformationDisplay m_informationDisplay;
|
||||
|
||||
/// This function is called by m_storage to notify that country downloading is finished.
|
||||
|
@ -352,6 +346,8 @@ public:
|
|||
//@}
|
||||
|
||||
gui::Controller * GetGuiController() const;
|
||||
anim::Controller * GetAnimController() const;
|
||||
Navigator & GetNavigator();
|
||||
|
||||
/// Set the localized strings bundle
|
||||
inline void AddString(string const & name, string const & value)
|
||||
|
@ -371,6 +367,7 @@ public:
|
|||
void SaveFacebookDialogResult(int result);
|
||||
/// @}
|
||||
|
||||
private:
|
||||
/// Checks, whether the country which contains
|
||||
/// the specified point is loaded
|
||||
bool IsCountryLoaded(m2::PointD const & pt) const;
|
||||
};
|
||||
|
|
|
@ -1,82 +1,248 @@
|
|||
#include "location_state.hpp"
|
||||
#include "drawer_yg.hpp"
|
||||
#include "navigator.hpp"
|
||||
#include "framework.hpp"
|
||||
#include "rotate_screen_task.hpp"
|
||||
|
||||
#include "../anim/controller.hpp"
|
||||
|
||||
#include "../platform/location.hpp"
|
||||
#include "../platform/platform.hpp"
|
||||
|
||||
#include "../indexer/mercator.hpp"
|
||||
#include "../geometry/rect2d.hpp"
|
||||
|
||||
#include "../indexer/mercator.hpp"
|
||||
|
||||
namespace location
|
||||
{
|
||||
|
||||
State::State() : m_flags(ENone)
|
||||
State::State(Framework * fw)
|
||||
: m_hasPosition(false),
|
||||
m_hasCompass(false),
|
||||
m_locationProcessMode(ELocationDoNothing),
|
||||
m_compassProcessMode(ECompassDoNothing),
|
||||
m_fw(fw)
|
||||
{
|
||||
}
|
||||
|
||||
void State::UpdateGps(m2::RectD const & rect)
|
||||
bool State::HasPosition() const
|
||||
{
|
||||
m_flags |= EGps;
|
||||
|
||||
m_positionMercator = rect.Center();
|
||||
|
||||
//m_errorRadiusMercator = sqrt(my::sq(rect.SizeX()) + my::sq(rect.SizeY())) / 2;
|
||||
m_errorRadiusMercator = rect.SizeX() / 2.0;
|
||||
return m_hasPosition;
|
||||
}
|
||||
|
||||
void State::UpdateCompass(CompassInfo const & info)
|
||||
bool State::HasCompass() const
|
||||
{
|
||||
m_flags |= ECompass;
|
||||
return m_hasCompass;
|
||||
}
|
||||
|
||||
void State::TurnOff()
|
||||
{
|
||||
m_hasPosition = false;
|
||||
m_hasCompass = false;
|
||||
}
|
||||
|
||||
void State::SkipLocationCentering()
|
||||
{
|
||||
m_locationProcessMode = ELocationSkipCentering;
|
||||
}
|
||||
|
||||
ELocationProcessMode State::LocationProcessMode() const
|
||||
{
|
||||
return m_locationProcessMode;
|
||||
}
|
||||
|
||||
void State::SetLocationProcessMode(ELocationProcessMode mode)
|
||||
{
|
||||
m_locationProcessMode = mode;
|
||||
}
|
||||
|
||||
ECompassProcessMode State::CompassProcessMode() const
|
||||
{
|
||||
return m_compassProcessMode;
|
||||
}
|
||||
|
||||
void State::SetCompassProcessMode(ECompassProcessMode mode)
|
||||
{
|
||||
m_compassProcessMode = mode;
|
||||
}
|
||||
|
||||
void State::OnLocationStatusChanged(location::TLocationStatus newStatus)
|
||||
{
|
||||
switch (newStatus)
|
||||
{
|
||||
case location::EStarted:
|
||||
|
||||
if (m_locationProcessMode != ELocationSkipCentering)
|
||||
m_locationProcessMode = ELocationCenterAndScale;
|
||||
break;
|
||||
|
||||
case location::EFirstEvent:
|
||||
|
||||
if (m_locationProcessMode != ELocationSkipCentering)
|
||||
{
|
||||
// set centering mode for the first location
|
||||
m_locationProcessMode = ELocationCenterAndScale;
|
||||
m_compassProcessMode = ECompassFollow;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
m_locationProcessMode = ELocationDoNothing;
|
||||
TurnOff();
|
||||
}
|
||||
|
||||
m_fw->Invalidate();
|
||||
}
|
||||
|
||||
void State::OnGpsUpdate(location::GpsInfo const & info)
|
||||
{
|
||||
double lon = info.m_longitude;
|
||||
double lat = info.m_latitude;
|
||||
|
||||
m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
|
||||
m2::PointD const center = rect.Center();
|
||||
|
||||
m_hasPosition = true;
|
||||
m_position = center;
|
||||
m_errorRadius = rect.SizeX() / 2;
|
||||
|
||||
switch (m_locationProcessMode)
|
||||
{
|
||||
case ELocationCenterAndScale:
|
||||
{
|
||||
int const rectScale = scales::GetScaleLevel(rect);
|
||||
int setScale = -1;
|
||||
|
||||
// correct rect scale if country isn't downloaded
|
||||
int const upperScale = scales::GetUpperWorldScale();
|
||||
if (rectScale > upperScale && !m_fw->IsCountryLoaded(center))
|
||||
setScale = upperScale;
|
||||
else
|
||||
{
|
||||
// correct rect scale for best user experience
|
||||
int const bestScale = scales::GetUpperScale() - 1;
|
||||
if (rectScale > bestScale)
|
||||
setScale = bestScale;
|
||||
}
|
||||
|
||||
if (setScale != -1)
|
||||
rect = scales::GetRectForLevel(setScale, center, 1.0);
|
||||
|
||||
double a = m_fw->GetNavigator().Screen().GetAngle();
|
||||
double dx = rect.SizeX();
|
||||
double dy = rect.SizeY();
|
||||
|
||||
m_fw->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
|
||||
|
||||
m_locationProcessMode = ELocationCenterOnly;
|
||||
break;
|
||||
}
|
||||
|
||||
case ELocationCenterOnly:
|
||||
m_fw->SetViewportCenter(center);
|
||||
break;
|
||||
|
||||
case ELocationSkipCentering:
|
||||
m_locationProcessMode = ELocationDoNothing;
|
||||
break;
|
||||
|
||||
case ELocationDoNothing:
|
||||
break;
|
||||
}
|
||||
|
||||
m_fw->Invalidate();
|
||||
}
|
||||
|
||||
void State::OnCompassUpdate(location::CompassInfo const & info)
|
||||
{
|
||||
m_hasCompass = true;
|
||||
|
||||
m_headingRad = ((info.m_trueHeading >= 0.0) ? info.m_trueHeading : info.m_magneticHeading);
|
||||
// 0 angle is for North ("up"), but in our coordinates it's to the right.
|
||||
m_headingRad = m_headingRad - math::pi / 2.0;
|
||||
|
||||
// Avoid situations when offset between magnetic north and true north is too small
|
||||
static double const MIN_SECTOR_RAD = math::pi / 18.0;
|
||||
m_headingHalfSectorRad = (info.m_accuracy < MIN_SECTOR_RAD ? MIN_SECTOR_RAD : info.m_accuracy);
|
||||
m_headingHalfErrorRad = (info.m_accuracy < MIN_SECTOR_RAD ? MIN_SECTOR_RAD : info.m_accuracy);
|
||||
|
||||
if (m_compassProcessMode == ECompassFollow)
|
||||
FollowCompass();
|
||||
|
||||
m_fw->Invalidate();
|
||||
}
|
||||
|
||||
void State::DrawMyPosition(DrawerYG & drawer, Navigator const & nav)
|
||||
void State::Draw(DrawerYG & drawer)
|
||||
{
|
||||
if ((m_flags & State::EGps) || (m_flags & State::ECompass))
|
||||
if (m_hasPosition)
|
||||
{
|
||||
m2::PointD const pxPosition = nav.GtoP(Position());
|
||||
double const pxErrorRadius = pxPosition.Length(nav.GtoP(Position() + m2::PointD(m_errorRadiusMercator, 0.0)));
|
||||
m2::PointD const pxPosition = m_fw->GetNavigator().GtoP(Position());
|
||||
double const pxErrorRadius = pxPosition.Length(m_fw->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
|
||||
|
||||
if (m_flags & State::EGps)
|
||||
// my position symbol
|
||||
drawer.drawSymbol(pxPosition, "current-position", yg::EPosCenter, yg::maxDepth);
|
||||
|
||||
// my position circle
|
||||
drawer.screen()->fillSector(pxPosition, 0, 2.0 * math::pi, pxErrorRadius,
|
||||
yg::Color(0, 0, 255, 32),
|
||||
yg::maxDepth - 3);
|
||||
|
||||
// display compass only if position is available
|
||||
double orientationRadius = max(pxErrorRadius, 30.0 * drawer.VisualScale());
|
||||
|
||||
double screenAngle = m_fw->GetNavigator().Screen().GetAngle();
|
||||
|
||||
// 0 angle is for North ("up"), but in our coordinates it's to the right.
|
||||
double headingRad = m_headingRad - math::pi / 2.0;
|
||||
|
||||
if (m_hasCompass)
|
||||
{
|
||||
// my position symbol
|
||||
drawer.drawSymbol(pxPosition, "current-position", yg::EPosCenter, yg::maxDepth);
|
||||
drawer.screen()->drawSector(pxPosition,
|
||||
screenAngle + headingRad - m_headingHalfErrorRad,
|
||||
screenAngle + headingRad + m_headingHalfErrorRad,
|
||||
orientationRadius,
|
||||
yg::Color(255, 255, 255, 192),
|
||||
yg::maxDepth);
|
||||
|
||||
// my position circle
|
||||
drawer.screen()->fillSector(pxPosition, 0, 2.0 * math::pi, pxErrorRadius,
|
||||
yg::Color(0, 0, 255, 32),
|
||||
yg::maxDepth - 3);
|
||||
|
||||
// display compass only if position is available
|
||||
double orientationRadius = max(pxErrorRadius, 30.0 * drawer.VisualScale());
|
||||
|
||||
double screenAngle = nav.Screen().GetAngle();
|
||||
|
||||
if (m_flags & State::ECompass)
|
||||
{
|
||||
drawer.screen()->drawSector(pxPosition,
|
||||
screenAngle + m_headingRad - m_headingHalfSectorRad,
|
||||
screenAngle + m_headingRad + m_headingHalfSectorRad,
|
||||
orientationRadius,
|
||||
yg::Color(255, 255, 255, 192),
|
||||
yg::maxDepth);
|
||||
|
||||
drawer.screen()->fillSector(pxPosition,
|
||||
screenAngle + m_headingRad - m_headingHalfSectorRad,
|
||||
screenAngle + m_headingRad + m_headingHalfSectorRad,
|
||||
orientationRadius,
|
||||
yg::Color(255, 255, 255, 96),
|
||||
yg::maxDepth - 1);
|
||||
}
|
||||
drawer.screen()->fillSector(pxPosition,
|
||||
screenAngle + headingRad - m_headingHalfErrorRad,
|
||||
screenAngle + headingRad + m_headingHalfErrorRad,
|
||||
orientationRadius,
|
||||
yg::Color(255, 255, 255, 96),
|
||||
yg::maxDepth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void State::FollowCompass()
|
||||
{
|
||||
if (!m_fw->GetNavigator().DoSupportRotation())
|
||||
return;
|
||||
|
||||
StopAnimation();
|
||||
|
||||
double startAngle = m_fw->GetNavigator().Screen().GetAngle();
|
||||
double endAngle = -m_headingRad;
|
||||
|
||||
double period = 2 * math::pi;
|
||||
|
||||
startAngle -= floor(startAngle / period) * period;
|
||||
endAngle -= floor(endAngle / period) * period;
|
||||
|
||||
if (fabs(startAngle - endAngle) > 20.0 / 180.0 * math::pi)
|
||||
{
|
||||
if (fabs(startAngle - endAngle) > math::pi)
|
||||
startAngle -= 2 * math::pi;
|
||||
|
||||
m_rotateScreenTask.reset(new RotateScreenTask(m_fw,
|
||||
startAngle,
|
||||
endAngle,
|
||||
1));
|
||||
|
||||
m_fw->GetAnimController()->AddTask(m_rotateScreenTask);
|
||||
}
|
||||
}
|
||||
|
||||
void State::StopAnimation()
|
||||
{
|
||||
if (m_rotateScreenTask && !m_rotateScreenTask->IsFinished())
|
||||
m_rotateScreenTask->Finish();
|
||||
m_rotateScreenTask.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include "../platform/location.hpp"
|
||||
|
||||
#include "../geometry/point2d.hpp"
|
||||
#include "../geometry/rect2d.hpp"
|
||||
|
||||
#include "../std/shared_ptr.hpp"
|
||||
|
||||
class DrawerYG;
|
||||
class Navigator;
|
||||
class Framework;
|
||||
class RotateScreenTask;
|
||||
|
||||
namespace location
|
||||
{
|
||||
class GpsInfo;
|
||||
class CompassInfo;
|
||||
|
||||
enum ELocationProcessMode
|
||||
{
|
||||
ELocationDoNothing,
|
||||
ELocationCenterAndScale,
|
||||
ELocationCenterOnly,
|
||||
ELocationSkipCentering
|
||||
};
|
||||
|
||||
enum ECompassProcessMode
|
||||
{
|
||||
ECompassDoNothing,
|
||||
ECompassFollow
|
||||
};
|
||||
|
||||
// Class, that handles position and compass updates,
|
||||
// centers, scales and rotates map according to this updates
|
||||
// and draws location and compass marks.
|
||||
class State
|
||||
{
|
||||
double m_errorRadiusMercator;
|
||||
m2::PointD m_positionMercator;
|
||||
private:
|
||||
double m_errorRadius; //< error radius in mercator
|
||||
m2::PointD m_position; //< position in mercator
|
||||
|
||||
double m_headingRad;
|
||||
/// Angle to the left and to the right from the North
|
||||
double m_headingHalfSectorRad;
|
||||
double m_headingRad; //< direction in radians
|
||||
double m_headingHalfErrorRad; //< direction error in radians
|
||||
|
||||
int m_flags; ///< stores flags from SymbolType
|
||||
bool m_hasPosition;
|
||||
bool m_hasCompass;
|
||||
|
||||
ELocationProcessMode m_locationProcessMode;
|
||||
ECompassProcessMode m_compassProcessMode;
|
||||
|
||||
shared_ptr<RotateScreenTask> m_rotateScreenTask;
|
||||
|
||||
Framework * m_fw;
|
||||
|
||||
void FollowCompass();
|
||||
|
||||
public:
|
||||
enum SymbolType
|
||||
{
|
||||
ENone = 0x0,
|
||||
EGps = 0x1,
|
||||
ECompass = 0x2
|
||||
};
|
||||
|
||||
State();
|
||||
State(Framework * framework);
|
||||
|
||||
/// @return GPS center point in mercator
|
||||
m2::PointD Position() const { return m_positionMercator; }
|
||||
m2::PointD const & Position() const { return m_position; }
|
||||
|
||||
inline bool IsValidPosition() const { return ((m_flags & EGps) != 0); }
|
||||
inline void TurnOff() { m_flags = ENone; }
|
||||
bool HasPosition() const;
|
||||
bool HasCompass() const;
|
||||
|
||||
/// @param[in] rect Bound rect for circle with position center and error radius.
|
||||
void UpdateGps(m2::RectD const & rect);
|
||||
void UpdateCompass(CompassInfo const & info);
|
||||
ELocationProcessMode LocationProcessMode() const;
|
||||
void SetLocationProcessMode(ELocationProcessMode mode);
|
||||
|
||||
void DrawMyPosition(DrawerYG & drawer, Navigator const & nav);
|
||||
ECompassProcessMode CompassProcessMode() const;
|
||||
void SetCompassProcessMode(ECompassProcessMode mode);
|
||||
|
||||
operator int() const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
void TurnOff();
|
||||
|
||||
void Draw(DrawerYG & drawer);
|
||||
void StopAnimation();
|
||||
|
||||
/// @name GPS location updates routine.
|
||||
//@{
|
||||
void SkipLocationCentering();
|
||||
void OnLocationStatusChanged(location::TLocationStatus newStatus);
|
||||
void OnGpsUpdate(location::GpsInfo const & info);
|
||||
void OnCompassUpdate(location::CompassInfo const & info);
|
||||
//@}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -550,6 +550,11 @@ void Navigator::StopScale(m2::PointD const & pt1, m2::PointD const & pt2, double
|
|||
// m_StartScreen = m_Screen;
|
||||
}
|
||||
|
||||
bool Navigator::IsRotatingDuringScale() const
|
||||
{
|
||||
return m_IsRotatingDuringScale;
|
||||
}
|
||||
|
||||
void Navigator::Scale(double scale)
|
||||
{
|
||||
ScaleToPoint(m_Screen.PixelRect().Center(), scale, 0);
|
||||
|
@ -577,3 +582,7 @@ void Navigator::SetSupportRotation(bool flag)
|
|||
m_DoSupportRotation = flag;
|
||||
}
|
||||
|
||||
bool Navigator::DoSupportRotation() const
|
||||
{
|
||||
return m_DoSupportRotation;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
void DoScale(m2::PointD const & org, m2::PointD const & p1, m2::PointD const & p2);
|
||||
void DoScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec);
|
||||
void StopScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec);
|
||||
bool IsRotatingDuringScale() const;
|
||||
|
||||
void ScaleToPoint(m2::PointD const & pt, double factor, double timeInSec);
|
||||
|
||||
|
@ -54,8 +55,10 @@ public:
|
|||
|
||||
bool InAction() const;
|
||||
|
||||
/// enabling/disabling screen rotation handling
|
||||
void SetSupportRotation(bool flag);
|
||||
|
||||
/// checking, whether the navigator supports rotation
|
||||
bool DoSupportRotation() const;
|
||||
/// Our surface is a square which is bigger than visible screen area on the device,
|
||||
/// so we should take it into an account
|
||||
m2::PointD ShiftPoint(m2::PointD const & pt) const;
|
||||
|
|
|
@ -36,7 +36,8 @@ RenderPolicy::RenderPolicy(Params const & p,
|
|||
m_doSupportRotation(doSupportRotation),
|
||||
m_doForceUpdate(false),
|
||||
m_visualScale(p.m_visualScale),
|
||||
m_skinName(p.m_skinName)
|
||||
m_skinName(p.m_skinName),
|
||||
m_isAnimating(false)
|
||||
{
|
||||
LOG(LDEBUG, ("each BaseRule will hold up to", idCacheSize, "cached values"));
|
||||
drule::rules().ResizeCaches(idCacheSize);
|
||||
|
@ -208,6 +209,16 @@ void RenderPolicy::JoinBenchmarkFence(int fenceID)
|
|||
{
|
||||
}
|
||||
|
||||
void RenderPolicy::SetIsAnimating(bool flag)
|
||||
{
|
||||
m_isAnimating = flag;
|
||||
}
|
||||
|
||||
bool RenderPolicy::IsAnimating() const
|
||||
{
|
||||
return m_isAnimating;
|
||||
}
|
||||
|
||||
RenderPolicy * CreateRenderPolicy(RenderPolicy::Params const & params)
|
||||
{
|
||||
#ifdef OMIM_OS_ANDROID
|
||||
|
|
|
@ -54,6 +54,7 @@ protected:
|
|||
m2::AnyRectD m_invalidRect;
|
||||
double m_visualScale;
|
||||
string m_skinName;
|
||||
bool m_isAnimating;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -113,6 +114,9 @@ public:
|
|||
bool DoForceUpdate() const;
|
||||
void SetForceUpdate(bool flag);
|
||||
|
||||
void SetIsAnimating(bool flag);
|
||||
bool IsAnimating() const;
|
||||
|
||||
void SetInvalidRect(m2::AnyRectD const & glbRect);
|
||||
m2::AnyRectD const & GetInvalidRect() const;
|
||||
|
||||
|
|
57
map/rotate_screen_task.cpp
Normal file
57
map/rotate_screen_task.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "rotate_screen_task.hpp"
|
||||
#include "framework.hpp"
|
||||
|
||||
RotateScreenTask::RotateScreenTask(Framework * framework,
|
||||
double startAngle,
|
||||
double endAngle,
|
||||
double interval)
|
||||
: m_framework(framework),
|
||||
m_startAngle(startAngle),
|
||||
m_endAngle(endAngle),
|
||||
m_interval(interval)
|
||||
{
|
||||
m_startTime = 0;
|
||||
m_isFinished = false;
|
||||
}
|
||||
|
||||
void RotateScreenTask::OnStart(double ts)
|
||||
{
|
||||
m_startTime = ts;
|
||||
m_curAngle = m_startAngle;
|
||||
m_framework->GetRenderPolicy()->SetIsAnimating(true);
|
||||
}
|
||||
|
||||
void RotateScreenTask::OnStep(double ts)
|
||||
{
|
||||
if (ts - m_startTime > m_interval)
|
||||
{
|
||||
m_isFinished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsFinished())
|
||||
return;
|
||||
|
||||
double elapsedSec = ts - m_startTime;
|
||||
double angle = m_startAngle + (m_endAngle - m_startAngle) * elapsedSec / m_interval;
|
||||
|
||||
m_framework->GetNavigator().Rotate(angle - m_curAngle);
|
||||
m_curAngle = angle;
|
||||
|
||||
m_framework->GetRenderPolicy()->GetWindowHandle()->invalidate();
|
||||
}
|
||||
|
||||
void RotateScreenTask::OnEnd(double ts)
|
||||
{
|
||||
m_framework->GetRenderPolicy()->SetIsAnimating(false);
|
||||
}
|
||||
|
||||
bool RotateScreenTask::IsFinished()
|
||||
{
|
||||
return m_isFinished;
|
||||
}
|
||||
|
||||
void RotateScreenTask::Finish()
|
||||
{
|
||||
m_isFinished = true;
|
||||
}
|
34
map/rotate_screen_task.hpp
Normal file
34
map/rotate_screen_task.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "../anim/task.hpp"
|
||||
|
||||
class Framework;
|
||||
|
||||
class RotateScreenTask : public anim::Task
|
||||
{
|
||||
private:
|
||||
|
||||
Framework * m_framework;
|
||||
|
||||
double m_startTime;
|
||||
double m_startAngle;
|
||||
double m_endAngle;
|
||||
double m_interval;
|
||||
double m_curAngle;
|
||||
|
||||
bool m_isFinished;
|
||||
|
||||
public:
|
||||
|
||||
RotateScreenTask(Framework * framework,
|
||||
double startAngle,
|
||||
double endAngle,
|
||||
double interval);
|
||||
|
||||
void OnStart(double ts);
|
||||
void OnStep(double ts);
|
||||
void OnEnd(double ts);
|
||||
|
||||
bool IsFinished();
|
||||
void Finish();
|
||||
};
|
|
@ -227,8 +227,8 @@ void Ruler::update()
|
|||
double a = ang::AngleTo(pt0, pt1);
|
||||
m2::RectD r = MercatorBounds::RectByCenterXYAndSizeInMeters(glbPivot.x,
|
||||
glbPivot.y,
|
||||
cos(a) * m_metresDiff / 2,
|
||||
sin(a) * m_metresDiff / 2);
|
||||
abs(cos(a) * m_metresDiff / 2),
|
||||
abs(sin(a) * m_metresDiff / 2));
|
||||
|
||||
pt0 = m_screen.GtoP(m2::PointD(r.minX(), r.minY()));
|
||||
pt1 = m_screen.GtoP(m2::PointD(r.maxX(), r.maxY()));
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
TilingRenderPolicyMT::TilingRenderPolicyMT(Params const & p)
|
||||
: BasicTilingRenderPolicy(p,
|
||||
false,
|
||||
false)
|
||||
{
|
||||
yg::ResourceManager::Params rmp = p.m_rmParams;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
TilingRenderPolicyST::TilingRenderPolicyST(Params const & p)
|
||||
: BasicTilingRenderPolicy(p,
|
||||
true,
|
||||
true)
|
||||
{
|
||||
int cpuCores = GetPlatform().CpuCores();
|
||||
|
|
Loading…
Add table
Reference in a new issue