From f78398ca42e364800d9624822b83ed5c109b64f1 Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Thu, 24 Mar 2016 17:13:14 +0300 Subject: [PATCH] [editor] Reduced radius to match features for exactly 1 meter. --- editor/changeset_wrapper.cpp | 12 +++++------ editor/changeset_wrapper.hpp | 4 ++-- editor/editor_tests/server_api_test.cpp | 5 +++-- editor/server_api.cpp | 27 ++++++++++++++----------- editor/server_api.hpp | 6 +++--- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/editor/changeset_wrapper.cpp b/editor/changeset_wrapper.cpp index 73e73e91ed..2b00a1e4d8 100644 --- a/editor/changeset_wrapper.cpp +++ b/editor/changeset_wrapper.cpp @@ -93,9 +93,9 @@ ChangesetWrapper::~ChangesetWrapper() } } -void ChangesetWrapper::LoadXmlFromOSM(ms::LatLon const & ll, pugi::xml_document & doc) +void ChangesetWrapper::LoadXmlFromOSM(ms::LatLon const & ll, pugi::xml_document & doc, double radiusInMeters) { - auto const response = m_api.GetXmlFeaturesAtLatLon(ll.lat, ll.lon); + auto const response = m_api.GetXmlFeaturesAtLatLon(ll.lat, ll.lon, radiusInMeters); if (response.first != OsmOAuth::HTTP::OK) MYTHROW(HttpErrorException, ("HTTP error", response, "with GetXmlFeaturesAtLatLon", ll)); @@ -103,11 +103,11 @@ void ChangesetWrapper::LoadXmlFromOSM(ms::LatLon const & ll, pugi::xml_document MYTHROW(OsmXmlParseException, ("Can't parse OSM server response for GetXmlFeaturesAtLatLon request", response.second)); } -void ChangesetWrapper::LoadXmlFromOSM(m2::RectD const & rect, pugi::xml_document & doc) +void ChangesetWrapper::LoadXmlFromOSM(ms::LatLon const & min, ms::LatLon const & max, pugi::xml_document & doc) { - auto const response = m_api.GetXmlFeaturesInRect(rect); + auto const response = m_api.GetXmlFeaturesInRect(min.lat, min.lon, max.lat, max.lon); if (response.first != OsmOAuth::HTTP::OK) - MYTHROW(HttpErrorException, ("HTTP error", response, "with GetXmlFeaturesInRect", rect)); + MYTHROW(HttpErrorException, ("HTTP error", response, "with GetXmlFeaturesInRect", min, max)); if (pugi::status_ok != doc.load(response.second.c_str()).status) MYTHROW(OsmXmlParseException, ("Can't parse OSM server response for GetXmlFeaturesInRect request", response.second)); @@ -154,7 +154,7 @@ XMLFeature ChangesetWrapper::GetMatchingAreaFeatureFromOSM(vector co if (doc.select_node("osm/relation")) { auto const rect = GetBoundingRect(geometry); - LoadXmlFromOSM(rect, doc); + LoadXmlFromOSM(ms::LatLon(rect.minY(), rect.minX()), ms::LatLon(rect.maxY(), rect.maxX()), doc); hasRelation = true; } diff --git a/editor/changeset_wrapper.hpp b/editor/changeset_wrapper.hpp index 3cc09f251d..375cd2b279 100644 --- a/editor/changeset_wrapper.hpp +++ b/editor/changeset_wrapper.hpp @@ -53,8 +53,8 @@ public: private: /// Unfortunately, pugi can't return xml_documents from methods. /// Throws exceptions from above list. - void LoadXmlFromOSM(ms::LatLon const & ll, pugi::xml_document & doc); - void LoadXmlFromOSM(m2::RectD const & rect, pugi::xml_document & doc); + void LoadXmlFromOSM(ms::LatLon const & ll, pugi::xml_document & doc, double radiusInMeters = 1.0); + void LoadXmlFromOSM(ms::LatLon const & min, ms::LatLon const & max, pugi::xml_document & doc); ServerApi06::TKeyValueTags m_changesetComments; ServerApi06 m_api; diff --git a/editor/editor_tests/server_api_test.cpp b/editor/editor_tests/server_api_test.cpp index 83d6e652f9..20c4fa0110 100644 --- a/editor/editor_tests/server_api_test.cpp +++ b/editor/editor_tests/server_api_test.cpp @@ -47,7 +47,7 @@ ServerApi06 CreateAPI() void DeleteOSMNodeIfExists(ServerApi06 const & api, uint64_t changeSetId, ms::LatLon const & ll) { // Delete all test nodes left on the server (if any). - auto const response = api.GetXmlFeaturesAtLatLon(ll); + auto const response = api.GetXmlFeaturesAtLatLon(ll, 1.0); TEST_EQUAL(response.first, OsmOAuth::HTTP::OK, ()); xml_document reply; reply.load_string(response.second.c_str()); @@ -72,6 +72,7 @@ UNIT_TEST(OSM_ServerAPI_ChangesetAndNode) uint64_t changeSetId = api.CreateChangeSet({{"created_by", "MAPS.ME Unit Test"}, {"comment", "For test purposes only."}}); auto const changesetCloser = [&]() { api.CloseChangeSet(changeSetId); }; + { MY_SCOPE_GUARD(guard, changesetCloser); @@ -99,7 +100,7 @@ UNIT_TEST(OSM_ServerAPI_ChangesetAndNode) // It is done here via Scope Guard. } - auto const response = api.GetXmlFeaturesAtLatLon(kModifiedLocation); + auto const response = api.GetXmlFeaturesAtLatLon(kModifiedLocation, 1.0); TEST_EQUAL(response.first, OsmOAuth::HTTP::OK, ()); auto const features = XMLFeature::FromOSM(response.second); TEST_EQUAL(1, features.size(), ()); diff --git a/editor/server_api.cpp b/editor/server_api.cpp index fad349603c..4d511e6df2 100644 --- a/editor/server_api.cpp +++ b/editor/server_api.cpp @@ -5,6 +5,7 @@ #include "geometry/mercator.hpp" #include "base/logging.hpp" +#include "base/math.hpp" #include "base/string_utils.hpp" #include "base/timer.hpp" @@ -155,31 +156,33 @@ UserPreferences ServerApi06::GetUserPreferences() const return pref; } -OsmOAuth::Response ServerApi06::GetXmlFeaturesInRect(m2::RectD const & latLonRect) const +OsmOAuth::Response ServerApi06::GetXmlFeaturesInRect(double minLat, double minLon, double maxLat, double maxLon) const { using strings::to_string_dac; // Digits After Comma. static constexpr double kDAC = 7; - m2::PointD const lb = latLonRect.LeftBottom(); - m2::PointD const rt = latLonRect.RightTop(); - string const url = "/map?bbox=" + to_string_dac(lb.x, kDAC) + ',' + to_string_dac(lb.y, kDAC) + ',' + - to_string_dac(rt.x, kDAC) + ',' + to_string_dac(rt.y, kDAC); + string const url = "/map?bbox=" + to_string_dac(minLon, kDAC) + ',' + to_string_dac(minLat, kDAC) + ',' + + to_string_dac(maxLon, kDAC) + ',' + to_string_dac(maxLat, kDAC); return m_auth.DirectRequest(url); } -OsmOAuth::Response ServerApi06::GetXmlFeaturesAtLatLon(double lat, double lon) const +OsmOAuth::Response ServerApi06::GetXmlFeaturesAtLatLon(double lat, double lon, double radiusInMeters) const { - double const kInflateEpsilon = MercatorBounds::GetCellID2PointAbsEpsilon() / 2; - m2::RectD rect(lon, lat, lon, lat); - rect.Inflate(kInflateEpsilon, kInflateEpsilon); - return GetXmlFeaturesInRect(rect); + double const latDegreeOffset = radiusInMeters * MercatorBounds::degreeInMetres; + double const minLat = max(-90.0, lat - latDegreeOffset); + double const maxLat = min( 90.0, lat + latDegreeOffset); + double const cosL = max(cos(my::DegToRad(max(fabs(minLat), fabs(maxLat)))), 0.00001); + double const lonDegreeOffset = radiusInMeters * MercatorBounds::degreeInMetres / cosL; + double const minLon = max(-180.0, lon - lonDegreeOffset); + double const maxLon = min( 180.0, lon + lonDegreeOffset); + return GetXmlFeaturesInRect(minLat, minLon, maxLat, maxLon); } -OsmOAuth::Response ServerApi06::GetXmlFeaturesAtLatLon(ms::LatLon const & ll) const +OsmOAuth::Response ServerApi06::GetXmlFeaturesAtLatLon(ms::LatLon const & ll, double radiusInMeters) const { - return GetXmlFeaturesAtLatLon(ll.lat, ll.lon); + return GetXmlFeaturesAtLatLon(ll.lat, ll.lon, radiusInMeters); } } // namespace osm diff --git a/editor/server_api.hpp b/editor/server_api.hpp index e69983b5a5..1ff1b697a8 100644 --- a/editor/server_api.hpp +++ b/editor/server_api.hpp @@ -76,9 +76,9 @@ public: void CloseNote(uint64_t const id) const; /// @returns OSM xml string with features in the bounding box or empty string on error. - OsmOAuth::Response GetXmlFeaturesInRect(m2::RectD const & latLonRect) const; - OsmOAuth::Response GetXmlFeaturesAtLatLon(double lat, double lon) const; - OsmOAuth::Response GetXmlFeaturesAtLatLon(ms::LatLon const & ll) const; + OsmOAuth::Response GetXmlFeaturesInRect(double minLat, double minLon, double maxLat, double maxLon) const; + OsmOAuth::Response GetXmlFeaturesAtLatLon(double lat, double lon, double radiusInMeters = 1.0) const; + OsmOAuth::Response GetXmlFeaturesAtLatLon(ms::LatLon const & ll, double radiusInMeters = 1.0) const; private: OsmOAuth m_auth;