[search] Compare Street names and House numbers

This commit is contained in:
Kirill Zhdanovich 2013-12-05 23:42:18 +01:00 committed by Alex Zolotarev
parent d18a824355
commit fec57ec157
3 changed files with 142 additions and 18 deletions

View file

@ -7,7 +7,6 @@
#include "../geometry/distance.hpp"
#include "../geometry/distance_on_sphere.hpp"
#include "../std/iostream.hpp"
#include "../std/set.hpp"
#include "../std/bind.hpp"
@ -15,9 +14,55 @@
namespace search
{
string affics1[] =
{
"аллея", "бульвар", "набережная",
"переулок", "площадь", "проезд",
"проспект", "шоссе", "тупик", "улица"
};
string affics2[] =
{
"ал.", "бул.", "наб.", "пер.",
"пл.", "пр.", "просп.", "ш.",
"туп.", "ул."
};
void GetStreetName(strings::SimpleTokenizer iter, string & streetName)
{
while(iter)
{
bool flag = true;
for (size_t i = 0; i < ARRAY_SIZE(affics2); ++i)
{
if (*iter == affics2[i] || *iter == affics1[i])
{
flag = false;
break;
}
}
if (flag)
streetName += *iter;
++iter;
}
}
int const BUILDING_PROCESS_SCALE = 15;
double const STREET_CONNECTION_LENGTH_M = 25.0;
void House::InitHouseNumberAndSuffix()
{
m_suffix = "";
m_intNumber = 0;
for (int i = 0; i < m_number.size(); ++i)
if (m_number[i] < '0' || m_number[i] > '9')
{
strings::to_int(m_number.substr(0, i), m_intNumber);
m_suffix = m_number.substr(i, m_number.size() - i);
return;
}
strings::to_int(m_number, m_intNumber);
}
struct StreetCreator
{
@ -75,6 +120,13 @@ m2::RectD Street::GetLimitRect(double offsetMeters) const
return rect;
}
void Street::SetName(string const & name)
{
m_name = name;
strings::SimpleTokenizer iter(name, " -");
GetStreetName(iter, m_processedName);
strings::MakeLowerCase(m_processedName);
}
HouseDetector::HouseDetector(Index const * pIndex)
: m_loader(pIndex), m_end2st(LessWithEpsilon(&m_epsMercator)), m_streetNum(0)
@ -96,7 +148,7 @@ void HouseDetector::FillQueue(queue<Street *> & q, Street const * street, bool i
for (IterT it = range.first; it != range.second; ++it)
{
/// @todo create clever street names compare functions
if (it->second->m_number == -1 && street->m_name == it->second->m_name)
if (it->second->m_number == -1 && street->GetName() == it->second->GetName())
{
it->second->m_number = m_streetNum;
q.push(it->second);
@ -137,7 +189,7 @@ void HouseDetector::LoadStreets(vector<FeatureID> & ids)
continue;
Street * st = new Street();
st->m_name = name;
st->SetName(name);
f.ForEachPoint(StreetCreator(st), FeatureType::BEST_GEOMETRY);
m_id2st[ids[i]] = st;
@ -258,7 +310,7 @@ void HouseDetector::ReadHouse(FeatureType const & f, Street * st, ProjectionCalc
map<FeatureID, House *>::iterator const it = m_id2house.find(f.GetID());
m2::PointD const pt = (it == m_id2house.end()) ?
f.GetLimitRect(BUILDING_PROCESS_SCALE).Center() : it->second->m_point;
f.GetLimitRect(BUILDING_PROCESS_SCALE).Center() : it->second->GetPosition();
HouseProjection pr;
if (calc.GetProjection(pt, pr))
@ -266,9 +318,7 @@ void HouseDetector::ReadHouse(FeatureType const & f, Street * st, ProjectionCalc
House * p;
if (it == m_id2house.end())
{
p = new House();
p->m_point = pt;
p->m_number = f.GetHouseNumber();
p = new House(f.GetHouseNumber(), pt);
m_id2house[f.GetID()] = p;
}
else
@ -312,7 +362,7 @@ void HouseDetector::MatchAllHouses(string const & houseNumber, vector<HouseProje
for (size_t i = 0; i < st->m_houses.size(); ++i)
{
House const * house = st->m_houses[i].m_house;
if (house->m_number == houseNumber && s.count(house) == 0)
if (house->GetNumber() == houseNumber && s.count(house) == 0)
{
res.push_back(st->m_houses[i]);
s.insert(house);

View file

@ -7,11 +7,11 @@
#include "../std/string.hpp"
#include "../std/queue.hpp"
#include "../std/iostream.hpp"
namespace search
{
class FeatureLoader
{
Index const * m_pIndex;
@ -29,10 +29,31 @@ public:
template <class ToDo> void ForEachInRect(m2::RectD const & rect, ToDo toDo);
};
struct House
class House
{
string m_number;
m2::PointD m_point;
int m_intNumber;
string m_suffix;
void InitHouseNumberAndSuffix();
public:
string const & GetNumber() const { return m_number; }
m2::PointD const & GetPosition() const { return m_point; }
House(string const & number, m2::PointD const & point)
{
m_number = number;
m_point = point;
InitHouseNumberAndSuffix();
}
inline static bool LessHouseNumber(House const & h1, House const & h2)
{
if (h1.m_intNumber == h2.m_intNumber)
return h1.m_suffix < h2.m_suffix;
return h1.m_intNumber < h2.m_intNumber;
}
};
struct HouseProjection
@ -41,16 +62,22 @@ struct HouseProjection
m2::PointD m_proj;
double m_distance;
static bool LessDistance(HouseProjection const & r1, HouseProjection const & r2)
inline static bool LessDistance(HouseProjection const & r1, HouseProjection const & r2)
{
return r1.m_distance < r2.m_distance;
}
};
// many features combines to street
struct Street
class Street
{
string m_name;
string m_processedName;
public:
void SetName(string const & name);
string const & GetName() const { return m_name; }
vector<m2::PointD> m_points;
vector<HouseProjection> m_houses;
@ -61,6 +88,11 @@ struct Street
/// Get limit rect for street with ortho offset to the left and right.
m2::RectD GetLimitRect(double offsetMeters) const;
inline static bool IsSameStreets(Street const & s1, Street const & s2)
{
return s1.m_processedName == s2.m_processedName;
}
};
class HouseDetector
@ -103,6 +135,7 @@ private:
void SetMetres2Mercator(double factor);
public:
HouseDetector(Index const * pIndex);
void LoadStreets(vector<FeatureID> & ids);

View file

@ -180,8 +180,8 @@ UNIT_TEST(SEARCH_HOUSE_NUMBER_SMOKE_TEST)
string houseName = "7";
GetCanditates(index, streetName, houseName, res, 100);
TEST_EQUAL(res.size(), 1, ());
TEST_ALMOST_EQUAL(res[0].m_house->m_point, m2::PointD(27.539850827603416406, 64.222406776416349317), ());
TEST_EQUAL(res[0].m_house->m_number, houseName, ());
TEST_ALMOST_EQUAL(res[0].m_house->GetPosition(), m2::PointD(27.539850827603416406, 64.222406776416349317), ());
TEST_EQUAL(res[0].m_house->GetNumber(), houseName, ());
}
{
vector <string> streetName(1, "проспект Независимости");
@ -189,8 +189,8 @@ UNIT_TEST(SEARCH_HOUSE_NUMBER_SMOKE_TEST)
string houseName = "10";
GetCanditates(index, streetName, houseName, res, 40);
TEST_EQUAL(res.size(), 1, ());
TEST_ALMOST_EQUAL(res[0].m_house->m_point, m2::PointD(27.551358845467561309, 64.234708728154814139), ());
TEST_EQUAL(res[0].m_house->m_number, houseName, ());
TEST_ALMOST_EQUAL(res[0].m_house->GetPosition(), m2::PointD(27.551358845467561309, 64.234708728154814139), ());
TEST_EQUAL(res[0].m_house->GetNumber(), houseName, ());
}
{
vector <string> streetName(1, "улица Ленина");
@ -198,7 +198,48 @@ UNIT_TEST(SEARCH_HOUSE_NUMBER_SMOKE_TEST)
string houseName = "9";
GetCanditates(index, streetName, houseName, res, 50);
TEST_EQUAL(res.size(), 1, ());
TEST_ALMOST_EQUAL(res[0].m_house->m_point, m2::PointD(27.560341563525355468, 64.240918042070561), ());
TEST_EQUAL(res[0].m_house->m_number, houseName, ());
TEST_ALMOST_EQUAL(res[0].m_house->GetPosition(), m2::PointD(27.560341563525355468, 64.240918042070561), ());
TEST_EQUAL(res[0].m_house->GetNumber(), houseName, ());
}
}
UNIT_TEST(STREET_COMPARE_TEST)
{
search::Street A, B;
TEST(search::Street::IsSameStreets(A, B), ());
string str[8][2] = { {"Московская", "Московская"},
{"ул. Московская", "Московская ул."},
{"ул. Московская", "Московская улица"},
{"ул. Московская", "улица Московская"},
{"ул. Московская", "площадь Московская"},
{"ул. мОСКОВСКАЯ", "Московская улица"},
{"Московская", "площадь Московская"},
{"Московская ", "аллея Московская"}
};
for (size_t i = 0; i < ARRAY_SIZE(str); ++i)
{
A.SetName(str[i][0]);
B.SetName(str[i][0]);
TEST(search::Street::IsSameStreets(A, B), ());
}
}
UNIT_TEST(HOUSE_COMPARE_TEST)
{
m2::PointD p(1,1);
TEST(search::House::LessHouseNumber(search::House("1", p), search::House("2", p)), ());
TEST(search::House::LessHouseNumber(search::House("123", p), search::House("123-3", p)), ());
TEST(search::House::LessHouseNumber(search::House("18a", p), search::House("18b", p)), ());
TEST(search::House::LessHouseNumber(search::House("120 1A", p), search::House("120 7A", p)), ());
TEST(search::House::LessHouseNumber(search::House("120 1A", p), search::House("120 7B", p)), ());
TEST(!search::House::LessHouseNumber(search::House("4", p), search::House("4", p)), ());
TEST(!search::House::LessHouseNumber(search::House("95", p), search::House("82-b", p)), ());
TEST(!search::House::LessHouseNumber(search::House("2", p), search::House("1", p)), ());
TEST(!search::House::LessHouseNumber(search::House("123-3", p), search::House("123", p)), ());
TEST(!search::House::LessHouseNumber(search::House("18b", p), search::House("18a", p)), ());
TEST(!search::House::LessHouseNumber(search::House("120 7A", p), search::House("120 1A", p)), ());
TEST(!search::House::LessHouseNumber(search::House("120 7B", p), search::House("120 1A", p)), ());
}