From d67e303dc56a536e062db53983d9aef5081309f9 Mon Sep 17 00:00:00 2001 From: vng Date: Tue, 1 Jul 2014 16:51:38 +0300 Subject: [PATCH] Fixed viewport for search results on the map. --- geometry/any_rect2d.hpp | 10 +++++ geometry/geometry_tests/anyrect_test.cpp | 13 ++++++ geometry/rect2d.hpp | 12 ++++++ map/framework.cpp | 53 +++++++++++++++--------- map/framework.hpp | 4 +- 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/geometry/any_rect2d.hpp b/geometry/any_rect2d.hpp index e8cd054268..ea9037818e 100644 --- a/geometry/any_rect2d.hpp +++ b/geometry/any_rect2d.hpp @@ -228,6 +228,16 @@ namespace m2 { m_zero = ConvertTo(ConvertFrom(m_zero) + p); } + + Point const Center() const + { + return ConvertFrom(m_rect.Center()); + } + + void SetSizesToIncludePoint(Point const & p) + { + m_rect.SetSizesToIncludePoint(ConvertTo(p)); + } }; template diff --git a/geometry/geometry_tests/anyrect_test.cpp b/geometry/geometry_tests/anyrect_test.cpp index e3d9a8872e..9ae89d06b5 100644 --- a/geometry/geometry_tests/anyrect_test.cpp +++ b/geometry/geometry_tests/anyrect_test.cpp @@ -71,3 +71,16 @@ UNIT_TEST(AnyRect_TestIsIntersect) TEST(r0.IsIntersect(r3), ()); } +UNIT_TEST(AnyRect_SetSizesToIncludePoint) +{ + m2::AnyRectD rect(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, 0, 50, 50)); + + TEST(!rect.IsPointInside(m2::PointD(0, 0)), ()); + TEST(!rect.IsPointInside(m2::PointD(200, 200)), ()); + + rect.SetSizesToIncludePoint(m2::PointD(0, 0)); + TEST(rect.IsPointInside(m2::PointD(0, 0)), ()); + + rect.SetSizesToIncludePoint(m2::PointD(200, 200)); + TEST(rect.IsPointInside(m2::PointD(200, 200)), ()); +} diff --git a/geometry/rect2d.hpp b/geometry/rect2d.hpp index 6154eec94a..09414221e6 100644 --- a/geometry/rect2d.hpp +++ b/geometry/rect2d.hpp @@ -176,6 +176,18 @@ namespace m2 m_maxY = c.y + dy; } + void SetSizesToIncludePoint(Point const & pt) + { + Point const c = Center(); + T const dx = my::Abs(pt.x - c.x); + T const dy = my::Abs(pt.y - c.y); + + m_minX = c.x - dx; + m_minY = c.y - dy; + m_maxX = c.x + dx; + m_maxY = c.y + dy; + } + void SetCenter(m2::Point const & p) { Offset(p - Center()); diff --git a/map/framework.cpp b/map/framework.cpp index ae6a6dd388..c3aa4f469d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -795,7 +795,12 @@ void Framework::ShowRectExVisibleScale(m2::RectD rect, int maxScale/* = -1*/) ShowRectFixed(rect); } -void Framework::ShowRectFixed(m2::RectD const & r) +void Framework::ShowRectFixed(m2::RectD const & rect) +{ + ShowRectFixedAR(ToRotated(rect)); +} + +void Framework::ShowRectFixedAR(m2::AnyRectD const & rect) { double const halfSize = m_scales.GetTileSize() / 2.0; m2::RectD etalonRect(-halfSize, -halfSize, halfSize, halfSize); @@ -803,7 +808,7 @@ void Framework::ShowRectFixed(m2::RectD const & r) m2::PointD const pxCenter = m_navigator.Screen().PixelRect().Center(); etalonRect.Offset(pxCenter); - m_navigator.SetFromRects(ToRotated(r), etalonRect); + m_navigator.SetFromRects(rect, etalonRect); Invalidate(); } @@ -835,8 +840,7 @@ void Framework::OnSearchResultsCallbackUI(search::Results const & results) { if (IsISActive()) { - m2::RectD dummy; - (void) FillSearchResultsMarks(results, dummy); + FillSearchResultsMarks(results); Invalidate(); } @@ -1234,10 +1238,30 @@ size_t Framework::ShowAllSearchResults() return count; } - m2::RectD rect; - if (!FillSearchResultsMarks(results, rect) && rect.IsValid()) + FillSearchResultsMarks(results); + + // Setup viewport according to results. + m2::AnyRectD viewport = m_navigator.Screen().GlobalRect(); + m2::PointD const center = viewport.Center(); + + double minDistance = numeric_limits::max(); + size_t minInd; + for (size_t i = 0; i < count; ++i) { - ShowRectEx(rect); + double const dist = center.SquareLength(results.GetResult(i).GetFeatureCenter()); + if (dist < minDistance) + { + minDistance = dist; + minInd = i; + } + } + + m2::PointD const pt = results.GetResult(minInd).GetFeatureCenter(); + if (!viewport.IsPointInside(pt)) + { + viewport.SetSizesToIncludePoint(pt); + + ShowRectFixedAR(viewport); StopLocationFollow(); } else @@ -1246,15 +1270,13 @@ size_t Framework::ShowAllSearchResults() return count; } -bool Framework::FillSearchResultsMarks(search::Results const & results, m2::RectD & rect) +void Framework::FillSearchResultsMarks(search::Results const & results) { UserMarkContainer::Type const type = UserMarkContainer::SEARCH_MARK; m_bmManager.UserMarksSetVisible(type, true); m_bmManager.UserMarksClear(type); m_bmManager.UserMarksSetDrawable(type, true); - m2::RectD const viewport = GetCurrentViewport(); - bool res = false; size_t const count = results.GetCount(); for (size_t i = 0; i < count; ++i) { @@ -1266,18 +1288,11 @@ bool Framework::FillSearchResultsMarks(search::Results const & results, m2::Rect AddressInfo info; info.MakeFrom(r); - m2::PointD const pt = r.GetFeatureCenter(); - - SearchMarkPoint * mark = static_cast(m_bmManager.UserMarksAddMark(type, pt)); + SearchMarkPoint * mark = static_cast( + m_bmManager.UserMarksAddMark(type, r.GetFeatureCenter())); mark->SetInfo(info); - - rect.Add(pt); - - res = res || viewport.IsPointInside(pt); } } - - return res; } void Framework::CancelInteractiveSearch() diff --git a/map/framework.hpp b/map/framework.hpp index 1ee3cbd011..673266d162 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -250,8 +250,7 @@ private: void OnSearchResultsCallback(search::Results const & results); void OnSearchResultsCallbackUI(search::Results const & results); - /// @return true if any result is in viewport rect. - bool FillSearchResultsMarks(search::Results const & results, m2::RectD & rect); + void FillSearchResultsMarks(search::Results const & results); public: m2::RectD GetCurrentViewport() const; @@ -363,6 +362,7 @@ private: m2::AnyRectD ToRotated(m2::RectD const & rect) const; void ShowRectFixed(m2::RectD const & rect); + void ShowRectFixedAR(m2::AnyRectD const & rect); public: /// Show rect for point and needed draw scale.