diff --git a/map/framework.cpp b/map/framework.cpp index c7287b8df3..3a6ebf2fd3 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -64,18 +64,24 @@ void Framework::OnLocationStatusChanged(location::TLocationStatus newStatus) void Framework::OnGpsUpdate(location::GpsInfo const & info) { - m_locationState.UpdateGps(info); + m2::RectD rect = MercatorBounds::MetresToXY( + info.m_longitude, info.m_latitude, info.m_horizontalAccuracy); + m2::PointD const center = rect.Center(); + + m_locationState.UpdateGps(rect); + if (m_centeringMode == ECenterAndScale) { - CenterAndScaleViewport(); - /// calling function twice to eliminate scaling - /// and rounding errors when positioning from 2-3 scale into 16-17 - CenterAndScaleViewport(); + int const upperScale = scales::GetUpperWorldScale(); + if (scales::GetScaleLevel(rect) > upperScale && IsEmptyModel(center)) + rect = scales::GetRectForLevel(upperScale, center, 1.0); + + ShowRectFixed(rect); + m_centeringMode = ECenterOnly; } else if (m_centeringMode == ECenterOnly) - SetViewportCenter(m_locationState.Position()); - Invalidate(); + SetViewportCenter(center); } void Framework::OnCompassUpdate(location::CompassInfo const & info) @@ -528,6 +534,7 @@ void Framework::DrawModel(shared_ptr const & e, bool Framework::IsEmptyModel(m2::PointD const & pt) { + // Correct, but slow version (check country polygon). /* string const fName = GetSearchEngine()->GetCountryFile(pt); if (fName.empty()) @@ -535,6 +542,8 @@ bool Framework::IsEmptyModel(m2::PointD const & pt) return !m_model.IsLoaded(fName); */ + + // Fast, but not strict-correct version (just check limit rect). return !m_model.IsCountryLoaded(pt); } @@ -608,7 +617,7 @@ void Framework::SetViewportCenter(m2::PointD const & pt) { m_navigator.CenterViewport(pt); Invalidate(); - } +} static int const theMetersFactor = 6; @@ -673,6 +682,7 @@ void Framework::EnterForeground() { } +/* /// @TODO refactor to accept point and min visible length void Framework::CenterAndScaleViewport() { @@ -702,6 +712,7 @@ void Framework::CenterAndScaleViewport() Invalidate(); } +*/ /// Show all model by it's world rect. void Framework::ShowAll() diff --git a/map/framework.hpp b/map/framework.hpp index a14bf1370e..e3d25cdad2 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -231,7 +231,7 @@ public: void EnterForeground(); /// @TODO refactor to accept point and min visible length - void CenterAndScaleViewport(); + //void CenterAndScaleViewport(); /// Show all model by it's world rect. void ShowAll(); diff --git a/map/location_state.cpp b/map/location_state.cpp index 7417883907..31238d0bd3 100644 --- a/map/location_state.cpp +++ b/map/location_state.cpp @@ -13,15 +13,14 @@ namespace location { } - void State::UpdateGps(GpsInfo const & info) + void State::UpdateGps(m2::RectD const & rect) { m_flags |= EGps; - m_positionMercator = m2::PointD(MercatorBounds::LonToX(info.m_longitude), - MercatorBounds::LatToY(info.m_latitude)); - m2::RectD const errorRectXY = - MercatorBounds::MetresToXY(info.m_longitude, info.m_latitude, - info.m_horizontalAccuracy); - m_errorRadiusMercator = sqrt(my::sq(errorRectXY.SizeX()) + my::sq(errorRectXY.SizeY())) / 4; + + m_positionMercator = rect.Center(); + + //m_errorRadiusMercator = sqrt(my::sq(rect.SizeX()) + my::sq(rect.SizeY())) / 2; + m_errorRadiusMercator = rect.SizeX() / 2.0; } void State::UpdateCompass(CompassInfo const & info) @@ -46,7 +45,7 @@ namespace location if ((m_flags & State::EGps) || (m_flags & State::ECompass)) { pxPosition = screen.GtoP(Position()); - pxErrorRadius = pxPosition.Length(screen.GtoP(Position() + m2::PointD(ErrorRadius(), 0))); + pxErrorRadius = pxPosition.Length(screen.GtoP(Position() + m2::PointD(m_errorRadiusMercator, 0.0))); pxPosition -= pxShift; diff --git a/map/location_state.hpp b/map/location_state.hpp index c79d70dc92..37fb5fb9b2 100644 --- a/map/location_state.hpp +++ b/map/location_state.hpp @@ -31,15 +31,14 @@ namespace location State(); - /// @return GPS error radius in mercator - double ErrorRadius() const { return m_errorRadiusMercator; } /// @return GPS center point in mercator m2::PointD Position() const { return m_positionMercator; } inline bool IsValidPosition() const { return ((m_flags & EGps) != 0); } + inline void TurnOff() { m_flags = ENone; } - void TurnOff() { m_flags = ENone; } - void UpdateGps(GpsInfo const & info); + /// @param[in] rect Bound rect for circle with position center and error radius. + void UpdateGps(m2::RectD const & rect); void UpdateCompass(CompassInfo const & info); void DrawMyPosition(DrawerYG & drawer, ScreenBase const & screen); diff --git a/platform/apple_location_service.mm b/platform/apple_location_service.mm index 5041fc371c..f8a2d4b459 100644 --- a/platform/apple_location_service.mm +++ b/platform/apple_location_service.mm @@ -104,7 +104,8 @@ public: - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { - LOG(LWARNING, ("locationManager failed with error", error.code, error.description)); + LOG(LWARNING, ("locationManager failed with error", error.code, [error.description UTF8String])); + if (error.code == kCLErrorDenied) m_service->OnDeniedError(); }