[search] Implemented search by POI with house numbers.

This commit is contained in:
Yuri Gorshenin 2016-02-12 12:22:12 +03:00 committed by Sergey Yershov
parent f2b7db27f1
commit 58df58f385
6 changed files with 121 additions and 41 deletions

View file

@ -149,7 +149,11 @@ UNIT_CLASS_TEST(SearchQueryV2Test, Smoke)
TestPOI busStop(m2::PointD(0, 0), "Bus stop", "en");
TestPOI tramStop(m2::PointD(0.0001, 0.0001), "Tram stop", "en");
TestPOI quantumTeleport1(m2::PointD(0.0002, 0.0002), "Quantum teleport 1", "en");
TestPOI quantumTeleport2(m2::PointD(10, 10), "Quantum teleport 2", "en");
quantumTeleport2.SetHouseNumber("3");
quantumTeleport2.SetStreet(feynmanStreet);
TestPOI quantumCafe(m2::PointD(-0.0002, -0.0002), "Quantum cafe", "en");
TestPOI lantern1(m2::PointD(10.0005, 10.0005), "lantern 1", "en");
TestPOI lantern2(m2::PointD(10.0006, 10.0005), "lantern 2", "en");
@ -214,6 +218,10 @@ UNIT_CLASS_TEST(SearchQueryV2Test, Smoke)
TRules rules = {make_shared<ExactMatch>(wonderlandId, quantumTeleport2)};
TEST(ResultsMatch("teleport feynman street", rules), ());
}
{
TRules rules = {make_shared<ExactMatch>(wonderlandId, quantumTeleport2)};
TEST(ResultsMatch("feynman street 3", rules), ());
}
{
TRules rules = {make_shared<ExactMatch>(wonderlandId, feynmanHouse),
make_shared<ExactMatch>(wonderlandId, lantern1)};

View file

@ -4,6 +4,7 @@
#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_algo.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "coding/multilang_utf8_string.hpp"
@ -16,6 +17,11 @@ namespace search
{
namespace tests_support
{
namespace
{
double const kTestPrecision = 1e-4;
} // namespace
// TestFeature -------------------------------------------------------------------------------------
TestFeature::TestFeature(string const & name, string const & lang)
: m_center(0, 0), m_hasCenter(false), m_name(name), m_lang(lang)
@ -38,27 +44,16 @@ bool TestFeature::Matches(FeatureType const & feature) const
{
uint8_t const langIndex = StringUtf8Multilang::GetLangIndex(m_lang);
string name;
return feature.GetName(langIndex, name) && m_name == name;
}
// TestPOI -----------------------------------------------------------------------------------------
TestPOI::TestPOI(m2::PointD const & center, string const & name, string const & lang)
: TestFeature(center, name, lang)
{
}
void TestPOI::Serialize(FeatureBuilder1 & fb) const
{
TestFeature::Serialize(fb);
auto const & classificator = classif();
fb.SetType(classificator.GetTypeByPath({"railway", "station"}));
}
string TestPOI::ToString() const
{
ostringstream os;
os << "TestPOI [" << m_name << ", " << m_lang << ", " << DebugPrint(m_center) << "]";
return os.str();
bool const nameMatches = feature.GetName(langIndex, name) && m_name == name;
if (!nameMatches)
return false;
if (m_hasCenter)
{
auto const center = feature::GetCenter(feature);
if (!m_center.EqualDxDy(center, kTestPrecision))
return false;
}
return true;
}
// TestCountry -------------------------------------------------------------------------------------
@ -153,6 +148,40 @@ string TestStreet::ToString() const
return os.str();
}
// TestPOI -----------------------------------------------------------------------------------------
TestPOI::TestPOI(m2::PointD const & center, string const & name, string const & lang)
: TestFeature(center, name, lang)
{
}
void TestPOI::Serialize(FeatureBuilder1 & fb) const
{
TestFeature::Serialize(fb);
auto const & classificator = classif();
fb.SetType(classificator.GetTypeByPath({"railway", "station"}));
if (!m_houseNumber.empty())
fb.AddHouseNumber(m_houseNumber);
if (!m_streetName.empty())
fb.AddStreet(m_streetName);
}
bool TestPOI::Matches(FeatureType const & feature) const
{
return TestFeature::Matches(feature) && m_houseNumber == feature.GetHouseNumber();
}
string TestPOI::ToString() const
{
ostringstream os;
os << "TestPOI [" << m_name << ", " << m_lang << ", " << DebugPrint(m_center);
if (!m_houseNumber.empty())
os << ", " << m_houseNumber;
if (!m_streetName.empty())
os << ", " << m_streetName;
os << "]";
return os.str();
}
// TestBuilding ------------------------------------------------------------------------------------
TestBuilding::TestBuilding(m2::PointD const & center, string const & name,
string const & houseNumber, string const & lang)
@ -177,6 +206,7 @@ TestBuilding::TestBuilding(vector<m2::PointD> const & boundary, string const & n
, m_houseNumber(houseNumber)
, m_streetName(street.GetName())
{
ASSERT(!m_boundary.empty(), ());
}
void TestBuilding::Serialize(FeatureBuilder1 & fb) const
@ -201,7 +231,22 @@ bool TestBuilding::Matches(FeatureType const & feature) const
auto const & checker = ftypes::IsBuildingChecker::Instance();
if (!checker(feature))
return false;
return TestFeature::Matches(feature) && m_houseNumber == feature.GetHouseNumber();
if (!TestFeature::Matches(feature))
return false;
if (m_houseNumber != feature.GetHouseNumber())
return false;
// TODO(@y): consider to check m_boundary.
if (!m_hasCenter && !m_boundary.empty())
{
m2::PointD center(0, 0);
for (auto const & p : m_boundary)
center += p;
center = center / m_boundary.size();
if (!center.EqualDxDy(feature::GetCenter(feature), kTestPrecision))
return false;
}
return true;
}
string TestBuilding::ToString() const

View file

@ -33,16 +33,6 @@ protected:
string const m_lang;
};
class TestPOI : public TestFeature
{
public:
TestPOI(m2::PointD const & center, string const & name, string const & lang);
// TestFeature overrides:
void Serialize(FeatureBuilder1 & fb) const override;
string ToString() const override;
};
class TestCountry : public TestFeature
{
public:
@ -92,6 +82,24 @@ private:
vector<m2::PointD> m_points;
};
class TestPOI : public TestFeature
{
public:
TestPOI(m2::PointD const & center, string const & name, string const & lang);
// TestFeature overrides:
void Serialize(FeatureBuilder1 & fb) const override;
bool Matches(FeatureType const & feature) const override;
string ToString() const override;
inline void SetHouseNumber(string const & houseNumber) { m_houseNumber = houseNumber; }
inline void SetStreet(TestStreet const & street) { m_streetName = street.GetName(); }
private:
string m_houseNumber;
string m_streetName;
};
class TestBuilding : public TestFeature
{
public:
@ -107,7 +115,7 @@ public:
bool Matches(FeatureType const & feature) const override;
string ToString() const override;
protected:
private:
vector<m2::PointD> const m_boundary;
string const m_houseNumber;
string const m_streetName;

View file

@ -239,7 +239,6 @@ private:
vector<strings::UniString> queryTokens;
NormalizeHouseNumber(child.m_subQuery, queryTokens);
auto const & checker = ftypes::IsBuildingChecker::Instance();
uint32_t numFilterInvocations = 0;
auto houseNumberFilter = [&](uint32_t id, FeatureType & feature, bool & loaded) -> bool
{
@ -262,9 +261,6 @@ private:
loaded = true;
}
if (!checker(feature))
return false;
if (!child.m_hasDelayedFeatures)
return false;

View file

@ -1,6 +1,7 @@
#include "search/v2/search_model.hpp"
#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "base/macros.hpp"
@ -21,7 +22,7 @@ public:
{
Classificator const & c = classif();
auto paths = { "amenity", "historic", "office", "railway", "shop", "sport", "tourism", "craft" };
auto paths = {"amenity", "historic", "office", "railway", "shop", "sport", "tourism", "craft"};
for (auto const & path : paths)
m_types.push_back(c.GetTypeByPath({path}));
}
@ -54,6 +55,21 @@ private:
OneLevelPOIChecker const m_oneLevel;
TwoLevelPOIChecker const m_twoLevel;
};
class CustomIsBuildingChecker
{
public:
static CustomIsBuildingChecker const & Instance()
{
static const CustomIsBuildingChecker inst;
return inst;
}
bool operator()(FeatureType const & ft) const { return !ft.GetHouseNumber().empty(); }
private:
CustomIsBuildingChecker() {}
};
} // namespace
// static
@ -65,7 +81,7 @@ SearchModel const & SearchModel::Instance()
SearchModel::SearchType SearchModel::GetSearchType(FeatureType const & feature) const
{
static auto const & buildingChecker = IsBuildingChecker::Instance();
static auto const & buildingChecker = CustomIsBuildingChecker::Instance();
static auto const & streetChecker = IsStreetChecker::Instance();
static auto const & localityChecker = IsLocalityChecker::Instance();
static auto const & poiChecker = IsPoiChecker::Instance();

View file

@ -24,11 +24,18 @@ class SearchModel
public:
enum SearchType
{
// Low-level features such as amenities, offices, shops, buildings
// without house number, etc.
SEARCH_TYPE_POI,
// All features with set house number.
SEARCH_TYPE_BUILDING,
SEARCH_TYPE_STREET,
SEARCH_TYPE_UNCLASSIFIED, // all low-level features except POI,
// BUILDING and STREET
// All low-level features except POI, BUILDING and STREET.
SEARCH_TYPE_UNCLASSIFIED,
SEARCH_TYPE_VILLAGE,
SEARCH_TYPE_CITY,
SEARCH_TYPE_STATE, // US or Canadian states