[search] Treat addr:interpolation as Address object. #5063

Merged
vng merged 4 commits from vng-addr into master 2023-04-30 13:55:01 +00:00
29 changed files with 155 additions and 214 deletions

View file

@ -211,7 +211,6 @@ void CaptionDescription::Init(FeatureType & f, int8_t deviceLang, int const zoom
if (m_mainText.size() > kMaxTextSize)
m_mainText = m_mainText.substr(0, kMaxTextSize) + "...";
m_roadNumber = f.GetRoadNumber();
m_houseNumber = f.GetHouseNumber();
ProcessZoomLevel(zoomLevel);
@ -228,11 +227,6 @@ std::string const & CaptionDescription::GetAuxText() const
return m_auxText;
}
std::string const & CaptionDescription::GetRoadNumber() const
{
return m_roadNumber;
}
bool CaptionDescription::IsNameExists() const
{
return !m_mainText.empty() || !m_houseNumber.empty();

View file

@ -1,6 +1,5 @@
#pragma once
#include "indexer/feature_data.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/drawing_rule_def.hpp"
@ -31,7 +30,6 @@ struct CaptionDescription
std::string const & GetMainText() const;
std::string const & GetAuxText() const;
std::string const & GetRoadNumber() const;
bool IsNameExists() const;
bool IsHouseNumberInMainText() const { return m_isHouseNumberInMainText; }
@ -43,7 +41,6 @@ private:
std::string m_mainText;
std::string m_auxText;
std::string m_roadNumber;
std::string m_houseNumber;
bool m_isHouseNumberInMainText = false;
};

View file

