[search] Better pivot choosing strategy.
This commit is contained in:
parent
8dc4ce809a
commit
36ea18fcba
2 changed files with 103 additions and 56 deletions
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "../base/logging.hpp"
|
||||
#include "../base/stl_iterator.hpp"
|
||||
#include "../base/limited_priority_queue.hpp"
|
||||
|
||||
#include "../std/set.hpp"
|
||||
#include "../std/bind.hpp"
|
||||
|
@ -482,6 +483,7 @@ int HouseDetector::MergeStreets()
|
|||
// }
|
||||
//#endif
|
||||
|
||||
LOG(LDEBUG, ("MergeStreets() result", m_streetNum));
|
||||
return m_streetNum;
|
||||
}
|
||||
|
||||
|
@ -605,6 +607,15 @@ bool MergedStreet::IsHousesReaded() const
|
|||
return m_cont.front()->m_housesReaded;
|
||||
}
|
||||
|
||||
void MergedStreet::Next(Index & i) const
|
||||
{
|
||||
while (i.s < m_cont.size() && i.h == m_cont[i.s]->m_houses.size())
|
||||
{
|
||||
i.h = 0;
|
||||
++i.s;
|
||||
}
|
||||
}
|
||||
|
||||
void MergedStreet::Erase(Index & i)
|
||||
{
|
||||
ASSERT(!IsEnd(i), ());
|
||||
|
@ -660,6 +671,51 @@ void MergedStreet::FinishReadingHouses()
|
|||
}
|
||||
}
|
||||
|
||||
HouseProjection const * MergedStreet::GetHousePivot(bool & odd, bool & sign) const
|
||||
{
|
||||
typedef my::limited_priority_queue<
|
||||
HouseProjection const *, HouseProjection::LessDistance> QueueT;
|
||||
QueueT q(16);
|
||||
|
||||
// Get some most closest houses.
|
||||
for (MergedStreet::Index i = Begin(); !IsEnd(i); Inc(i))
|
||||
q.push(&Get(i));
|
||||
|
||||
// Calculate all probabilities.
|
||||
// even-left, odd-left, even-right, odd-right
|
||||
size_t counter[4] = { 0, 0, 0, 0 };
|
||||
for (QueueT::const_iterator i = q.begin(); i != q.end(); ++i)
|
||||
{
|
||||
size_t ind = (*i)->m_house->GetIntNumber() % 2;
|
||||
if ((*i)->m_projectionSign)
|
||||
ind += 2;
|
||||
++counter[ind];
|
||||
}
|
||||
|
||||
// Get best odd-sign pair.
|
||||
if (counter[0] + counter[3] > counter[1] + counter[2])
|
||||
{
|
||||
odd = true;
|
||||
sign = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
odd = false;
|
||||
sign = true;
|
||||
}
|
||||
|
||||
// Get result pivot according to odd-sign pair.
|
||||
while (!q.empty())
|
||||
{
|
||||
HouseProjection const * p = q.top();
|
||||
if ((p->m_projectionSign == sign) == (p->IsOdd() == odd))
|
||||
return p;
|
||||
q.pop();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class ProjectionCalcT>
|
||||
void HouseDetector::ReadHouse(FeatureType const & f, Street * st, ProjectionCalcT & calc)
|
||||
{
|
||||
|
@ -856,12 +912,16 @@ void ProccessHouses(vector<search::HouseProjection> & houses, HouseMapT & m)
|
|||
for_each(result.begin(), result.end(), bind(&AddHouseToMap, _1, ref(m)));
|
||||
}
|
||||
|
||||
House const * GetClosestHouse(MergedStreet const & st, string const & houseNumber, bool isOdd, bool sign)
|
||||
House const * GetClosestHouse(MergedStreet const & st, string const & houseNumber)
|
||||
{
|
||||
double dist = numeric_limits<double>::max();
|
||||
int streetIndex = -1;
|
||||
int houseIndex = -1;
|
||||
|
||||
bool isOdd, sign;
|
||||
if (st.GetHousePivot(isOdd, sign) == 0)
|
||||
return 0;
|
||||
|
||||
House::ParsedNumber parsedNumber(houseNumber);
|
||||
for (size_t i = 0; i < st.size(); ++i)
|
||||
{
|
||||
|
@ -1004,7 +1064,7 @@ HouseCompetitors GetBestHouseFromChains(vector<HouseChain> & houseChains, string
|
|||
}
|
||||
|
||||
|
||||
HouseCompetitors ProccessHouses(vector<search::HouseProjection> const & st, string const & houseNumber)
|
||||
HouseCompetitors ProccessHouses(vector<search::HouseProjection> const & st, string const & houseNumber)
|
||||
{
|
||||
vector <HouseChain> houseChains;
|
||||
vector <bool> used(st.size(), false);
|
||||
|
@ -1109,8 +1169,12 @@ HouseCompetitors ProccessHouses(vector<search::HouseProjection> const & st, stri
|
|||
return GetBestHouseFromChains(houseChains, houseNumber);
|
||||
}
|
||||
|
||||
House const * GetBestHouseWithNumber(MergedStreet const & st, string const & houseNumber, bool isOdd, bool sign)
|
||||
House const * GetBestHouseWithNumber(MergedStreet const & st, string const & houseNumber)
|
||||
{
|
||||
bool isOdd, sign;
|
||||
if (st.GetHousePivot(isOdd, sign) == 0)
|
||||
return 0;
|
||||
|
||||
double maxScore = numeric_limits <double>::max();
|
||||
HouseCompetitors result(0, maxScore);
|
||||
|
||||
|
@ -1147,49 +1211,28 @@ House const * GetBestHouseWithNumber(MergedStreet const & st, string const & hou
|
|||
return 0;
|
||||
}
|
||||
|
||||
House const * GetLSHouse(MergedStreet const & st, string const & houseNumber,
|
||||
bool & isOdd, bool & sign, HouseMapT & m)
|
||||
House const * GetLSHouse(MergedStreet const & st, string const & houseNumber, HouseMapT & m)
|
||||
{
|
||||
double resDist = numeric_limits<double>::max();
|
||||
search::HouseProjection pivot;
|
||||
|
||||
for (size_t i = 0; i < st.size(); ++i)
|
||||
for (size_t j = 0; j < st[i]->m_houses.size(); ++j)
|
||||
{
|
||||
search::HouseProjection const & pr = st[i]->m_houses[j];
|
||||
// Skip houses with projection on street ends.
|
||||
if (resDist > pr.m_distance &&
|
||||
pr.m_proj != st[i]->m_points.front() && pr.m_proj != st[i]->m_points.back())
|
||||
{
|
||||
pivot = pr;
|
||||
resDist = pr.m_distance;
|
||||
}
|
||||
}
|
||||
|
||||
if (pivot.m_house == 0)
|
||||
bool isOdd, sign;
|
||||
HouseProjection const * pivot = st.GetHousePivot(isOdd, sign);
|
||||
if (pivot == 0)
|
||||
return 0;
|
||||
|
||||
m.insert(make_pair(pivot.m_house, 0));
|
||||
m.insert(make_pair(pivot->m_house, 0));
|
||||
|
||||
isOdd = pivot.m_house->GetIntNumber() % 2 == 1;
|
||||
sign = pivot.m_projectionSign;
|
||||
|
||||
for (size_t i = 0; i < st.size(); ++i)
|
||||
vector<HouseProjection> v1, v2;
|
||||
for (MergedStreet::Index i = st.Begin(); !st.IsEnd(i); st.Inc(i))
|
||||
{
|
||||
vector<search::HouseProjection> left, right;
|
||||
for (size_t j = 0; j < st[i]->m_houses.size(); ++j)
|
||||
{
|
||||
search::HouseProjection const & projection = st[i]->m_houses[j];
|
||||
if (projection.m_projectionSign == sign && projection.m_house->GetIntNumber() % 2 == isOdd)
|
||||
right.push_back(projection);
|
||||
else if (projection.m_projectionSign != sign && projection.m_house->GetIntNumber() % 2 != isOdd)
|
||||
left.push_back(projection);
|
||||
}
|
||||
|
||||
ProccessHouses(right, m);
|
||||
ProccessHouses(left, m);
|
||||
search::HouseProjection const & p = st.Get(i);
|
||||
if (p.m_projectionSign == sign && p.IsOdd() == isOdd)
|
||||
v1.push_back(p);
|
||||
else if (p.m_projectionSign != sign && p.IsOdd() != isOdd)
|
||||
v2.push_back(p);
|
||||
}
|
||||
|
||||
ProccessHouses(v1, m);
|
||||
ProccessHouses(v2, m);
|
||||
|
||||
House const * arrRes[] = { 0, 0, 0 };
|
||||
House::ParsedNumber parsedNumber(houseNumber);
|
||||
for (HouseMapT::iterator it = m.begin(); it != m.end(); ++it)
|
||||
|
@ -1218,15 +1261,12 @@ void HouseDetector::GetHouseForName(string const & houseNumber, vector<House con
|
|||
{
|
||||
LOG(LDEBUG, (m_streets[i].GetDbgName()));
|
||||
|
||||
bool isOdd, sign;
|
||||
House const * house = 0;
|
||||
HouseMapT m;
|
||||
|
||||
House const * house = 0;
|
||||
house = GetLSHouse(m_streets[i], houseNumber, isOdd, sign, m);
|
||||
house = GetBestHouseWithNumber(m_streets[i], houseNumber, isOdd, sign);
|
||||
|
||||
//if (house == 0)
|
||||
// house = GetClosestHouse(m_streets[i], houseNumber, isOdd, sign);
|
||||
//house = GetLSHouse(m_streets[i], houseNumber, m);
|
||||
house = GetBestHouseWithNumber(m_streets[i], houseNumber);
|
||||
//house = GetClosestHouse(m_streets[i], houseNumber);
|
||||
|
||||
if (house)
|
||||
res.push_back(house);
|
||||
|
|
|
@ -89,6 +89,16 @@ struct HouseProjection
|
|||
double m_streetDistance;
|
||||
/// false - to the left, true - to the right from projection segment
|
||||
bool m_projectionSign;
|
||||
|
||||
inline bool IsOdd() const { return (m_house->GetIntNumber() % 2 == 1); }
|
||||
|
||||
struct LessDistance
|
||||
{
|
||||
bool operator() (HouseProjection const * p1, HouseProjection const * p2) const
|
||||
{
|
||||
return p1->m_distance < p2->m_distance;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// many features combines to street
|
||||
|
@ -134,26 +144,20 @@ public:
|
|||
bool IsHousesReaded() const;
|
||||
void FinishReadingHouses();
|
||||
|
||||
HouseProjection const * GetHousePivot(bool & isOdd, bool & sign) const;
|
||||
|
||||
/// @name Temporary
|
||||
//@{
|
||||
inline size_t size() const { return m_cont.size(); }
|
||||
inline Street const * operator[] (size_t i) const { return m_cont[i]; }
|
||||
//@}
|
||||
|
||||
private:
|
||||
public:
|
||||
struct Index
|
||||
{
|
||||
size_t s, h;
|
||||
Index() : s(0), h(0) {}
|
||||
};
|
||||
inline void Next(Index & i) const
|
||||
{
|
||||
while (i.s < m_cont.size() && i.h == m_cont[i.s]->m_houses.size())
|
||||
{
|
||||
i.h = 0;
|
||||
++i.s;
|
||||
}
|
||||
}
|
||||
|
||||
inline Index Begin() const
|
||||
{
|
||||
|
@ -175,7 +179,10 @@ private:
|
|||
ASSERT(!IsEnd(i), ());
|
||||
return m_cont[i.s]->m_houses[i.h];
|
||||
}
|
||||
|
||||
private:
|
||||
void Erase(Index & i);
|
||||
void Next(Index & i) const;
|
||||
};
|
||||
|
||||
class HouseDetector
|
||||
|
@ -202,7 +209,7 @@ private:
|
|||
|
||||
void SetMetres2Mercator(double factor);
|
||||
|
||||
//double GetApprLengthMeters(int index) const;
|
||||
double GetApprLengthMeters(int index) const;
|
||||
|
||||
public:
|
||||
typedef map<FeatureID, Street *>::iterator IterM;
|
||||
|
|
Reference in a new issue