diff --git a/geometry/screenbase.cpp b/geometry/screenbase.cpp index 20ec1eb0a4..c493fc4e8d 100644 --- a/geometry/screenbase.cpp +++ b/geometry/screenbase.cpp @@ -43,6 +43,7 @@ void ScreenBase::UpdateDependentParameters() m_GtoP = math::Inverse(m_PtoG); PtoG(m_PixelRect, m_ClipRect); + PtoG(m_PixelRect, m_GlobalRect); } void ScreenBase::SetFromRect(m2::RectD const & GlobalRect) diff --git a/map/navigator.cpp b/map/navigator.cpp index 60aa8b759b..0830d82407 100644 --- a/map/navigator.cpp +++ b/map/navigator.cpp @@ -74,6 +74,56 @@ bool Navigator::LoadState() void Navigator::OnSize(int x0, int y0, int w, int h) { m_Screen.OnSize(x0, y0, w, h); + + m2::RectD globalRect = m_Screen.GlobalRect(); + m2::RectD tmpRect = globalRect; + + /// trying to shift global rect a bit + + if (globalRect.minX() < MercatorBounds::minX) + { + globalRect.Offset(m2::PointD(MercatorBounds::minX - globalRect.minX(), 0)); + + if (globalRect.maxX() > MercatorBounds::maxX) + { + double k = (globalRect.Center().x - MercatorBounds::maxX) / (globalRect.Center().x - globalRect.maxX()); + globalRect.Scale(k); + } + } + + if (globalRect.maxX() > MercatorBounds::maxX) + { + globalRect.Offset(m2::PointD(MercatorBounds::maxX - globalRect.maxX(), 0)); + if (globalRect.minX() < MercatorBounds::minX) + { + double k = (globalRect.Center().x - MercatorBounds::minX) / (globalRect.Center().x - globalRect.minX()); + globalRect.Scale(k); + } + } + + if (globalRect.minY() < MercatorBounds::minY) + { + globalRect.Offset(m2::PointD(MercatorBounds::minY - globalRect.minY(), 0)); + + if (globalRect.maxY() > MercatorBounds::maxY) + { + double k = (globalRect.Center().y - MercatorBounds::maxY) / (globalRect.Center().y - globalRect.maxY()); + globalRect.Scale(k); + } + } + + if (globalRect.maxY() > MercatorBounds::maxY) + { + globalRect.Offset(m2::PointD(MercatorBounds::maxY - globalRect.maxY(), 0)); + if (globalRect.minY() < MercatorBounds::minY) + { + double k = (globalRect.Center().y - MercatorBounds::minY) / (globalRect.Center().y - globalRect.minY()); + globalRect.Scale(k); + } + } + + m_Screen.SetFromRect(globalRect); + if (!m_InAction) m_StartScreen.OnSize(x0, y0, w, h); } @@ -94,12 +144,28 @@ void Navigator::DoDrag(m2::PointD const & pt, double /*timeInSec*/) //m_Screen = m_StartScreen; ScreenBase tmp = m_StartScreen; - tmp.Move(pt.x - m_StartPt1.x, pt.y - m_StartPt1.y); + + int dx = pt.x - m_StartPt1.x; + int dy = pt.y - m_StartPt1.y; + + tmp.Move(dx, 0); + if (!CheckBorders(tmp)) + dx = 0; + tmp = m_StartScreen; + tmp.Move(0, dy); + if (!CheckBorders(tmp)) + dy = 0; + + tmp = m_StartScreen; + tmp.Move(dx, dy); if (CheckBorders(tmp)) + { + m_StartScreen = tmp; + m_StartPt1 = pt; + m_LastPt1 = pt; m_Screen = tmp; - - m_LastPt1 = pt; + } } void Navigator::StopDrag(m2::PointD const & pt, double timeInSec, bool /*animate*/) @@ -108,7 +174,7 @@ void Navigator::StopDrag(m2::PointD const & pt, double timeInSec, bool /*animate // Ensure that final pos is reached. DoDrag(pt, timeInSec); - ASSERT(m_LastPt1 == pt, (m_LastPt1.x, m_LastPt1.y, pt.x, pt.y)); + //ASSERT(m_LastPt1 == pt, (m_LastPt1.x, m_LastPt1.y, pt.x, pt.y)); //LOG(LDEBUG, (pt.x, pt.y)); m_InAction = false; // m_StartScreen = m_Screen; @@ -182,18 +248,17 @@ bool Navigator::CheckMinScale(ScreenBase const & screen) bool Navigator::CheckBorders(ScreenBase const & screen) { - m2::RectD WorldBoundsRect(MercatorBounds::minX, MercatorBounds::minY, - MercatorBounds::maxX, MercatorBounds::maxY); + m2::RectD ScreenBounds = screen.GlobalRect(); - m2::PointD ScreenCenter = screen.GlobalRect().Center(); - m2::PointD WorldCenter = WorldBoundsRect.Center(); + m2::RectD WorldBounds(MercatorBounds::minX, MercatorBounds::minY, + MercatorBounds::maxX, MercatorBounds::maxY); - return ScreenCenter.Length(WorldCenter) < WorldBoundsRect.LeftTop().Length(WorldCenter); + return ScreenBounds.IsRectInside(WorldBounds) || WorldBounds.IsRectInside(ScreenBounds); } bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, m2::PointD const & oldPt1, m2::PointD const & oldPt2, - bool skipMaxScaleCheck) + bool skipMaxScaleAndBordersCheck) { math::Matrix newM = m_Screen.GtoPMatrix() * ScreenBase::CalcTransform(oldPt1, oldPt2, newPt1, newPt2); @@ -201,15 +266,12 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, tmp.SetGtoPMatrix(newM); tmp.Rotate(tmp.GetAngle()); - if ((!skipMaxScaleCheck) && (!CheckMaxScale(tmp))) + if ((!skipMaxScaleAndBordersCheck) && (!CheckMaxScale(tmp) || !CheckBorders(tmp))) return false; if (!CheckMinScale(tmp)) return false; - if (!CheckBorders(tmp)) - return false; - m_Screen = tmp; return true; diff --git a/map/navigator.hpp b/map/navigator.hpp index deb3e9eb86..5ae1f16c59 100644 --- a/map/navigator.hpp +++ b/map/navigator.hpp @@ -94,7 +94,7 @@ private: // Device orientation EOrientation m_orientation; // Used in DoScale and ScaleByPoint - bool ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, m2::PointD const & oldPt1, m2::PointD const & oldPt2, bool skipMaxScaleCheck); + bool ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, m2::PointD const & oldPt1, m2::PointD const & oldPt2, bool skipMaxScaleAndBordersCheck); }; #include "../base/stop_mem_debug.hpp"