@ -210,10 +210,14 @@ bool FeatureBuilder::PreSerialize()
if (!m_params.IsValid())
return false;
// Conform serialization logic (see HeaderMask::HEADER_MASK_HAS_ADDINFO):
// - rank (city) is stored only for Point
// - ref (road number, address range) is stored only for Line
// - house is stored for PointEx and Area
switch (m_params.GetGeomType())
{
case GeomType::Point:
// Store house number like HEADER_GEOM_POINT_EX.
// Store house number like HeaderGeomType::PointEx.
if (!m_params.house.IsEmpty())
{
m_params.SetGeomTypePointEx();
@ -222,7 +226,6 @@ bool FeatureBuilder::PreSerialize()
if (!m_params.ref.empty())
{
if (ftypes::IsMotorwayJunctionChecker::Instance()(GetTypes()) ||
(m_params.name.IsEmpty() &&
(ftypes::IsPostBoxChecker::Instance()(GetTypes()) ||
@ -232,9 +235,9 @@ bool FeatureBuilder::PreSerialize()
{
m_params.name.AddString(StringUtf8Multilang::kDefaultCode, m_params.ref);
}
}
m_params.ref.clear();
m_params.ref.clear();
}
break;
case GeomType::Line:

View file

@ -14,11 +14,11 @@
#include "indexer/classificator.hpp"
#include "indexer/data_source.hpp"
#include "indexer/feature_algo.hpp"
#include "indexer/feature_utils.hpp"
#include "indexer/feature_visibility.hpp"
#include "indexer/features_vector.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/postcodes_matcher.hpp"
#include "indexer/road_shields_parser.hpp"
#include "indexer/scales_patch.hpp"
#include "indexer/search_string_utils.hpp"
#include "indexer/trie_builder.hpp"
@ -314,7 +314,7 @@ public:
// Road number.
if (hasStreetType)
{
for (auto const & shield : feature::GetRoadShieldsNames(f.GetRoadNumber()))
for (auto const & shield : ftypes::GetRoadShieldsNames(f))
inserter(StringUtf8Multilang::kDefaultCode, shield);
}

View file

@ -128,15 +128,14 @@ void ScreenBase::SetAutoPerspective(bool isAutoPerspective)
void ScreenBase::SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect)
{
m2::RectD const & lRect = glbRect.GetLocalRect();
ASSERT(!lRect.IsEmptyInterior(), (lRect));
ASSERT(lRect.IsValid(), (lRect));
ASSERT(!pxRect.IsEmptyInterior(), (pxRect));
double const hScale = lRect.SizeX() / pxRect.SizeX();
double const vScale = lRect.SizeY() / pxRect.SizeY();
ASSERT_GREATER(hScale, 0.0, ());
ASSERT_GREATER(vScale, 0.0, ());
m_Scale = std::max(hScale, vScale);
ASSERT_GREATER(m_Scale, 0.0, ());
m_Angle = glbRect.Angle();
m_Org = glbRect.GlobalCenter();

View file

@ -823,7 +823,7 @@ uint8_t FeatureType::GetRank()
uint64_t FeatureType::GetPopulation() { return feature::RankToPopulation(GetRank()); }
string const & FeatureType::GetRoadNumber()
string const & FeatureType::GetRef()
{
ParseCommon();
return m_params.ref;

View file

@ -157,7 +157,7 @@ public:
uint8_t GetRank();
uint64_t GetPopulation();
std::string const & GetRoadNumber();
std::string const & GetRef();
feature::Metadata const & GetMetadata();

View file

@ -1,20 +1,13 @@
#include "indexer/feature_impl.hpp"
#include "base/string_utils.hpp"
#include "base/math.hpp"
namespace feature
{
using namespace std;
bool IsHouseNumber(string const & s)
{
return !s.empty() && strings::IsASCIIDigit(s[0]);
}
uint8_t PopulationToRank(uint64_t p)
{
return static_cast<uint8_t>(min(0xFF, base::SignedRound(log(double(p)) / log(1.1))));
return static_cast<uint8_t>(std::min(0xFF, base::SignedRound(log(double(p)) / log(1.1))));
}
uint64_t RankToPopulation(uint8_t r)

View file

@ -4,7 +4,6 @@
#include "base/assert.hpp"
#include <cstring>
#include <string>
namespace strings { class UniString; }
@ -21,8 +20,6 @@ inline std::string GetTagForIndex(std::string const & prefix, size_t ind)
return prefix + char('0' + ind);
}
bool IsHouseNumber(std::string const & s);
uint8_t PopulationToRank(uint64_t p);
uint64_t RankToPopulation(uint8_t r);
} // namespace feature

View file

@ -1,11 +1,9 @@
#include "indexer/feature_utils.hpp"
#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/feature_visibility.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/road_shields_parser.hpp"
#include "indexer/scales.hpp"
#include "platform/localization.hpp"
@ -13,7 +11,6 @@
#include "coding/string_utf8_multilang.hpp"
#include "coding/transliteration.hpp"
#include "base/base.hpp"
#include "base/control_flow.hpp"
#include <unordered_map>
@ -129,6 +126,10 @@ vector<int8_t> MakeLanguagesPriorityList(int8_t deviceLang, bool preferDefault)
if (preferDefault)
langPriority.push_back(StrUtf8::kDefaultCode);
/// @DebugNote
// Add ru lang for descriptions/rendering tests.
//langPriority.push_back(StrUtf8::GetLangIndex("ru"));
auto const similarLangs = GetSimilarLanguages(deviceLang);
langPriority.insert(langPriority.cend(), similarLangs.cbegin(), similarLangs.cend());
langPriority.insert(langPriority.cend(), {StrUtf8::kInternationalCode, StrUtf8::kEnglishCode});
@ -436,12 +437,4 @@ vector<string> GetLocalizedRecyclingTypes(TypesHolder const & types)
auto const & isRecyclingType = ftypes::IsRecyclingTypeChecker::Instance();
return GetLocalizedTypes(isRecyclingType, types);
}
vector<string> GetRoadShieldsNames(string const & rawRoadNumber)
{
vector<string> names;
for (auto && shield : ftypes::GetRoadShields(rawRoadNumber))
names.push_back(std::move(shield.m_name));
return names;
}
} // namespace feature

View file

@ -125,7 +125,4 @@ namespace feature
// Returns vector of recycling types localized by platform.
std::vector<std::string> GetLocalizedRecyclingTypes(TypesHolder const & types);
// Returns names of feature road shields. Applicable for road features.
std::vector<std::string> GetRoadShieldsNames(std::string const & rawRoadNumber);
} // namespace feature

View file

@ -385,7 +385,9 @@ IsStreetOrSquareChecker::IsStreetOrSquareChecker()
IsAddressObjectChecker::IsAddressObjectChecker() : BaseChecker(1 /* level */)
{
auto const paths = {"building", "amenity", "shop", "tourism", "historic", "office", "craft"};
base::StringIL const paths = {
"building", "amenity", "shop", "tourism", "historic", "office", "craft", "addr:interpolation"
};
Classificator const & c = classif();
for (auto const & p : paths)

View file

@ -4,6 +4,7 @@
#include "indexer/feature_algo.hpp"
#include "indexer/feature_utils.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/road_shields_parser.hpp"
#include "geometry/mercator.hpp"
@ -58,7 +59,7 @@ void MapObject::SetFromFeatureType(FeatureType & ft)
m_metadata = ft.GetMetadata();
m_houseNumber = ft.GetHouseNumber();
m_roadNumber = ft.GetRoadNumber();
m_roadShields = ftypes::GetRoadShieldsNames(ft);
m_featureID = ft.GetID();
m_geomType = ft.GetGeomType();
@ -159,14 +160,9 @@ string MapObject::FormatCuisines() const
return strings::JoinStrings(GetLocalizedCuisines(), kFieldsSeparator);
}
vector<string> MapObject::GetRoadShields() const
{
return feature::GetRoadShieldsNames(m_roadNumber);
}
string MapObject::FormatRoadShields() const
{
return strings::JoinStrings(GetRoadShields(), kFieldsSeparator);
return strings::JoinStrings(m_roadShields, kFieldsSeparator);
}
int MapObject::GetStars() const

View file

@ -87,7 +87,6 @@ public:
/// @returns translated and formatted cuisines.
std::string FormatCuisines() const;
std::vector<std::string> GetRoadShields() const;
std::string FormatRoadShields() const;
std::string_view GetOpeningHours() const;
@ -119,7 +118,7 @@ protected:
StringUtf8Multilang m_name;
std::string m_houseNumber;
std::string m_roadNumber;
std::vector<std::string> m_roadShields;
feature::TypesHolder m_types;
feature::Metadata m_metadata;

View file

@ -1,6 +1,7 @@
#include "indexer/road_shields_parser.hpp"
#include "indexer/feature.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "base/string_utils.hpp"
@ -582,8 +583,8 @@ public:
RoadShieldsSetT GetRoadShields(FeatureType & f)
{
std::string const roadNumber = f.GetRoadNumber();
if (roadNumber.empty())
auto const & ref = f.GetRef();
if (ref.empty())
return {};
// Find out country name.
@ -596,7 +597,7 @@ RoadShieldsSetT GetRoadShields(FeatureType & f)
if (underlinePos != std::string::npos)
mwmName = mwmName.substr(0, underlinePos);
return GetRoadShields(mwmName, roadNumber);
return GetRoadShields(mwmName, ref);
}
RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const & roadNumber)
@ -640,8 +641,19 @@ RoadShieldsSetT GetRoadShields(std::string const & rawRoadNumber)
if (rawRoadNumber.empty())
return {};
return SimpleRoadShieldParser(rawRoadNumber, SimpleRoadShieldParser::ShieldTypes())
.GetRoadShields();
return SimpleRoadShieldParser(rawRoadNumber, SimpleRoadShieldParser::ShieldTypes()).GetRoadShields();
}
std::vector<std::string> GetRoadShieldsNames(FeatureType & ft)
{
std::vector<std::string> names;
auto const & ref = ft.GetRef();
if (!ref.empty() && IsStreetOrSquareChecker::Instance()(ft))
{
for (auto && shield : GetRoadShields(ref))
names.push_back(std::move(shield.m_name));
}
return names;
}
std::string DebugPrint(RoadShieldType shieldType)

