From 234c6db9d3ab80f2db35e007beee4f0c42c978b2 Mon Sep 17 00:00:00 2001 From: vng Date: Fri, 30 Mar 2012 16:53:14 +0300 Subject: [PATCH] [bookmarks] KML loading. --- map/framework.cpp | 118 +++++++++++++++++++++++++++++-- map/framework.hpp | 2 + map/map_tests/bookmarks_test.cpp | 74 +++++++++++++++++++ map/map_tests/map_tests.pro | 5 +- 4 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 map/map_tests/bookmarks_test.cpp diff --git a/map/framework.cpp b/map/framework.cpp index 991e417abc..8af03b9245 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -19,6 +19,8 @@ #include "../indexer/scales.hpp" #include "../indexer/classificator.hpp" +#include "../coding/parse_xml.hpp" // LoadFromKML + #include "../base/math.hpp" #include "../base/string_utils.hpp" @@ -201,6 +203,111 @@ void Framework::ClearBookmarks() m_bookmarks.clear(); } +namespace +{ + class KMLParser + { + Framework & m_framework; + + int m_level; + + string m_name; + m2::PointD m_org; + + void Reset() + { + m_name.clear(); + m_org = m2::PointD(-1000, -1000); + } + + void SetOrigin(string const & s) + { + // order in string is: lon, lat, z + + strings::SimpleTokenizer iter(s, ", "); + if (iter) + { + double lon; + if (strings::to_double(*iter, lon) && MercatorBounds::ValidLon(lon) && ++iter) + { + double lat; + if (strings::to_double(*iter, lat) && MercatorBounds::ValidLat(lat)) + m_org = m2::PointD(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat)); + } + } + } + + bool IsValid() const + { + return (!m_name.empty() && + MercatorBounds::ValidX(m_org.x) && MercatorBounds::ValidY(m_org.y)); + } + + public: + KMLParser(Framework & f) : m_framework(f), m_level(0) + { + Reset(); + } + + bool Push(string const & name) + { + switch (m_level) + { + case 0: + if (name != "kml") return false; + break; + + case 1: + if (name != "Document") return false; + break; + + case 2: + if (name != "Placemark") return false; + break; + + case 3: + if (name != "Point" && name != "name") return false; + break; + + case 4: + if (name != "coordinates") return false; + } + + ++m_level; + return true; + } + + void AddAttr(string const &, string const &) {} + + void Pop(string const &) + { + --m_level; + + if (m_level == 2 && IsValid()) + { + m_framework.AddBookmark(m_org, m_name); + Reset(); + } + } + + void CharData(string const & value) + { + switch (m_level) + { + case 4: m_name = value; break; + case 5: SetOrigin(value); break; + } + } + }; +} + +void Framework::LoadFromKML(ReaderPtr const & reader) +{ + ReaderSource > src(reader); + KMLParser parser(*this); + ParseXML(src, parser, true); +} + void Framework::GetLocalMaps(vector & outMaps) { Platform & pl = GetPlatform(); @@ -284,7 +391,6 @@ void Framework::OnSize(int w, int h) if (w < 2) w = 2; if (h < 2) h = 2; - if (m_renderPolicy) { m_informationDisplay.setDisplayRect(m2::RectI(m2::PointI(0, 0), m2::PointU(w, h))); @@ -347,7 +453,7 @@ void Framework::DrawModel(shared_ptr const & e, try { - int const scale = (m_queryMaxScaleMode ? 17 : scaleLevel); + int const scale = (m_queryMaxScaleMode ? scales::GetUpperScale() : scaleLevel); //threads::MutexGuard lock(m_modelSyn); if (isTiling) @@ -357,11 +463,11 @@ void Framework::DrawModel(shared_ptr const & e, } catch (redraw_operation_cancelled const &) { - DrawerYG * pDrawer = e->drawer(); - if (pDrawer->screen()->renderState()) + shared_ptr pState = e->drawer()->screen()->renderState(); + if (pState) { - pDrawer->screen()->renderState()->m_isEmptyModelCurrent = false; - pDrawer->screen()->renderState()->m_isEmptyModelActual = false; + pState->m_isEmptyModelCurrent = false; + pState->m_isEmptyModelActual = false; } } diff --git a/map/framework.hpp b/map/framework.hpp index 3125456463..efcb274aa0 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -129,6 +129,8 @@ public: void GetBookmark(size_t i, Bookmark & bm) const; void ClearBookmarks(); + void LoadFromKML(ReaderPtr const & reader); + storage::Storage & Storage() { return m_storage; } void OnLocationStatusChanged(location::TLocationStatus newStatus); diff --git a/map/map_tests/bookmarks_test.cpp b/map/map_tests/bookmarks_test.cpp new file mode 100644 index 0000000000..88c606a9ad --- /dev/null +++ b/map/map_tests/bookmarks_test.cpp @@ -0,0 +1,74 @@ +#include "../../testing/testing.hpp" + +#include "../../map/framework.hpp" + + +namespace +{ +char const * kmlString = + "" + "" + "" + "MapName" + "" + "" + "" + "" + "Nebraska" + "" + "#style2" + "" + "-99.901810,41.492538,0.000000" + "" + "" + "" + "Monongahela National Forest" + "]]>" + "#style3" + "" + "-79.829674,38.627785,0.000000" + "" + "" + "" + "From: Минск, Минская область, Беларусь" + "" + "#style5" + "" + "27.566765,53.900047,0.000000" + "" + "" + "" + ""; +} + +UNIT_TEST(Bookmarks_ImportKML) +{ + Framework fm; + + fm.LoadFromKML(new MemReader(kmlString, strlen(kmlString))); + + TEST_EQUAL(fm.BookmarksCount(), 3, ()); + + Bookmark bm; + fm.GetBookmark(0, bm); + TEST_EQUAL(bm.GetName(), "Nebraska", ()); + fm.GetBookmark(1, bm); + TEST_EQUAL(bm.GetName(), "Monongahela National Forest", ()); + + fm.GetBookmark(2, bm); + m2::PointD const org = bm.GetOrg(); + TEST_ALMOST_EQUAL(MercatorBounds::XToLon(org.x), 27.566765, ()); + TEST_ALMOST_EQUAL(MercatorBounds::YToLat(org.y), 53.900047, ()); +} diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index 7bccab3371..2e341aee87 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = map yg indexer platform geometry coding base freetype fribidi expat protobuf +DEPENDENCIES = map storage search yg indexer platform geometry coding base freetype fribidi expat protobuf tomcrypt include($$ROOT_DIR/common.pri) @@ -16,7 +16,7 @@ win32* { LIBS *= -lShell32 -lOpengl32 win32-g++: LIBS *= -lpthread } -macx*: LIBS *= "-framework Foundation" +macx*: LIBS *= "-framework Foundation" "-framework IOKit" SOURCES += \ ../../testing/testingmain.cpp \ @@ -25,3 +25,4 @@ SOURCES += \ debug_features_test.cpp \ draw_processor_test.cpp \ multithread_map_test.cpp \ + bookmarks_test.cpp