forked from organicmaps/organicmaps
Read Houses and Make simple search
This commit is contained in:
parent
a1bb8c1cde
commit
d18a824355
4 changed files with 542 additions and 30 deletions
|
@ -1,6 +1,324 @@
|
|||
#include "house_detector.hpp"
|
||||
|
||||
#include "../indexer/classificator.hpp"
|
||||
|
||||
search::HouseDetector::HouseDetector()
|
||||
#include "../base/logging.hpp"
|
||||
|
||||
#include "../geometry/distance.hpp"
|
||||
#include "../geometry/distance_on_sphere.hpp"
|
||||
|
||||
#include "../std/iostream.hpp"
|
||||
#include "../std/set.hpp"
|
||||
#include "../std/bind.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
||||
int const BUILDING_PROCESS_SCALE = 15;
|
||||
double const STREET_CONNECTION_LENGTH_M = 25.0;
|
||||
|
||||
|
||||
struct StreetCreator
|
||||
{
|
||||
Street * street;
|
||||
StreetCreator(Street * st): street(st)
|
||||
{}
|
||||
void operator () (CoordPointT const & point)
|
||||
{
|
||||
street->m_points.push_back(m2::PointD(point.first, point.second));
|
||||
}
|
||||
};
|
||||
|
||||
FeatureLoader::FeatureLoader(Index const * pIndex)
|
||||
: m_pIndex(pIndex), m_pGuard(0)
|
||||
{
|
||||
}
|
||||
|
||||
FeatureLoader::~FeatureLoader()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void FeatureLoader::CreateLoader(size_t mwmID)
|
||||
{
|
||||
if (m_pGuard == 0 || mwmID != m_pGuard->GetID())
|
||||
{
|
||||
delete m_pGuard;
|
||||
m_pGuard = new Index::FeaturesLoaderGuard(*m_pIndex, mwmID);
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureLoader::Load(FeatureID const & id, FeatureType & f)
|
||||
{
|
||||
CreateLoader(id.m_mwm);
|
||||
m_pGuard->GetFeature(id.m_offset, f);
|
||||
}
|
||||
|
||||
void FeatureLoader::Free()
|
||||
{
|
||||
delete m_pGuard;
|
||||
m_pGuard = 0;
|
||||
}
|
||||
|
||||
template <class ToDo>
|
||||
void FeatureLoader::ForEachInRect(m2::RectD const & rect, ToDo toDo)
|
||||
{
|
||||
m_pIndex->ForEachInRect(toDo, rect, BUILDING_PROCESS_SCALE);
|
||||
}
|
||||
|
||||
m2::RectD Street::GetLimitRect(double offsetMeters) const
|
||||
{
|
||||
m2::RectD rect;
|
||||
for (size_t i = 0; i < m_points.size(); ++i)
|
||||
rect.Add(MercatorBounds::RectByCenterXYAndSizeInMeters(m_points[i], offsetMeters));
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
HouseDetector::HouseDetector(Index const * pIndex)
|
||||
: m_loader(pIndex), m_end2st(LessWithEpsilon(&m_epsMercator)), m_streetNum(0)
|
||||
{
|
||||
// default value for conversions
|
||||
SetMetres2Mercator(360.0 / 40.0E06);
|
||||
}
|
||||
|
||||
void HouseDetector::SetMetres2Mercator(double factor)
|
||||
{
|
||||
m_epsMercator = factor * STREET_CONNECTION_LENGTH_M;
|
||||
}
|
||||
|
||||
void HouseDetector::FillQueue(queue<Street *> & q, Street const * street, bool isBeg)
|
||||
{
|
||||
pair<IterT, IterT> const & range =
|
||||
m_end2st.equal_range(isBeg ? street->m_points.front() : street->m_points.back());
|
||||
|
||||
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)
|
||||
{
|
||||
it->second->m_number = m_streetNum;
|
||||
q.push(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HouseDetector::Bfs(Street * st)
|
||||
{
|
||||
queue <Street *> q;
|
||||
q.push(st);
|
||||
st->m_number = m_streetNum;
|
||||
while(!q.empty())
|
||||
{
|
||||
Street * street = q.front();
|
||||
q.pop();
|
||||
FillQueue(q, street, true);
|
||||
FillQueue(q, street, false);
|
||||
}
|
||||
}
|
||||
|
||||
void HouseDetector::LoadStreets(vector<FeatureID> & ids)
|
||||
{
|
||||
sort(ids.begin(), ids.end());
|
||||
|
||||
for (size_t i = 0; i < ids.size(); ++i)
|
||||
{
|
||||
if (m_id2st.find(ids[i]) != m_id2st.end())
|
||||
continue;
|
||||
|
||||
FeatureType f;
|
||||
m_loader.Load(ids[i], f);
|
||||
if (f.GetFeatureType() == feature::GEOM_LINE)
|
||||
{
|
||||
/// @todo Assume that default name always exist as primary compare key.
|
||||
string name;
|
||||
if (!f.GetName(0, name) || name.empty())
|
||||
continue;
|
||||
|
||||
Street * st = new Street();
|
||||
st->m_name = name;
|
||||
f.ForEachPoint(StreetCreator(st), FeatureType::BEST_GEOMETRY);
|
||||
|
||||
m_id2st[ids[i]] = st;
|
||||
m_end2st.insert(pair<m2::PointD, Street *> (st->m_points.front(), st));
|
||||
m_end2st.insert(pair<m2::PointD, Street *> (st->m_points.back(), st));
|
||||
}
|
||||
else
|
||||
ASSERT(false, ());
|
||||
}
|
||||
|
||||
m_loader.Free();
|
||||
}
|
||||
|
||||
int HouseDetector::MergeStreets()
|
||||
{
|
||||
for (IterT it = m_end2st.begin(); it != m_end2st.end(); ++it)
|
||||
{
|
||||
if (it->second->m_number == -1)
|
||||
{
|
||||
Street * st = it->second;
|
||||
++m_streetNum;
|
||||
Bfs(st);
|
||||
}
|
||||
}
|
||||
return m_streetNum;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class HouseChecker
|
||||
{
|
||||
uint32_t m_types[2];
|
||||
public:
|
||||
HouseChecker()
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
char const * arr0[] = { "building" };
|
||||
m_types[0] = c.GetTypeByPath(vector<string>(arr0, arr0 + 1));
|
||||
char const * arr1[] = { "building", "address" };
|
||||
m_types[1] = c.GetTypeByPath(vector<string>(arr1, arr1 + 2));
|
||||
}
|
||||
|
||||
bool IsHouse(feature::TypesHolder const & types)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(m_types); ++i)
|
||||
if (types.Has(m_types[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
double GetDistanceMeters(m2::PointD const & p1, m2::PointD const & p2)
|
||||
{
|
||||
return ms::DistanceOnEarth(MercatorBounds::YToLat(p1.y), MercatorBounds::XToLon(p1.x),
|
||||
MercatorBounds::YToLat(p2.y), MercatorBounds::XToLon(p2.x));
|
||||
}
|
||||
|
||||
class ProjectionCalcToStreet
|
||||
{
|
||||
Street const * m_street;
|
||||
double m_distanceMeters;
|
||||
|
||||
typedef m2::ProjectionToSection<m2::PointD> ProjectionT;
|
||||
vector<ProjectionT> m_calcs;
|
||||
|
||||
public:
|
||||
ProjectionCalcToStreet(Street const * st, double distanceMeters)
|
||||
: m_street(st), m_distanceMeters(distanceMeters)
|
||||
{
|
||||
}
|
||||
|
||||
bool GetProjection(m2::PointD const & pt, HouseProjection & proj)
|
||||
{
|
||||
if (m_calcs.empty())
|
||||
{
|
||||
for (size_t i = 1; i < m_street->m_points.size(); ++i)
|
||||
{
|
||||
m_calcs.push_back(ProjectionT());
|
||||
m_calcs.back().SetBounds(m_street->m_points[i-1], m_street->m_points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m2::PointD resPt;
|
||||
double dist = numeric_limits<double>::max();
|
||||
double resDist = numeric_limits<double>::max();
|
||||
for (size_t i = 0; i < m_calcs.size(); ++i)
|
||||
{
|
||||
m2::PointD const proj = m_calcs[i](pt);
|
||||
dist = GetDistanceMeters(pt, proj);
|
||||
if (dist < resDist)
|
||||
{
|
||||
resPt = proj;
|
||||
resDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (resDist <= m_distanceMeters)
|
||||
{
|
||||
proj.m_proj = resPt;
|
||||
proj.m_distance = dist;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class ProjectionCalcT>
|
||||
void HouseDetector::ReadHouse(FeatureType const & f, Street * st, ProjectionCalcT & calc)
|
||||
{
|
||||
static HouseChecker checker;
|
||||
if (checker.IsHouse(feature::TypesHolder(f)))
|
||||
{
|
||||
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;
|
||||
|
||||
HouseProjection pr;
|
||||
if (calc.GetProjection(pt, pr))
|
||||
{
|
||||
House * p;
|
||||
if (it == m_id2house.end())
|
||||
{
|
||||
p = new House();
|
||||
p->m_point = pt;
|
||||
p->m_number = f.GetHouseNumber();
|
||||
m_id2house[f.GetID()] = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = it->second;
|
||||
ASSERT(p != 0, ());
|
||||
}
|
||||
|
||||
pr.m_house = p;
|
||||
st->m_houses.push_back(pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HouseDetector::ReadHouses(Street * st, double offsetMeters)
|
||||
{
|
||||
if (st->m_housesReaded)
|
||||
return;
|
||||
|
||||
ProjectionCalcToStreet calcker(st, offsetMeters);
|
||||
m_loader.ForEachInRect(st->GetLimitRect(offsetMeters),
|
||||
bind(&HouseDetector::ReadHouse<ProjectionCalcToStreet>, this, _1, st, ref(calcker)));
|
||||
|
||||
st->m_housesReaded = true;
|
||||
}
|
||||
|
||||
void HouseDetector::ReadAllHouses(double offsetMeters)
|
||||
{
|
||||
for (map<FeatureID, Street *>::iterator it = m_id2st.begin(); it != m_id2st.end(); ++it)
|
||||
ReadHouses(it->second, offsetMeters);
|
||||
}
|
||||
|
||||
void HouseDetector::MatchAllHouses(string const & houseNumber, vector<HouseProjection> & res)
|
||||
{
|
||||
/// @temporary decision to avoid duplicating houses
|
||||
set<House const *> s;
|
||||
|
||||
for (map<FeatureID, Street *>::iterator it = m_id2st.begin(); it != m_id2st.end();++it)
|
||||
{
|
||||
Street const * st = it->second;
|
||||
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)
|
||||
{
|
||||
res.push_back(st->m_houses[i]);
|
||||
s.insert(house);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,70 +1,118 @@
|
|||
#pragma once
|
||||
|
||||
#include "../indexer/feature_decl.hpp"
|
||||
#include "../indexer/index.hpp"
|
||||
|
||||
#include "../geometry/point2d.hpp"
|
||||
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/queue.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
||||
const double s_epsilon = 10.0 * 360.0 / 40E6;
|
||||
|
||||
class FeatureLoader
|
||||
{
|
||||
Index const * m_pIndex;
|
||||
Index::FeaturesLoaderGuard * m_pGuard;
|
||||
|
||||
void CreateLoader(size_t mwmID);
|
||||
|
||||
public:
|
||||
FeatureLoader(Index const * pIndex);
|
||||
~FeatureLoader();
|
||||
|
||||
void Load(FeatureID const & id, FeatureType & f);
|
||||
void Free();
|
||||
|
||||
template <class ToDo> void ForEachInRect(m2::RectD const & rect, ToDo toDo);
|
||||
};
|
||||
|
||||
class House
|
||||
struct House
|
||||
{
|
||||
string m_number;
|
||||
m2::PointD m_point;
|
||||
public:
|
||||
};
|
||||
|
||||
struct HouseProjection
|
||||
{
|
||||
House const * m_house;
|
||||
m2::PointD m_proj;
|
||||
double m_distance;
|
||||
|
||||
static bool LessDistance(HouseProjection const & r1, HouseProjection const & r2)
|
||||
{
|
||||
return r1.m_distance < r2.m_distance;
|
||||
}
|
||||
};
|
||||
|
||||
// many features combines to street
|
||||
class Street
|
||||
struct Street
|
||||
{
|
||||
string m_name;
|
||||
vector<m2::PointD> m_points;
|
||||
|
||||
vector<House> m_houses;
|
||||
vector<HouseProjection> m_houses;
|
||||
bool m_housesReaded;
|
||||
int m_number;
|
||||
|
||||
Street() : m_housesReaded(false), m_number(-1) {}
|
||||
|
||||
/// Get limit rect for street with ortho offset to the left and right.
|
||||
m2::RectD GetLimitRect(double offsetMeters) const;
|
||||
};
|
||||
|
||||
class HouseDetector
|
||||
{
|
||||
FeatureLoader m_loader;
|
||||
|
||||
// id -> street
|
||||
//map<FeatureID, Street *> m_id2st;
|
||||
map<FeatureID, Street *> m_id2st;
|
||||
map<FeatureID, House *> m_id2house;
|
||||
|
||||
public:
|
||||
struct LessWithEpsilon
|
||||
class LessWithEpsilon
|
||||
{
|
||||
//static double s_epsilon;
|
||||
|
||||
double * m_eps;
|
||||
public:
|
||||
LessWithEpsilon(double * eps) : m_eps(eps) {}
|
||||
bool operator() (m2::PointD const & p1, m2::PointD const & p2) const
|
||||
{
|
||||
if (p1.x + s_epsilon < p2.x)
|
||||
if (p1.x + *m_eps < p2.x)
|
||||
return true;
|
||||
else if (p2.x + s_epsilon < p1.x)
|
||||
else if (p2.x + *m_eps < p1.x)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
return (p1.y + s_epsilon < p2.y);
|
||||
}
|
||||
return (p1.y + *m_eps < p2.y);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// start, end point -> street
|
||||
double m_epsMercator;
|
||||
typedef multimap<m2::PointD, Street *, LessWithEpsilon>::iterator IterT;
|
||||
multimap<m2::PointD, Street *, LessWithEpsilon> m_end2st;
|
||||
|
||||
Street * GetNext(Street const *);
|
||||
Street * GetPrev(Street const *);
|
||||
int m_streetNum;
|
||||
|
||||
void FillQueue(queue<Street *> & q, Street const * street, bool isBeg);
|
||||
void Bfs(Street * st);
|
||||
|
||||
template <class ProjectionCalcT>
|
||||
void ReadHouse(FeatureType const & f, Street * st, ProjectionCalcT & calc);
|
||||
|
||||
void SetMetres2Mercator(double factor);
|
||||
|
||||
public:
|
||||
HouseDetector();
|
||||
HouseDetector(Index const * pIndex);
|
||||
|
||||
void LoadStreets(vector<FeatureID> & ids);
|
||||
/// @return number of different joined streets.
|
||||
int MergeStreets();
|
||||
|
||||
void ReadHouses(Street * st, double offsetMeters);
|
||||
void ReadAllHouses(double offsetMeters);
|
||||
|
||||
void MatchAllHouses(string const & houseNumber, vector<HouseProjection> & res);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,22 @@
|
|||
#include "../../testing/testing.hpp"
|
||||
|
||||
#include "../../base/logging.hpp"
|
||||
|
||||
#include "../../platform/platform.hpp"
|
||||
|
||||
#include "../../indexer/scales.hpp"
|
||||
#include "../../indexer/index.hpp"
|
||||
#include "../../indexer/classificator_loader.hpp"
|
||||
|
||||
#include "../house_detector.hpp"
|
||||
|
||||
#include "../../std/iostream.hpp"
|
||||
|
||||
|
||||
UNIT_TEST(LESS_WITH_EPSILON)
|
||||
{
|
||||
search::HouseDetector::LessWithEpsilon compare;
|
||||
double q = 3.0 * 360.0 / 40.0E06;
|
||||
search::HouseDetector::LessWithEpsilon compare(&q);
|
||||
{
|
||||
m2::PointD a(1, 1);
|
||||
m2::PointD b(2, 2);
|
||||
|
@ -24,38 +37,168 @@ UNIT_TEST(LESS_WITH_EPSILON)
|
|||
}
|
||||
{
|
||||
m2::PointD a(1, 1);
|
||||
m2::PointD b(1 + search::s_epsilon, 1);
|
||||
m2::PointD b(1 + q, 1);
|
||||
TEST(!compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
{
|
||||
m2::PointD a(1, 1);
|
||||
m2::PointD b(1 + search::s_epsilon, 1 - search::s_epsilon);
|
||||
m2::PointD b(1 + q, 1 - q);
|
||||
TEST(!compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
{
|
||||
m2::PointD a(1, 1 - search::s_epsilon);
|
||||
m2::PointD b(1 + search::s_epsilon, 1);
|
||||
m2::PointD a(1, 1 - q);
|
||||
m2::PointD b(1 + q, 1);
|
||||
TEST(!compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
{
|
||||
m2::PointD a(1 - search::s_epsilon, 1 - search::s_epsilon);
|
||||
m2::PointD a(1 - q, 1 - q);
|
||||
m2::PointD b(1, 1);
|
||||
TEST(!compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
{
|
||||
m2::PointD a(1, 1);
|
||||
m2::PointD b(1 + search::s_epsilon, 1 + search::s_epsilon);
|
||||
m2::PointD b(1 + q, 1 + q);
|
||||
TEST(!compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
{
|
||||
m2::PointD a(1, 1);
|
||||
m2::PointD b(1 + 2 * search::s_epsilon, 1 + search::s_epsilon);
|
||||
m2::PointD b(1 + 2 * q, 1 + q);
|
||||
TEST(compare(a, b), ());
|
||||
TEST(!compare(b, a), ());
|
||||
}
|
||||
}
|
||||
|
||||
struct Process
|
||||
{
|
||||
vector <FeatureID> vect;
|
||||
vector <string> streetNames;
|
||||
void operator() (FeatureType const & f)
|
||||
{
|
||||
if (f.GetFeatureType() == feature::GEOM_LINE)
|
||||
{
|
||||
string name;
|
||||
if (f.GetName(0, name))
|
||||
{
|
||||
for (size_t i = 0; i < streetNames.size(); ++i)
|
||||
if (name == streetNames[i])
|
||||
{
|
||||
vect.push_back(f.GetID());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
UNIT_TEST(STREET_MERGE_TEST)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
Index index;
|
||||
m2::RectD rect;
|
||||
|
||||
index.Add("minsk-pass.mwm", rect);
|
||||
{
|
||||
search::HouseDetector houser(&index);
|
||||
Process toDo;
|
||||
toDo.streetNames.push_back("Московская улица");
|
||||
index.ForEachInScale(toDo, scales::GetUpperScale());
|
||||
houser.LoadStreets(toDo.vect);
|
||||
TEST_EQUAL(houser.MergeStreets(), 1, ());
|
||||
}
|
||||
|
||||
{
|
||||
search::HouseDetector houser(&index);
|
||||
Process toDo;
|
||||
toDo.streetNames.push_back("проспект Независимости");
|
||||
toDo.streetNames.push_back("Московская улица");
|
||||
index.ForEachInScale(toDo, scales::GetUpperScale());
|
||||
houser.LoadStreets(toDo.vect);
|
||||
TEST_EQUAL(houser.MergeStreets(), 2, ());
|
||||
}
|
||||
{
|
||||
search::HouseDetector houser(&index);
|
||||
Process toDo;
|
||||
toDo.streetNames.push_back("проспект Независимости");
|
||||
toDo.streetNames.push_back("Московская улица");
|
||||
toDo.streetNames.push_back("Вишнёвый переулок");
|
||||
toDo.streetNames.push_back("Студенческий переулок");
|
||||
toDo.streetNames.push_back("Полоцкий переулок");
|
||||
index.ForEachInScale(toDo, scales::GetUpperScale());
|
||||
houser.LoadStreets(toDo.vect);
|
||||
TEST_EQUAL(houser.MergeStreets(), 5, ());
|
||||
}
|
||||
{
|
||||
search::HouseDetector houser(&index);
|
||||
Process toDo;
|
||||
toDo.streetNames.push_back("проспект Независимости");
|
||||
toDo.streetNames.push_back("Московская улица");
|
||||
toDo.streetNames.push_back("улица Кирова");
|
||||
toDo.streetNames.push_back("улица Городской Вал");
|
||||
index.ForEachInScale(toDo, scales::GetUpperScale());
|
||||
houser.LoadStreets(toDo.vect);
|
||||
TEST_EQUAL(houser.MergeStreets(), 4, ());
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void GetCanditates(Index & index, vector<string> const & v, string const & houseName,
|
||||
vector<search::HouseProjection> & res, double offset)
|
||||
{
|
||||
search::HouseDetector houser(&index);
|
||||
Process toDo;
|
||||
toDo.streetNames = v;
|
||||
index.ForEachInScale(toDo, scales::GetUpperScale());
|
||||
|
||||
houser.LoadStreets(toDo.vect);
|
||||
houser.ReadAllHouses(offset);
|
||||
houser.MatchAllHouses(houseName, res);
|
||||
|
||||
sort(res.begin(), res.end(), &search::HouseProjection::LessDistance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UNIT_TEST(SEARCH_HOUSE_NUMBER_SMOKE_TEST)
|
||||
{
|
||||
classificator::Load();
|
||||
|
||||
Index index;
|
||||
m2::RectD rect;
|
||||
index.Add("minsk-pass.mwm", rect);
|
||||
|
||||
{
|
||||
vector <string> streetName(1, "Московская улица");
|
||||
vector <search::HouseProjection> res;
|
||||
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, ());
|
||||
}
|
||||
{
|
||||
vector <string> streetName(1, "проспект Независимости");
|
||||
vector <search::HouseProjection> res;
|
||||
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, ());
|
||||
}
|
||||
{
|
||||
vector <string> streetName(1, "улица Ленина");
|
||||
vector <search::HouseProjection> res;
|
||||
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, ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ CONFIG -= app_bundle
|
|||
TEMPLATE = app
|
||||
|
||||
ROOT_DIR = ../..
|
||||
DEPENDENCIES = search platform indexer geometry coding base
|
||||
DEPENDENCIES = search platform indexer geometry coding base \
|
||||
protobuf
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
|
@ -17,6 +18,8 @@ win32 {
|
|||
win32-g++: LIBS += -lpthread
|
||||
}
|
||||
|
||||
macx-*: LIBS *= "-framework Foundation" "-framework IOKit"
|
||||
|
||||
SOURCES += \
|
||||
../../testing/testingmain.cpp \
|
||||
#keyword_matcher_test.cpp \
|
||||
|
|
Loading…
Add table
Reference in a new issue