View file

@ -65,6 +65,9 @@ RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const &
// Simple parsing without specific country styles.
RoadShieldsSetT GetRoadShields(std::string const & rawRoadNumber);
// Returns names of road shields if |ft| is a "highway" feature.
std::vector<std::string> GetRoadShieldsNames(FeatureType & ft);
std::string DebugPrint(RoadShieldType shieldType);
std::string DebugPrint(RoadShield const & shield);
} // namespace ftypes

View file

@ -91,7 +91,7 @@ static PlacePageDataHotelType convertHotelType(std::optional<ftypes::IsHotelChec
_title = rawData.GetTitle().empty() ? nil : @(rawData.GetTitle().c_str());
_secondaryTitle = rawData.GetSecondaryTitle().empty() ? nil : @(rawData.GetSecondaryTitle().c_str());
_subtitle = rawData.GetSubtitle().empty() ? nil : @(rawData.GetSubtitle().c_str());
_coordinates = rawData.GetFormattedCoordinate(true).empty() ? nil : @(rawData.GetFormattedCoordinate(true).c_str());
_coordinates = @(rawData.GetFormattedCoordinate(true).c_str());
_address = rawData.GetAddress().empty() ? nil : @(rawData.GetAddress().c_str());
_isMyPosition = rawData.IsMyPosition();
_isPopular = rawData.GetPopularity() > 0;

View file

@ -12,7 +12,6 @@ set(SRC
bookmark_manager.cpp
bookmark_manager.hpp
bookmarks_search_params.hpp
caching_address_getter.hpp
chart_generator.cpp
chart_generator.hpp
elevation_info.cpp

View file

@ -1,34 +0,0 @@
#pragma once
#include "search/reverse_geocoder.hpp"
// TODO: get rid of this class when version 8.6 will not be supported.
// TODO: because of fast algorithm and new mwm section which were implemented for 9.0.
// Note: this class is NOT thread-safe.
class CachingAddressGetter
{
public:
search::ReverseGeocoder::Address GetAddressAtPoint(DataSource const & dataSource,
m2::PointD const & pt,
double distanceThresholdMeters) const
{
if (pt.EqualDxDy(m_cache.m_point, kMwmPointAccuracy))
return m_cache.m_address;
m_cache.m_point = pt;
m_cache.m_address = {};
search::ReverseGeocoder const coder(dataSource);
coder.GetNearbyAddress(pt, distanceThresholdMeters, m_cache.m_address);
return m_cache.m_address;
}
private:
struct Cache
{
m2::PointD m_point;
search::ReverseGeocoder::Address m_address;
};
mutable Cache m_cache;
};

View file

@ -589,10 +589,13 @@ void Framework::FillTrackInfo(Track const & track, m2::PointD const & trackPoint
info.SetMercator(trackPoint);
}
search::ReverseGeocoder::Address Framework::GetAddressAtPoint(m2::PointD const & pt,
double distanceThresholdMeters) const
search::ReverseGeocoder::Address Framework::GetAddressAtPoint(m2::PointD const & pt) const
{
return m_addressGetter.GetAddressAtPoint(m_featuresFetcher.GetDataSource(), pt, distanceThresholdMeters);
search::ReverseGeocoder const coder(m_featuresFetcher.GetDataSource());
search::ReverseGeocoder::Address addr;
/// @todo Call exact address manually here?
coder.GetNearbyAddress(pt, 0.5 /* maxDistanceM */, addr);
return addr;
}
void Framework::FillFeatureInfo(FeatureID const & fid, place_page::Info & info) const

View file

@ -3,7 +3,6 @@
#include "map/api_mark_point.hpp"
#include "map/bookmark.hpp"
#include "map/bookmark_manager.hpp"
#include "map/caching_address_getter.hpp"
#include "map/features_fetcher.hpp"
#include "map/isolines_manager.hpp"
#include "map/mwm_url.hpp"
@ -598,8 +597,7 @@ private:
void FillDescription(FeatureType & ft, place_page::Info & info) const;
public:
search::ReverseGeocoder::Address GetAddressAtPoint(m2::PointD const & pt,
double distanceThresholdMeters = 0.5) const;
search::ReverseGeocoder::Address GetAddressAtPoint(m2::PointD const & pt) const;
/// Get "best for the user" feature at given point even if it's invisible on the screen.
/// Ignores coastlines and prefers buildings over other area features.
@ -714,7 +712,6 @@ public:
std::string const & note);
private:
CachingAddressGetter m_addressGetter;
settings::UsageStats m_usageStats;
public:

View file

@ -89,7 +89,8 @@ void DirectionsEngine::LoadPathAttributes(FeatureID const & featureId,
pathSegment.m_roadNameInfo.m_junction_ref = ft->GetMetadata(feature::Metadata::FMD_JUNCTION_REF);
pathSegment.m_roadNameInfo.m_destination_ref = ft->GetMetadata(feature::Metadata::FMD_DESTINATION_REF);
pathSegment.m_roadNameInfo.m_destination = ft->GetMetadata(feature::Metadata::FMD_DESTINATION);
pathSegment.m_roadNameInfo.m_ref = ft->GetRoadNumber();
/// @todo Should make some better parsing here (@see further use in GetFullRoadName).
pathSegment.m_roadNameInfo.m_ref = ft->GetRef();
pathSegment.m_roadNameInfo.m_name = ft->GetName(StringUtf8Multilang::kDefaultCode);
}

View file

@ -115,7 +115,7 @@ private:
{
auto const interpol = ftypes::IsAddressInterpolChecker::Instance().GetInterpolType(feature);
if (interpol != feature::InterpolType::None)
return house_numbers::HouseNumbersMatchRange(feature.GetRoadNumber(), queryParse, interpol);
return house_numbers::HouseNumbersMatchRange(feature.GetRef(), queryParse, interpol);
else
return house_numbers::HouseNumbersMatch(strings::MakeUniString(feature.GetHouseNumber()), queryParse);
}

View file

@ -1,10 +1,5 @@
#include "house_detector.hpp"
#include "search/algos.hpp"
#include "search/common.hpp"
#include "indexer/classificator.hpp"
#include "indexer/feature_impl.hpp"
#include "indexer/search_string_utils.hpp"
#include "platform/platform.hpp"
@ -12,7 +7,6 @@
#include "coding/string_utf8_multilang.hpp"
#include "geometry/angles.hpp"
#include "geometry/parametrized_segment.hpp"
#include "base/limited_priority_queue.hpp"
#include "base/logging.hpp"
@ -30,13 +24,14 @@
#include <boost/iterator/transform_iterator.hpp>
namespace search
{
using namespace std;
using namespace std::placeholders;
using boost::make_transform_iterator;
namespace search
{
namespace
{
#if 0
@ -1092,38 +1087,36 @@ HouseProjection const * MergedStreet::GetHousePivot(bool isOdd, bool & sign) con
template <typename ProjectionCalculator>
void HouseDetector::ReadHouse(FeatureType & f, Street * st, ProjectionCalculator & calc)
{
string const houseNumber = f.GetHouseNumber();
string const & hn = f.GetHouseNumber();
if (hn.empty() || !ftypes::IsBuildingChecker::Instance()(f))
return;
/// @todo After new data generation we can skip IsHouseNumber check here.
if (ftypes::IsBuildingChecker::Instance()(f) && feature::IsHouseNumber(houseNumber))
auto const it = m_id2house.find(f.GetID());
bool const isNew = it == m_id2house.end();
m2::PointD const pt =
isNew ? f.GetLimitRect(FeatureType::BEST_GEOMETRY).Center() : it->second->GetPosition();
HouseProjection pr;
if (calc.GetProjection(pt, pr) && pr.m_distMeters <= m_houseOffsetM)
{
auto const it = m_id2house.find(f.GetID());
bool const isNew = it == m_id2house.end();
pr.m_streetDistance =
st->GetPrefixLength(pr.m_segIndex) + st->m_points[pr.m_segIndex].Length(pr.m_proj);
m2::PointD const pt =
isNew ? f.GetLimitRect(FeatureType::BEST_GEOMETRY).Center() : it->second->GetPosition();
HouseProjection pr;
if (calc.GetProjection(pt, pr) && pr.m_distMeters <= m_houseOffsetM)
House * p;
if (isNew)
{
pr.m_streetDistance =
st->GetPrefixLength(pr.m_segIndex) + st->m_points[pr.m_segIndex].Length(pr.m_proj);
House * p;
if (isNew)
{
p = new House(houseNumber, pt);
m_id2house[f.GetID()] = p;
}
else
{
p = it->second;
ASSERT(p != 0, ());
}
pr.m_house = p;
st->m_houses.push_back(pr);
p = new House(hn, pt);
m_id2house[f.GetID()] = p;
}
else
{
p = it->second;
ASSERT(p != 0, ());
}
pr.m_house = p;
st->m_houses.push_back(pr);
}
}

View file

@ -11,6 +11,7 @@
#include "indexer/feature_utils.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/map_object.hpp"
#include "indexer/road_shields_parser.hpp"
#include "platform/measurement_utils.hpp"
@ -292,7 +293,7 @@ void FillDetails(FeatureType & ft, Result::Details & details)
auto const cuisines = feature::GetLocalizedCuisines(feature::TypesHolder(ft));
details.m_cuisine = strings::JoinStrings(cuisines, osm::MapObject::kFieldsSeparator);
auto const roadShields = feature::GetRoadShieldsNames(ft.GetRoadNumber());
auto const roadShields = ftypes::GetRoadShieldsNames(ft);
details.m_roadShields = strings::JoinStrings(roadShields, osm::MapObject::kFieldsSeparator);
details.m_isInitialized = true;

View file

@ -15,8 +15,8 @@
#include "indexer/data_source.hpp"
#include "indexer/feature_algo.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/feature_utils.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "indexer/road_shields_parser.hpp"
#include "indexer/search_string_utils.hpp"
#include "coding/string_utf8_multilang.hpp"
@ -170,7 +170,7 @@ NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params,
if (type == Model::TYPE_STREET)
{
for (auto const & shield : feature::GetRoadShieldsNames(ft.GetRoadNumber()))
for (auto const & shield : ftypes::GetRoadShieldsNames(ft))
UpdateNameScores(shield, StringUtf8Multilang::kDefaultCode, sliceNoCategories, bestScores);
}
@ -278,7 +278,8 @@ string FormatStreetAndHouse(ReverseGeocoder::Address const & addr)
// TODO: Share common formatting code for search results and place page.
string FormatFullAddress(ReverseGeocoder::Address const & addr, string const & region)
{
// TODO: Print "near" for not exact addresses.
/// @todo Print "near" for not exact addresses.
/// Add some threshold for addr:interpolation or refactor ReverseGeocoder?
if (addr.GetDistance() != 0)
return region;
@ -305,47 +306,6 @@ bool ResultExists(RankerResult const & p, vector<RankerResult> const & results,
return find_if(results.begin(), results.end(), equalCmp) != results.cend();
}
class LazyAddressGetter
{
public:
LazyAddressGetter(ReverseGeocoder const & reverseGeocoder, m2::PointD const & center)
: m_reverseGeocoder(reverseGeocoder), m_center(center)
{
}
ReverseGeocoder::Address const & GetNearbyAddress()
{
if (m_computedNearby)
return m_address;
m_reverseGeocoder.GetNearbyAddress(m_center, m_address);
m_computedNearby = true;
return m_address;
}
bool GetExactAddress(ReverseGeocoder::Address & address)
{
if (m_computedExact)
{
address = m_address;
return true;
}
m_reverseGeocoder.GetNearbyAddress(m_center, 0.0, m_address);
if (m_address.IsValid())
{
m_computedExact = true;
m_computedNearby = true;
address = m_address;
}
return m_computedExact;
}
private:
ReverseGeocoder const & m_reverseGeocoder;
m2::PointD const m_center;
ReverseGeocoder::Address m_address;
bool m_computedExact = false;
bool m_computedNearby = false;
};
} // namespace
class RankerResultMaker
@ -453,6 +413,15 @@ private:
return ft;
}
bool GetExactAddress(FeatureType & ft, m2::PointD const & center, ReverseGeocoder::Address & addr) const
{
if (m_reverseGeocoder.GetExactAddress(ft, addr))
return true;
m_reverseGeocoder.GetNearbyAddress(center, 0.0 /* maxDistanceM */, addr);
return addr.IsValid();
}
// For the best performance, incoming ids should be sorted by id.first (mwm file id).
unique_ptr<FeatureType> LoadFeature(FeatureID const & id, m2::PointD & center, string & name,
string & country)
@ -475,7 +444,7 @@ private:
if (name.empty())
{
ReverseGeocoder::Address addr;
if (LazyAddressGetter(m_reverseGeocoder, center).GetExactAddress(addr))
if (GetExactAddress(*ft, center, addr))
{
unique_ptr<FeatureType> streetFeature;
@ -721,7 +690,13 @@ Result Ranker::MakeResult(RankerResult const & rankerResult, bool needAddress, b
// Format full address only for suitable results.
if (ftypes::IsAddressObjectChecker::Instance()(rankerResult.GetTypes()))
address = FormatFullAddress(LazyAddressGetter(m_reverseGeocoder, rankerResult.GetCenter()).GetNearbyAddress(), address);
{
ReverseGeocoder::Address addr;
if (!(rankerResult.GetID().IsValid() && m_reverseGeocoder.GetExactAddress(rankerResult.GetID(), addr)))
m_reverseGeocoder.GetNearbyAddress(rankerResult.GetCenter(), addr);
address = FormatFullAddress(addr, address);
}
res.SetAddress(std::move(address));
}
@ -991,4 +966,5 @@ string Ranker::GetLocalizedRegionInfoForResult(RankerResult const & result) cons
return m_regionInfoGetter.GetLocalizedFullName(id);
}
} // namespace search

View file

@ -77,6 +77,20 @@ string Join(string const & s, Args &&... args)
return s;
return s + ", " + tail;
}
ReverseGeocoder::Building FromFeatureImpl(FeatureType & ft, std::string const & hn, double distMeters)
{
return { ft.GetID(), distMeters, hn, feature::GetCenter(ft) };
}
std::string const & GetHouseNumber(FeatureType & ft)
{
std::string const & hn = ft.GetHouseNumber();
if (hn.empty() && ftypes::IsAddressInterpolChecker::Instance()(ft))
return ft.GetRef();
return hn;
}
} // namespace
ReverseGeocoder::ReverseGeocoder(DataSource const & dataSource) : m_dataSource(dataSource) {}
@ -217,11 +231,10 @@ bool ReverseGeocoder::GetOriginalStreetByHouse(FeatureType & house, FeatureID &
void ReverseGeocoder::GetNearbyAddress(m2::PointD const & center, Address & addr) const
{
return GetNearbyAddress(center, kLookupRadiusM, addr);
GetNearbyAddress(center, kLookupRadiusM, addr);
}
void ReverseGeocoder::GetNearbyAddress(m2::PointD const & center, double maxDistanceM,
Address & addr) const
void ReverseGeocoder::GetNearbyAddress(m2::PointD const & center, double maxDistanceM, Address & addr) const
{
vector<Building> buildings;
GetNearbyBuildings(center, maxDistanceM, buildings);
@ -241,11 +254,12 @@ void ReverseGeocoder::GetNearbyAddress(m2::PointD const & center, double maxDist
bool ReverseGeocoder::GetExactAddress(FeatureType & ft, Address & addr) const
{
if (ft.GetHouseNumber().empty())
std::string const & hn = GetHouseNumber(ft);
if (hn.empty())
return false;
HouseTable table(m_dataSource);
return GetNearbyAddress(table, FromFeature(ft, 0.0 /* distMeters */), false /* ignoreEdits */,
addr);
return GetNearbyAddress(table, FromFeatureImpl(ft, hn, 0.0 /* distMeters */), false /* ignoreEdits */, addr);
}
bool ReverseGeocoder::GetExactAddress(FeatureID const & fid, Address & addr) const
@ -311,10 +325,15 @@ bool ReverseGeocoder::GetNearbyAddress(HouseTable & table, Building const & bld,
void ReverseGeocoder::GetNearbyBuildings(m2::PointD const & center, double radius,
vector<Building> & buildings) const
{
auto const addBuilding = [&](FeatureType & ft) {
auto const addBuilding = [&](FeatureType & ft)
{
std::string const & hn = GetHouseNumber(ft);
if (hn.empty())
return;
auto const distance = feature::GetMinDistanceMeters(ft, center);
if (!ft.GetHouseNumber().empty() && distance <= radius)
buildings.push_back(FromFeature(ft, distance));
if (distance <= radius)
buildings.push_back(FromFeatureImpl(ft, hn, distance));
};
auto const stop = [&]() { return buildings.size() >= kMaxNumTriesToApproxAddress; };
@ -371,7 +390,7 @@ string ReverseGeocoder::GetLocalizedRegionAddress(RegionAddress const & addr,
// static
ReverseGeocoder::Building ReverseGeocoder::FromFeature(FeatureType & ft, double distMeters)
{
return { ft.GetID(), distMeters, ft.GetHouseNumber(), feature::GetCenter(ft) };
return FromFeatureImpl(ft, ft.GetHouseNumber(), distMeters);
}
std::optional<HouseToStreetTable::Result> ReverseGeocoder::HouseTable::Get(FeatureID const & fid)

View file

@ -5,6 +5,7 @@
#include "indexer/feature.hpp"
#include "indexer/feature_algo.hpp"
#include "indexer/road_shields_parser.hpp"
#include "indexer/search_string_utils.hpp"
#include "base/control_flow.hpp"
@ -151,10 +152,6 @@ bool Matcher::Matches(strings::UniString const & query, Sample::Result const & g
bool Matcher::Matches(strings::UniString const & query, Sample::Result const & golden,
FeatureType & ft)
{
static double constexpr kToleranceMeters = 50;
auto const houseNumber = ft.GetHouseNumber();
auto const queryTokens = NormalizeAndTokenizeAsUtf8(ToUtf8(query));
bool nameMatches = false;
@ -166,7 +163,14 @@ bool Matcher::Matches(strings::UniString const & query, Sample::Result const & g
{
if (ft.GetGeomType() == feature::GeomType::Line)
{
nameMatches = StreetMatches(ft.GetRoadNumber(), queryTokens);
for (auto const & name : ftypes::GetRoadShieldsNames(ft))
{
if (StreetMatches(name, queryTokens))
{
nameMatches = true;
break;
}
}
}
else
{
@ -195,10 +199,11 @@ bool Matcher::Matches(strings::UniString const & query, Sample::Result const & g
});
bool houseNumberMatches = true;
if (!golden.m_houseNumber.empty() && !houseNumber.empty())
houseNumberMatches = golden.m_houseNumber == houseNumber;
std::string const & hn = ft.GetHouseNumber();
if (!golden.m_houseNumber.empty() && !hn.empty())
houseNumberMatches = golden.m_houseNumber == hn;
return (nameMatches && houseNumberMatches &&
feature::GetMinDistanceMeters(ft, golden.m_pos) < kToleranceMeters);
/// @todo Where are 50 meters came from?
return (nameMatches && houseNumberMatches && feature::GetMinDistanceMeters(ft, golden.m_pos) < 50.0);
}
} // namespace search

View file

@ -215,12 +215,9 @@ m2::RectD GenerateNearbyViewport(m2::PointD const & point)
bool GetBuildingInfo(FeatureType & ft, search::ReverseGeocoder const & coder, string & street)
{
auto const houseNumber = ft.GetHouseNumber();
if (houseNumber.empty() ||
!search::house_numbers::LooksLikeHouseNumber(houseNumber, false /* prefix */))
{
std::string const & hn = ft.GetHouseNumber();
if (hn.empty() || !search::house_numbers::LooksLikeHouseNumber(hn, false /* prefix */))
return false;
}
street = coder.GetFeatureStreetName(ft);
if (street.empty())
@ -323,9 +320,8 @@ optional<Sample> GenerateRequest(
}
}
auto const house = ft.GetHouseNumber();
auto const featureCenter = feature::GetCenter(ft);
auto const address = ModifyAddress(street, house, lang);
auto const address = ModifyAddress(std::move(street), ft.GetHouseNumber(), lang);
auto query = address;
if (!cafeStr.empty())
query = FLAGS_add_cafe_address ? CombineRandomly(cafeStr, address) : cafeStr;