diff options
author | vng <viktor.govako@gmail.com> | 2015-12-22 13:57:16 +0300 |
---|---|---|
committer | Sergey Yershov <yershov@corp.mail.ru> | 2016-03-23 16:03:16 +0300 |
commit | 2fe8fee598e31e2a456b09208b2d53eeb69df0c9 (patch) | |
tree | 6354377d1817bbab9e8374238c87996e95574c3d /search/reverse_geocoder.cpp | |
parent | 21370ee3d9635139c460addabdf60abb559369c7 (diff) |
[search] Get street name and house number from point.
Diffstat (limited to 'search/reverse_geocoder.cpp')
-rw-r--r-- | search/reverse_geocoder.cpp | 104 |
1 files changed, 78 insertions, 26 deletions
diff --git a/search/reverse_geocoder.cpp b/search/reverse_geocoder.cpp index 7fa17a951f..b01866d2cc 100644 --- a/search/reverse_geocoder.cpp +++ b/search/reverse_geocoder.cpp @@ -1,6 +1,8 @@ #include "reverse_geocoder.hpp" #include "search_string_utils.hpp" +#include "search/v2/house_to_street_table.hpp" + #include "indexer/feature.hpp" #include "indexer/feature_algo.hpp" #include "indexer/ftypes_matcher.hpp" @@ -13,34 +15,27 @@ namespace search { namespace { -size_t constexpr kMaxStreetIndex = 16; size_t constexpr kSimilarityThresholdPercent = 10; - -/// @todo Need to check projection here? -double CalculateMinDistance(FeatureType const & ft, m2::PointD const & pt) -{ - ASSERT_EQUAL(ft.GetFeatureType(), feature::GEOM_LINE, ()); - - double res = numeric_limits<double>::max(); - ft.ForEachPoint([&] (m2::PointD const & p) - { - double const d = MercatorBounds::DistanceOnEarth(p, pt); - if (d < res) - res = d; - }, FeatureType::BEST_GEOMETRY); - - return res; -} +int const kQueryScale = scales::GetUpperScale(); } // namespace // static double const ReverseGeocoder::kLookupRadiusM = 500.0; +// static +m2::RectD ReverseGeocoder::GetLookupRect(m2::PointD const & center) +{ + return MercatorBounds::RectByCenterXYAndSizeInMeters(center, kLookupRadiusM); +} + void ReverseGeocoder::GetNearbyStreets(FeatureType const & addrFt, vector<Street> & streets) { - m2::PointD const & center = feature::GetCenter(addrFt); - m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters( - center, kLookupRadiusM); + GetNearbyStreets(feature::GetCenter(addrFt), streets); +} + +void ReverseGeocoder::GetNearbyStreets(m2::PointD const & center, vector<Street> & streets) +{ + m2::RectD const rect = GetLookupRect(center); auto const addStreet = [&](FeatureType const & ft) { @@ -56,25 +51,49 @@ void ReverseGeocoder::GetNearbyStreets(FeatureType const & addrFt, vector<Street return; ASSERT(!name.empty(), ()); - streets.push_back({ft.GetID(), CalculateMinDistance(ft, center), name}); + streets.push_back({ft.GetID(), feature::GetMinDistance(ft, center), name}); }; - m_index.ForEachInRect(addStreet, rect, scales::GetUpperScale()); + m_index.ForEachInRect(addStreet, rect, kQueryScale); sort(streets.begin(), streets.end(), my::CompareBy(&Street::m_distanceMeters)); } +void ReverseGeocoder::GetNearbyBuildings(m2::PointD const & center, vector<Building> & buildings) +{ + // Seems like a copy-paste here of the GetNearbyStreets function. + // Trying to factor out common logic will cause many variables logic. + + m2::RectD const rect = GetLookupRect(center); + + auto const addBld = [&](FeatureType const & ft) + { + if (!ftypes::IsBuildingChecker::Instance()(ft)) + return; + + // Skip empty house nubers. + string const number = ft.GetHouseNumber(); + if (number.empty()) + return; + + buildings.push_back({ft.GetID(), feature::GetMinDistance(ft, center), + number, feature::GetCenter(ft)}); + }; + + m_index.ForEachInRect(addBld, rect, kQueryScale); + sort(buildings.begin(), buildings.end(), my::CompareBy(&Building::m_distanceMeters)); +} + // static size_t ReverseGeocoder::GetMatchedStreetIndex(string const & keyName, vector<Street> const & streets) { strings::UniString const expected = strings::MakeUniString(keyName); - // Do limit possible return values. - size_t const count = min(streets.size(), kMaxStreetIndex); - // Find the exact match or the best match in kSimilarityTresholdPercent limit. + size_t const count = streets.size(); size_t result = count; size_t minPercent = kSimilarityThresholdPercent + 1; + for (size_t i = 0; i < count; ++i) { string key; @@ -98,6 +117,39 @@ size_t ReverseGeocoder::GetMatchedStreetIndex(string const & keyName, } } - return (result < count ? result : streets.size()); + return result; } + +void ReverseGeocoder::GetNearbyAddress(m2::PointD const & center, + Building & building, Street & street) +{ + vector<Building> buildings; + GetNearbyBuildings(center, buildings); + + vector<Street> streets; + unique_ptr<search::v2::HouseToStreetTable> table; + MwmSet::MwmId mwmId; + + for (auto const & b : buildings) + { + if (!table || mwmId != b.m_id.m_mwmId) + { + auto handle = m_index.GetMwmHandleById(b.m_id.m_mwmId); + auto value = handle.GetValue<MwmValue>(); + if (value) + table = search::v2::HouseToStreetTable::Load(*value); + } + + GetNearbyStreets(b.m_center, streets); + + uint32_t const ind = table->Get(b.m_id.m_index); + if (ind < streets.size()) + { + building = b; + street = streets[ind]; + return; + } + } +} + } // namespace search |