m2::AnyRectD ToRotated(m2::RectD const & rect, Navigator const & navigator) { double const dx = rect.SizeX(); double const dy = rect.SizeY(); return m2::AnyRectD(rect.Center(), navigator.Screen().GetAngle(), m2::RectD(-dx/2, -dy/2, dx/2, dy/2)); }
m2::PointD CalculateCenter(double scale, m2::RectD const & pixelRect, m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth) { m2::PointD formingVector = (pixelRect.Center() - pixelPos) * scale; formingVector.y = -formingVector.y; formingVector.Rotate(azimuth); return userPos + formingVector; }
drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, double targetScale, double targetAngle, m2::PointD const & endPixelPos) { auto sequenceAnim = make_unique_dp<SequenceAnimation>(); sequenceAnim->SetCustomType(kPrettyFollowAnim); m2::RectD const viewportRect = startScreen.PixelRectIn3d(); ScreenBase tmp = startScreen; tmp.SetAngle(targetAngle); tmp.MatchGandP3d(userPos, viewportRect.Center()); double const moveDuration = PositionInterpolator::GetMoveDuration(startScreen.GetOrg(), tmp.GetOrg(), startScreen); ASSERT_GREATER(moveDuration, 0.0, ()); double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0; tmp = startScreen; if (moveDuration > 0.0) { tmp.SetScale(startScreen.GetScale() * scaleFactor); auto zoomOutAnim = make_unique_dp<MapLinearAnimation>(); zoomOutAnim->SetScale(startScreen.GetScale(), tmp.GetScale()); zoomOutAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); sequenceAnim->AddAnimation(move(zoomOutAnim)); tmp.MatchGandP3d(userPos, viewportRect.Center()); auto moveAnim = make_unique_dp<MapLinearAnimation>(); moveAnim->SetMove(startScreen.GetOrg(), tmp.GetOrg(), viewportRect, tmp.GetScale()); moveAnim->SetMaxDuration(kMaxAnimationTimeSec); sequenceAnim->AddAnimation(move(moveAnim)); } auto followAnim = make_unique_dp<MapFollowAnimation>(tmp, userPos, endPixelPos, tmp.GetScale(), targetScale, tmp.GetAngle(), targetAngle, false /* isAutoZoom */); followAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); sequenceAnim->AddAnimation(move(followAnim)); return sequenceAnim; }
void Framework::ShowNode(TCountryId const & idx, bool zoomToDownloadButton) { if (zoomToDownloadButton) { m2::RectD const rect = CalcLimitRect(idx, m_work.GetStorage(), m_work.GetCountryInfoGetter()); m_work.SetViewportCenter(rect.Center(), 10); } else { m_work.ShowNode(idx); } }
void Engine::SetRankPivot(SearchParams const & params, m2::RectD const & viewport, bool viewportSearch, Query & processor) { if (!viewportSearch && params.IsValidPosition()) { m2::PointD const pos = MercatorBounds::FromLatLon(params.m_lat, params.m_lon); if (m2::Inflate(viewport, viewport.SizeX() / 4.0, viewport.SizeY() / 4.0).IsPointInside(pos)) { processor.SetRankPivot(pos); return; } } processor.SetRankPivot(viewport.Center()); }
void ClipTriangleByRect(m2::RectD const & rect, m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3, ClipTriangleByRectResultIt const & resultIterator) { if (resultIterator == nullptr) return; if (rect.IsPointInside(p1) && rect.IsPointInside(p2) && rect.IsPointInside(p3)) { resultIterator(p1, p2, p3); return; } const double kEps = 1e-8; vector<m2::PointD> poligon; auto const addPoligonPoint = [&poligon, kEps](m2::PointD const & pt) { if (poligon.empty() || !poligon.back().EqualDxDy(pt, kEps)) poligon.push_back(pt); }; vector<m2::PointD> const corners = { rect.LeftTop(), rect.RightTop(), rect.RightBottom(), rect.LeftBottom() }; int firstClipCode[3]; int lastClipCode[3]; bool intersected[3]; intersected[0] = IntersectEdge(rect, corners, p1, p2, p3, addPoligonPoint, 0, 0, firstClipCode[0], lastClipCode[0]); intersected[1] = IntersectEdge(rect, corners, p2, p3, p1, addPoligonPoint, lastClipCode[0], 0, firstClipCode[1], lastClipCode[1]); intersected[2] = IntersectEdge(rect, corners, p3, p1, p2, addPoligonPoint, lastClipCode[1] != 0 ? lastClipCode[1] : lastClipCode[0], firstClipCode[0] != 0 ? firstClipCode[0] : firstClipCode[1], firstClipCode[2], lastClipCode[2]); int const intersectCount = intersected[0] + intersected[1] + intersected[2]; if (intersectCount == 0) { if (IsPointInsideTriangle(rect.Center(), p1, p2, p3)) { resultIterator(rect.LeftTop(), rect.RightTop(), rect.RightBottom()); resultIterator(rect.RightBottom(), rect.LeftBottom(), rect.LeftTop()); } return; } if (intersectCount == 1 && intersected[2]) InsertCorners(corners, p1, p2, p3, addPoligonPoint, lastClipCode[2], firstClipCode[2]); if (!poligon.empty() && poligon.back().EqualDxDy(poligon[0], kEps)) poligon.pop_back(); if (poligon.size() < 3) return; for (size_t i = 0; i < poligon.size() - 2; ++i) resultIterator(poligon[0], poligon[i + 1], poligon[i + 2]); }
void Engine::DoSearch(SearchParams const & params, m2::RectD const & viewport, shared_ptr<QueryHandle> handle, Query & processor) { bool const viewportSearch = params.GetMode() == Mode::Viewport; // Initialize query processor. processor.Init(viewportSearch); handle->Attach(processor); MY_SCOPE_GUARD(detach, [&handle] { handle->Detach(); }); // Early exit when query processing is cancelled. if (processor.IsCancelled()) { params.m_onResults(Results::GetEndMarker(true /* isCancelled */)); return; } SetRankPivot(params, viewport, viewportSearch, processor); if (params.IsValidPosition()) processor.SetPosition(MercatorBounds::FromLatLon(params.m_lat, params.m_lon)); else processor.SetPosition(viewport.Center()); processor.SetMode(params.GetMode()); processor.SetSuggestsEnabled(params.GetSuggestsEnabled()); // This flag is needed for consistency with old search algorithm // only. It will be gone when we remove old search code. processor.SetSearchInWorld(true); processor.SetInputLocale(params.m_inputLocale); ASSERT(!params.m_query.empty(), ()); processor.SetQuery(params.m_query); Results res; processor.SearchCoordinates(res); try { if (params.m_onStarted) params.m_onStarted(); processor.SetViewport(viewport, true /* forceUpdate */); if (viewportSearch) processor.SearchViewportPoints(res); else processor.Search(res, kResultsCount); if (!processor.IsCancelled()) EmitResults(params, res); } catch (Query::CancelException const &) { LOG(LDEBUG, ("Search has been cancelled.")); } if (!viewportSearch && !processor.IsCancelled()) SendStatistics(params, viewport, res); // Emit finish marker to client. params.m_onResults(Results::GetEndMarker(processor.IsCancelled())); }