int GetTileScaleBase(m2::RectD const & r) { double const sz = max(r.SizeX(), r.SizeY()); return max(1, my::rounds(log((MercatorBounds::maxX - MercatorBounds::minX) / sz) / log(2.0))); }
static bool empty_scr_rect(m2::RectD const & r) { double const eps = 1.0; return (r.SizeX() < eps && r.SizeY() < eps); }
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen) { m2::PointD const oldPos = GetDrawablePosition(); double const oldAzimut = GetDrawableAzimut(); m2::RectD const rect = MercatorBounds::MetresToXY(info.m_longitude, info.m_latitude, info.m_horizontalAccuracy); // Use FromLatLon instead of rect.Center() since in case of large info.m_horizontalAccuracy // there is significant difference between the real location and the estimated one. m_position = MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude); m_errorRadius = rect.SizeX() * 0.5; bool const hasBearing = info.HasBearing(); if ((isNavigable && hasBearing) || (!isNavigable && hasBearing && info.HasSpeed() && info.m_speed > kMinSpeedThresholdMps)) { SetDirection(my::DegToRad(info.m_bearing)); m_lastGPSBearing.Reset(); } if (m_listener) m_listener->PositionChanged(Position()); if (m_isPositionAssigned && (!AlmostCurrentPosition(oldPos) || !AlmostCurrentAzimut(oldAzimut))) { CreateAnim(oldPos, oldAzimut, screen); m_isDirtyViewport = true; } if (m_notFollowAfterPending && m_mode == location::PendingPosition) { ChangeMode(location::NotFollow); if (m_isInRouting) m_routingNotFollowTimer.Reset(); m_notFollowAfterPending = false; } else if (!m_isPositionAssigned) { ChangeMode(m_isFirstLaunch ? location::Follow : m_desiredInitMode); if (!m_isFirstLaunch || !AnimationSystem::Instance().AnimationExists(Animation::MapPlane)) { if (m_mode == location::Follow) ChangeModelView(m_position, kDoNotChangeZoom); else if (m_mode == location::FollowAndRotate) ChangeModelView(m_position, m_drawDirection, m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), kDoNotChangeZoom); } } else if (m_mode == location::PendingPosition || m_mode == location::NotFollowNoPosition) { if (m_isInRouting) { ChangeMode(location::FollowAndRotate); UpdateViewport(kMaxScaleZoomLevel); } else { ChangeMode(location::Follow); if (!m_isFirstLaunch) { if (GetZoomLevel(screen, m_position, m_errorRadius) <= kMaxScaleZoomLevel) { m2::PointD const size(m_errorRadius, m_errorRadius); ChangeModelView(m2::RectD(m_position - size, m_position + size)); } else { ChangeModelView(m_position, kMaxScaleZoomLevel); } } else { if (!AnimationSystem::Instance().AnimationExists(Animation::MapPlane)) ChangeModelView(m_position, kDoNotChangeZoom); } } } m_isPositionAssigned = true; SetIsVisible(true); double const kEps = 1e-5; if (fabs(m_lastLocationTimestamp - info.m_timestamp) > kEps) { m_lastLocationTimestamp = info.m_timestamp; m_updateLocationTimer.Reset(); } }
bool CanShrinkInto(ScreenBase const & screen, m2::RectD const & boundRect) { m2::RectD clipRect = screen.ClipRect(); return (boundRect.SizeX() >= clipRect.SizeX()) && (boundRect.SizeY() >= clipRect.SizeY()); }
double CalculateScale(m2::RectD const & pixelRect, m2::RectD const & localRect) { return max(localRect.SizeX() / pixelRect.SizeX(), localRect.SizeY() / pixelRect.SizeY()); }
ScreenBase const ShrinkAndScaleInto(ScreenBase const & screen, m2::RectD boundRect) { ReduceRectHack(boundRect); ScreenBase res = screen; m2::RectD globalRect = res.ClipRect(); m2::PointD newOrg = res.GetOrg(); double scale = 1; double offs = 0; if (globalRect.minX() < boundRect.minX()) { offs = boundRect.minX() - globalRect.minX(); globalRect.Offset(offs, 0); newOrg.x += offs; if (globalRect.maxX() > boundRect.maxX()) { double k = boundRect.SizeX() / globalRect.SizeX(); scale /= k; /// scaling always occur pinpointed to the rect center... globalRect.Scale(k); /// ...so we should shift a rect after scale globalRect.Offset(boundRect.minX() - globalRect.minX(), 0); } } if (globalRect.maxX() > boundRect.maxX()) { offs = boundRect.maxX() - globalRect.maxX(); globalRect.Offset(offs, 0); newOrg.x += offs; if (globalRect.minX() < boundRect.minX()) { double k = boundRect.SizeX() / globalRect.SizeX(); scale /= k; globalRect.Scale(k); globalRect.Offset(boundRect.maxX() - globalRect.maxX(), 0); } } if (globalRect.minY() < boundRect.minY()) { offs = boundRect.minY() - globalRect.minY(); globalRect.Offset(0, offs); newOrg.y += offs; if (globalRect.maxY() > boundRect.maxY()) { double k = boundRect.SizeY() / globalRect.SizeY(); scale /= k; globalRect.Scale(k); globalRect.Offset(0, boundRect.minY() - globalRect.minY()); } } if (globalRect.maxY() > boundRect.maxY()) { offs = boundRect.maxY() - globalRect.maxY(); globalRect.Offset(0, offs); newOrg.y += offs; if (globalRect.minY() < boundRect.minY()) { double k = boundRect.SizeY() / globalRect.SizeY(); scale /= k; globalRect.Scale(k); globalRect.Offset(0, boundRect.maxY() - globalRect.maxY()); } } res.SetOrg(globalRect.Center()); res.Scale(scale); return res; }
void Navigator::Move(double azDir, double factor) { m2::RectD const r = m_Screen.ClipRect(); m_Screen.MoveG(m2::PointD(r.SizeX() * factor * cos(azDir), r.SizeY() * factor * sin(azDir))); }
double CalculateScale(ScreenBase const & screen, m2::RectD const & localRect) { m2::RectD const pixelRect = screen.PixelRect(); return max(localRect.SizeX() / pixelRect.SizeX(), localRect.SizeY() / pixelRect.SizeY()); }