[search] Divide IntermediateResukt into PreResult1 and PreResult2. Do not load features, while making PreResult1.

This commit is contained in:
vng 2012-02-10 02:51:40 +03:00 committed by Alex Zolotarev
parent b07616b315
commit a2273f714f
4 changed files with 367 additions and 283 deletions

View file

@ -20,13 +20,86 @@ namespace search
namespace impl
{
IntermediateResult::IntermediateResult(m2::RectD const & viewportRect, m2::PointD const & pos,
FeatureType const & f, m2::PointD const & center, uint8_t rank,
string const & displayName, string const & fileName)
double ResultDistance(m2::PointD const & a, m2::PointD const & b)
{
return ms::DistanceOnEarth(MercatorBounds::YToLat(a.y), MercatorBounds::XToLon(a.x),
MercatorBounds::YToLat(b.y), MercatorBounds::XToLon(b.x));
}
uint8_t ViewportDistance(m2::RectD const & viewport, m2::PointD const & p)
{
if (viewport.IsPointInside(p))
return 0;
m2::RectD r = viewport;
r.Scale(3);
if (r.IsPointInside(p))
return 1;
r = viewport;
r.Scale(5);
if (r.IsPointInside(p))
return 2;
return 3;
}
PreResult1::PreResult1(uint32_t fID, uint8_t rank, m2::PointD const & center, size_t mwmID,
m2::PointD const & pos, m2::RectD const & viewport)
: m_center(center),
m_mwmID(mwmID),
m_featureID(fID),
m_rank(rank)
{
CalcParams(viewport, pos);
}
void PreResult1::CalcParams(m2::RectD const & viewport, m2::PointD const & pos)
{
// Check if point is valid (see Query::empty_pos_value).
if (pos.x > -500 && pos.y > -500)
{
ASSERT ( my::between_s(-180.0, 180.0, pos.x), (pos.x) );
ASSERT ( my::between_s(-180.0, 180.0, pos.y), (pos.y) );
m_distance = ResultDistance(m_center, pos);
}
else
{
// empty distance
m_distance = -1.0;
}
m_viewportDistance = ViewportDistance(viewport, m_center);
}
bool PreResult1::LessRank(PreResult1 const & r1, PreResult1 const & r2)
{
return (r1.m_rank > r2.m_rank);
}
bool PreResult1::LessDistance(PreResult1 const & r1, PreResult1 const & r2)
{
return (r1.m_distance < r2.m_distance);
}
bool PreResult1::LessViewportDistance(PreResult1 const & r1, PreResult1 const & r2)
{
return (r1.m_viewportDistance < r2.m_viewportDistance);
}
PreResult2::PreResult2(FeatureType const & f, PreResult1 const & res,
string const & displayName, string const & fileName)
: m_types(f),
m_str(displayName),
m_center(res.m_center),
m_distance(res.m_distance),
m_resultType(RESULT_FEATURE),
m_center(center), m_searchRank(rank)
m_searchRank(res.m_rank),
m_viewportDistance(res.m_viewportDistance)
{
ASSERT_GREATER(m_types.Size(), 0, ());
@ -35,95 +108,36 @@ IntermediateResult::IntermediateResult(m2::RectD const & viewportRect, m2::Point
m_region.SetName(fileName);
else
m_region.SetPoint(m_center);
CalcCommonParams(viewportRect, pos);
}
IntermediateResult::IntermediateResult(m2::RectD const & viewportRect, m2::PointD const & pos,
double lat, double lon, double precision)
PreResult2::PreResult2(m2::RectD const & viewport, m2::PointD const & pos,
double lat, double lon)
: m_str("(" + strings::to_string(lat) + ", " + strings::to_string(lon) + ")"),
m_center(m2::PointD(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat))),
m_resultType(RESULT_LATLON), m_searchRank(255)
{
CalcCommonParams(viewportRect, pos);
// dummy object to avoid copy-paste
PreResult1 res(0, 0, m2::PointD(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat)),
0, pos, viewport);
m_center = res.m_center;
m_distance = res.m_distance;
m_viewportDistance = res.m_viewportDistance;
// get region info
m_region.SetPoint(m_center);
}
void IntermediateResult::CalcCommonParams(m2::RectD const & viewportRect, m2::PointD const & pos)
{
// Check if point is valid (see Query::empty_pos_value).
if (pos.x > -500 && pos.y > -500)
{
ASSERT ( my::between_s(-180.0, 180.0, pos.x), (pos.x) );
ASSERT ( my::between_s(-180.0, 180.0, pos.y), (pos.y) );
m_distance = ResultDistance(pos, m_center);
}
else
{
// empty distance
m_distance = -1.0;
}
m_viewportDistance = ViewportDistance(viewportRect, m_center);
}
IntermediateResult::IntermediateResult(string const & name, int penalty)
PreResult2::PreResult2(string const & name, int penalty)
: m_str(name), m_completionString(name + " "),
// Categories should always be first.
m_distance(-1000.0), // smallest distance :)
m_viewportDistance(0), // closest to viewport
m_resultType(RESULT_CATEGORY),
m_searchRank(255) // best rank
m_searchRank(255), // best rank
m_viewportDistance(0) // closest to viewport
{
}
/*
bool IntermediateResult::LessOrderF::operator()
(IntermediateResult const & r1, IntermediateResult const & r2) const
{
if (r1.m_resultType != r2.m_resultType)
return (r1.m_resultType < r2.m_resultType);
if (r1.m_searchRank != r2.m_searchRank)
return (r1.m_searchRank > r2.m_searchRank);
return (r1.m_distance < r2.m_distance);
}
*/
bool IntermediateResult::LessRank(IntermediateResult const & r1, IntermediateResult const & r2)
{
return (r1.m_searchRank > r2.m_searchRank);
}
bool IntermediateResult::LessDistance(IntermediateResult const & r1, IntermediateResult const & r2)
{
return (r1.m_distance < r2.m_distance);
/*
if (r1.m_distance != r2.m_distance)
return (r1.m_distance < r2.m_distance);
else
return LessRank(r1, r2);
*/
}
bool IntermediateResult::LessViewportDistance(IntermediateResult const & r1, IntermediateResult const & r2)
{
return (r1.m_viewportDistance < r2.m_viewportDistance);
/*
if (r1.m_viewportDistance != r2.m_viewportDistance)
return (r1.m_viewportDistance < r2.m_viewportDistance);
else
return LessRank(r1, r2);
*/
}
Result IntermediateResult::GenerateFinalResult(
Result PreResult2::GenerateFinalResult(
storage::CountryInfoGetter const * pInfo,
CategoriesT const * pCat) const
{
@ -151,36 +165,22 @@ Result IntermediateResult::GenerateFinalResult(
}
}
double IntermediateResult::ResultDistance(m2::PointD const & a, m2::PointD const & b)
bool PreResult2::LessRank(PreResult2 const & r1, PreResult2 const & r2)
{
return ms::DistanceOnEarth(MercatorBounds::YToLat(a.y), MercatorBounds::XToLon(a.x),
MercatorBounds::YToLat(b.y), MercatorBounds::XToLon(b.x));
return (r1.m_searchRank > r2.m_searchRank);
}
double IntermediateResult::ResultDirection(m2::PointD const & a, m2::PointD const & b)
bool PreResult2::LessDistance(PreResult2 const & r1, PreResult2 const & r2)
{
return ang::AngleTo(a, b);
return (r1.m_distance < r2.m_distance);
}
int IntermediateResult::ViewportDistance(m2::RectD const & viewport, m2::PointD const & p)
bool PreResult2::LessViewportDistance(PreResult2 const & r1, PreResult2 const & r2)
{
if (viewport.IsPointInside(p))
return 0;
m2::RectD r = viewport;
r.Scale(3);
if (r.IsPointInside(p))
return 1;
r = viewport;
r.Scale(5);
if (r.IsPointInside(p))
return 2;
return 3;
return (r1.m_viewportDistance < r2.m_viewportDistance);
}
bool IntermediateResult::StrictEqualF::operator()(IntermediateResult const & r) const
bool PreResult2::StrictEqualF::operator() (PreResult2 const & r) const
{
if (m_r.m_resultType == r.m_resultType && m_r.m_resultType == RESULT_FEATURE)
{
@ -230,8 +230,7 @@ namespace
};
}
bool IntermediateResult::LessLinearTypesF::operator()
(IntermediateResult const & r1, IntermediateResult const & r2) const
bool PreResult2::LessLinearTypesF::operator() (PreResult2 const & r1, PreResult2 const & r2) const
{
if (r1.m_resultType != r2.m_resultType)
return (r1.m_resultType < r2.m_resultType);
@ -249,8 +248,7 @@ bool IntermediateResult::LessLinearTypesF::operator()
return (r1.m_distance < r2.m_distance);
}
bool IntermediateResult::EqualLinearTypesF::operator()
(IntermediateResult const & r1, IntermediateResult const & r2) const
bool PreResult2::EqualLinearTypesF::operator() (PreResult2 const & r1, PreResult2 const & r2) const
{
if (r1.m_resultType == r2.m_resultType && r1.m_str == r2.m_str)
{
@ -263,7 +261,7 @@ bool IntermediateResult::EqualLinearTypesF::operator()
return false;
}
string IntermediateResult::DebugPrint() const
string PreResult2::DebugPrint() const
{
string res("IntermediateResult: ");
res += "Name: " + m_str;
@ -274,7 +272,7 @@ string IntermediateResult::DebugPrint() const
return res;
}
string IntermediateResult::GetFeatureType(CategoriesT const * pCat) const
string PreResult2::GetFeatureType(CategoriesT const * pCat) const
{
ASSERT_EQUAL(m_resultType, RESULT_FEATURE, ());
@ -301,7 +299,7 @@ string IntermediateResult::GetFeatureType(CategoriesT const * pCat) const
return s;
}
void IntermediateResult::RegionInfo::GetRegion(
void PreResult2::RegionInfo::GetRegion(
storage::CountryInfoGetter const * pInfo, storage::CountryInfo & info) const
{
if (!m_file.empty())

View file

@ -22,10 +22,35 @@ namespace search
namespace impl
{
class IntermediateResult
/// First results class. Objects are creating during search in trie.
class PreResult1
{
void CalcCommonParams(m2::RectD const & viewportRect, m2::PointD const & pos);
friend class PreResult2;
m2::PointD m_center;
double m_distance;
size_t m_mwmID;
uint32_t m_featureID;
uint8_t m_viewportDistance;
uint8_t m_rank;
void CalcParams(m2::RectD const & viewportRect, m2::PointD const & pos);
public:
PreResult1(uint32_t fID, uint8_t rank, m2::PointD const & center, size_t mwmID,
m2::PointD const & pos, m2::RectD const & viewport);
static bool LessRank(PreResult1 const & r1, PreResult1 const & r2);
static bool LessDistance(PreResult1 const & r1, PreResult1 const & r2);
static bool LessViewportDistance(PreResult1 const & r1, PreResult1 const & r2);
inline pair<uint32_t, size_t> GetID() const { return make_pair(m_featureID, m_mwmID); }
};
/// Second result class. Objects are creating during reading of features.
class PreResult2
{
public:
enum ResultType
{
@ -35,64 +60,49 @@ public:
};
// For RESULT_FEATURE.
IntermediateResult(m2::RectD const & viewportRect, m2::PointD const & pos,
FeatureType const & f, m2::PointD const & center, uint8_t rank,
string const & displayName, string const & fileName);
PreResult2(FeatureType const & f, PreResult1 const & res,
string const & displayName, string const & fileName);
// For RESULT_LATLON.
IntermediateResult(m2::RectD const & viewportRect, m2::PointD const & pos,
double lat, double lon, double precision);
PreResult2(m2::RectD const & viewport, m2::PointD const & pos,
double lat, double lon);
// For RESULT_CATEGORY.
IntermediateResult(string const & name, int penalty);
PreResult2(string const & name, int penalty);
typedef multimap<strings::UniString, uint32_t> CategoriesT;
Result GenerateFinalResult(storage::CountryInfoGetter const * pInfo,
CategoriesT const * pCat) const;
/// Results order functor.
/*
struct LessOrderF
{
bool operator() (IntermediateResult const & r1, IntermediateResult const & r2) const;
};
*/
static bool LessRank(IntermediateResult const & r1, IntermediateResult const & r2);
static bool LessDistance(IntermediateResult const & r1, IntermediateResult const & r2);
static bool LessViewportDistance(IntermediateResult const & r1, IntermediateResult const & r2);
static bool LessRank(PreResult2 const & r1, PreResult2 const & r2);
static bool LessDistance(PreResult2 const & r1, PreResult2 const & r2);
static bool LessViewportDistance(PreResult2 const & r1, PreResult2 const & r2);
/// Filter equal features for different mwm's.
class StrictEqualF
{
IntermediateResult const & m_r;
PreResult2 const & m_r;
public:
StrictEqualF(IntermediateResult const & r) : m_r(r) {}
bool operator() (IntermediateResult const & r) const;
StrictEqualF(PreResult2 const & r) : m_r(r) {}
bool operator() (PreResult2 const & r) const;
};
/// To filter equal linear objects.
//@{
struct LessLinearTypesF
{
bool operator() (IntermediateResult const & r1, IntermediateResult const & r2) const;
bool operator() (PreResult2 const & r1, PreResult2 const & r2) const;
};
class EqualLinearTypesF
{
public:
bool operator() (IntermediateResult const & r1, IntermediateResult const & r2) const;
bool operator() (PreResult2 const & r1, PreResult2 const & r2) const;
};
//@}
string DebugPrint() const;
private:
static double ResultDistance(m2::PointD const & viewportCenter,
m2::PointD const & featureCenter);
static double ResultDirection(m2::PointD const & viewportCenter,
m2::PointD const & featureCenter);
static int ViewportDistance(m2::RectD const & viewport, m2::PointD const & p);
string GetFeatureType(CategoriesT const * pCat) const;
feature::TypesHolder m_types;
@ -124,26 +134,16 @@ private:
} m_region;
m2::PointD m_center;
double m_distance;
int m_viewportDistance;
ResultType m_resultType;
uint8_t m_searchRank;
uint8_t m_viewportDistance;
};
inline string DebugPrint(IntermediateResult const & t)
inline string DebugPrint(PreResult2 const & t)
{
return t.DebugPrint();
}
} // namespace search::impl
} // namespace search
namespace boost
{
inline string DebugPrint(shared_ptr<search::impl::IntermediateResult> const & p)
{
return DebugPrint(*p);
}
}

View file

@ -128,13 +128,21 @@ void Query::UpdateViewportOffsets()
namespace
{
typedef bool (*CompareFunctionT) (impl::IntermediateResult const &,
impl::IntermediateResult const &);
CompareFunctionT g_arrCompare[] =
typedef bool (*CompareFunctionT1) (impl::PreResult1 const &, impl::PreResult1 const &);
typedef bool (*CompareFunctionT2) (impl::PreResult2 const &, impl::PreResult2 const &);
CompareFunctionT1 g_arrCompare1[] =
{
&impl::IntermediateResult::LessRank,
&impl::IntermediateResult::LessViewportDistance,
&impl::IntermediateResult::LessDistance
&impl::PreResult1::LessRank,
&impl::PreResult1::LessViewportDistance,
&impl::PreResult1::LessDistance
};
CompareFunctionT2 g_arrCompare2[] =
{
&impl::PreResult2::LessRank,
&impl::PreResult2::LessViewportDistance,
&impl::PreResult2::LessDistance
};
}
@ -168,10 +176,11 @@ void Query::Search(string const & query, Results & res, unsigned int resultsNeed
m_tokens.data(), m_tokens.size(), &m_prefix));
// Results queue's initialization.
STATIC_ASSERT ( m_qCount == ARRAY_SIZE(g_arrCompare) );
STATIC_ASSERT ( m_qCount == ARRAY_SIZE(g_arrCompare1) );
STATIC_ASSERT ( m_qCount == ARRAY_SIZE(g_arrCompare2) );
for (size_t i = 0; i < m_qCount; ++i)
m_results[i] = QueueT(resultsNeeded, CompareT(g_arrCompare[i]));
m_results[i] = QueueT(2 * resultsNeeded, CompareT<impl::PreResult1>(g_arrCompare1[i]));
}
// Match (lat, lon).
@ -179,13 +188,14 @@ void Query::Search(string const & query, Results & res, unsigned int resultsNeed
double lat, lon, latPrec, lonPrec;
if (search::MatchLatLon(m_rawQuery, lat, lon, latPrec, lonPrec))
{
double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec)); // Min 55 meters
AddResult(ValueT(new impl::IntermediateResult(m_viewport, m_position, lat, lon, precision)));
//double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec)); // Min 55 meters
res.AddResult(impl::PreResult2(m_viewport, m_position, lat, lon).
GenerateFinalResult(m_pInfoGetter, m_pCategories));
}
}
if (m_cancel) return;
SuggestStrings();
SuggestStrings(res);
if (m_cancel) return;
SearchFeatures();
@ -217,44 +227,22 @@ namespace
}
};
//@}
}
void Query::AddResult(ValueT const & result)
{
for (size_t i = 0; i < m_qCount; ++i)
{
// don't add equal features
if (m_results[i].end() == find_if(m_results[i].begin(), m_results[i].end(),
ProxyFunctor1<ResultT::StrictEqualF>(result)))
{
m_results[i].push(result);
}
//else
//{
// LOG(LINFO, ("Skipped feature:", result));
//}
}
}
namespace
{
class IndexedValue
{
typedef impl::IntermediateResult ValueT;
typedef shared_ptr<ValueT> PointerT;
array<size_t, Query::m_qCount> m_ind;
PointerT m_val;
// Do not use shared_ptr for optimization issues :).
shared_ptr<impl::PreResult2> m_val;
public:
IndexedValue(PointerT const & v) : m_val(v)
explicit IndexedValue(impl::PreResult2 * v) : m_val(v)
{
for (size_t i = 0; i < m_ind.size(); ++i)
m_ind[i] = numeric_limits<size_t>::max();
}
PointerT get() const { return m_val; }
ValueT const & operator*() const { return *m_val; }
impl::PreResult2 const & operator*() const { return *m_val; }
void SetIndex(size_t i, size_t v) { m_ind[i] = v; }
@ -269,7 +257,7 @@ namespace
for (size_t i = 0; i < m_ind.size(); ++i)
index = index + " " + strings::to_string(m_ind[i]);
return boost::DebugPrint(m_val) + "; Index:" + index;
return impl::DebugPrint(*m_val) + "; Index:" + index;
}
bool operator < (IndexedValue const & r) const
@ -284,50 +272,148 @@ namespace
}
};
struct LessPointer
inline string DebugPrint(IndexedValue const & t)
{
bool operator() (IndexedValue const & r1, IndexedValue const & r2) const
{
return (r1.get() < r2.get());
}
};
struct EqualPointer
{
bool operator() (IndexedValue const & r1, IndexedValue const & r2) const
{
return (r1.get() == r2.get());
}
};
inline string DebugPrint(IndexedValue const & v)
{
return v.DebugPrint();
return t.DebugPrint();
}
struct LessByFeatureID
{
typedef shared_ptr<impl::PreResult1> PtrT;
bool operator() (PtrT const & r1, PtrT const & r2) const
{
return (r1->GetID() < r2->GetID());
}
};
}
namespace impl
{
class PreResult2Maker
{
typedef map<size_t, FeaturesVector *> FeaturesMapT;
map<size_t, FeaturesVector *> m_features;
vector<MwmInfo> m_mwmInfo;
Query & m_query;
public:
PreResult2Maker(Query & q) : m_query(q)
{
m_query.m_pIndex->GetMwmInfo(m_mwmInfo);
}
~PreResult2Maker()
{
for (FeaturesMapT::iterator i = m_features.begin(); i != m_features.end(); ++i)
delete i->second;
}
impl::PreResult2 * operator() (impl::PreResult1 const & r)
{
// Find or create needed FeaturesVector for result.
pair<uint32_t, size_t> const id = r.GetID();
string countryName;
FeaturesMapT::iterator iF = m_features.insert(
make_pair(id.second, static_cast<FeaturesVector*>(0))).first;
if (iF->second == 0)
{
for (MwmSet::MwmId mwmId = 0; mwmId < m_mwmInfo.size(); ++mwmId)
{
if (mwmId == id.second)
{
Index::MwmLock mwmLock(*m_query.m_pIndex, mwmId);
countryName = mwmLock.GetCountryName();
if (MwmValue * pMwm = mwmLock.GetValue())
{
feature::DataHeader const & h = pMwm->GetHeader();
if (h.GetType() == feature::DataHeader::world)
countryName = string();
iF->second = new FeaturesVector(pMwm->m_cont, h);
break;
}
}
}
}
if (iF->second == 0)
{
LOG(LERROR, ("Valid MWM for search result not found", id));
return 0;
}
FeatureType feature;
iF->second->Get(id.first, feature);
uint32_t penalty;
string name;
m_query.GetBestMatchName(feature, penalty, name);
return new impl::PreResult2(feature, r, name, countryName);
}
};
}
void Query::FlushResults(Results & res)
{
typedef impl::PreResult2 ResultT;
vector<IndexedValue> indV;
// fill vector with objects in queues
for (size_t i = 0; i < m_qCount; ++i)
{
indV.insert(indV.end(), m_results[i].begin(), m_results[i].end());
m_results[i].clear();
}
// make unique set of PreResult1
typedef set<shared_ptr<impl::PreResult1>, LessByFeatureID> PreResultSetT;
PreResultSetT theSet;
// remove equal objects
sort(indV.begin(), indV.end(), LessPointer());
indV.erase(unique(indV.begin(), indV.end(), EqualPointer()), indV.end());
/*
#ifdef DEBUG
{
impl::PreResult2Maker maker(*this);
LOG(LDEBUG, ("Dump features for rank:"));
for (QueueT::const_iterator i = m_results[0].begin(); i != m_results[0].end(); ++i)
{
impl::PreResult2 * res = maker(**i);
LOG(LDEBUG, (*res));
delete res;
}
LOG(LDEBUG, ("------------------------"));
}
#endif
*/
for (size_t i = 0; i < m_qCount; ++i)
{
theSet.insert(m_results[i].begin(), m_results[i].end());
m_results[i].clear();
}
// make PreResult2 vector
impl::PreResult2Maker maker(*this);
for (PreResultSetT::const_iterator i = theSet.begin(); i != theSet.end(); ++i)
{
impl::PreResult2 * res = maker(**i);
if (res == 0) continue;
// do not insert duplicating results
if (indV.end() == find_if(indV.begin(), indV.end(), ProxyFunctor1<ResultT::StrictEqualF>(res)))
indV.push_back(IndexedValue(res));
else
delete res;
}
}
// remove duplicating linear objects
sort(indV.begin(), indV.end(), ProxyFunctor2<ResultT::LessLinearTypesF>());
indV.erase(unique(indV.begin(), indV.end(), ProxyFunctor2<ResultT::EqualLinearTypesF>()),
indV.erase(unique(indV.begin(), indV.end(),
ProxyFunctor2<ResultT::EqualLinearTypesF>()),
indV.end());
for (size_t i = 0; i < m_qCount; ++i)
{
CompareT comp(g_arrCompare[i]);
CompareT<impl::PreResult2> comp(g_arrCompare2[i]);
// sort by needed criteria
sort(indV.begin(), indV.end(), comp);
@ -349,24 +435,44 @@ void Query::FlushResults(Results & res)
// sort results according to combined criteria
sort(indV.begin(), indV.end());
// emit results
// emit feature results
for (size_t i = 0; i < indV.size(); ++i)
{
if (m_cancel) return;
if (m_cancel) break;
LOG(LDEBUG, (indV[i]));
res.AddResult(indV[i].get()->GenerateFinalResult(m_pInfoGetter, m_pCategories));
res.AddResult((*(indV[i])).GenerateFinalResult(m_pInfoGetter, m_pCategories));
}
}
void Query::AddFeatureResult(FeatureType const & f, TrieValueT const & val, string const & fName)
namespace
{
uint32_t penalty;
string name;
GetBestMatchName(f, penalty, name);
class EqualFeature
{
typedef shared_ptr<impl::PreResult1> ValueT;
ValueT m_val;
AddResult(ValueT(new impl::IntermediateResult(
m_viewport, m_position, f, val.m_pt, val.m_rank, name, fName)));
public:
EqualFeature(ValueT const & v) : m_val(v) {}
bool operator() (ValueT const & r) const
{
return (m_val->GetID() == r->GetID());
}
};
}
void Query::AddResultFromTrie(TrieValueT const & val, size_t mwmID)
{
shared_ptr<impl::PreResult1> p(new impl::PreResult1(
val.m_featureId, val.m_rank, val.m_pt, mwmID, m_position, m_viewport));
for (size_t i = 0; i < m_qCount; ++i)
{
// here can be the duplicates because of different language match (for suggest token)
if (m_results[i].end() == find_if(m_results[i].begin(), m_results[i].end(), EqualFeature(p)))
m_results[i].push(shared_ptr<impl::PreResult1>(p));
}
}
namespace impl
@ -401,7 +507,15 @@ public:
void Query::GetBestMatchName(FeatureType const & f, uint32_t & penalty, string & name)
{
impl::BestNameFinder bestNameFinder(penalty, name, *m_pKeywordsScorer);
f.ForEachNameRef(bestNameFinder);
(void)f.ForEachNameRef(bestNameFinder);
/*
if (!f.ForEachNameRef(bestNameFinder))
{
feature::TypesHolder types(f);
LOG(LDEBUG, (types));
LOG(LDEBUG, (f.GetLimitRect(-1)));
}
*/
}
namespace impl
@ -409,46 +523,20 @@ namespace impl
class FeatureLoader
{
size_t m_count;
FeaturesVector & m_featuresVector;
Query & m_query;
string m_fName;
/*
class DoFindByName
{
string m_name;
public:
DoFindByName(char const * s) : m_name(s) {}
bool operator() (uint8_t, string const & s)
{
if (m_name.find_first_of(s) != string::npos)
LOG(LINFO, ("Found name: ", s));
return true;
}
};
*/
size_t m_mwmID;
size_t m_count;
public:
FeatureLoader(FeaturesVector & featuresVector, Query & query, string const & fName)
: m_count(0), m_featuresVector(featuresVector), m_query(query), m_fName(fName)
FeatureLoader(Query & query, size_t mwmID)
: m_query(query), m_mwmID(mwmID), m_count(0)
{
}
void operator() (trie::ValueReader::ValueType const & value)
void operator() (Query::TrieValueT const & value)
{
++m_count;
FeatureType feature;
m_featuresVector.Get(value.m_featureId, feature);
//#ifdef DEBUG
// DoFindByName doFind("ул. Карбышева");
// feature.ForEachNameRef(doFind);
//#endif
m_query.AddFeatureResult(feature, value, m_fName);
m_query.AddResultFromTrie(value, m_mwmID);
}
size_t GetCount() const { return m_count; }
@ -489,6 +577,7 @@ void Query::SearchFeatures()
langs.insert(StringUtf8Multilang::GetLangIndex("int_name"));
langs.insert(StringUtf8Multilang::GetLangIndex("en"));
langs.insert(StringUtf8Multilang::GetLangIndex("default"));
SearchFeatures(tokens, mwmInfo, langs, true);
}
@ -541,17 +630,11 @@ void Query::SearchFeatures(vector<vector<strings::UniString> > const & tokens,
trie::ValueReader(cp),
trie::EdgeValueReader()));
bool const isWorld = (header.GetType() == feature::DataHeader::world);
FeaturesVector featuresVector(pMwm->m_cont, header);
impl::FeatureLoader emitter(featuresVector, *this, isWorld ? "" : mwmLock.GetCountryName());
size_t const count = pTrieRoot->m_edge.size();
// Get categories edge root.
scoped_ptr<TrieIterator> pCategoriesRoot;
TrieIterator::Edge::EdgeStrT categoriesEdge;
size_t const count = pTrieRoot->m_edge.size();
for (size_t i = 0; i < count; ++i)
{
TrieIterator::Edge::EdgeStrT const & edge = pTrieRoot->m_edge[i].m_str;
@ -566,6 +649,10 @@ void Query::SearchFeatures(vector<vector<strings::UniString> > const & tokens,
}
ASSERT_NOT_EQUAL(pCategoriesRoot, 0, ());
bool const isWorld = (header.GetType() == feature::DataHeader::world);
impl::FeatureLoader emitter(*this, mwmId);
// Iterate through first language edges.
for (size_t i = 0; i < count; ++i)
{
@ -593,14 +680,14 @@ void Query::SearchFeatures(vector<vector<strings::UniString> > const & tokens,
}
}
void Query::SuggestStrings()
void Query::SuggestStrings(Results & res)
{
if (m_pStringsToSuggest)
{
if (m_tokens.size() == 0 && !m_prefix.empty())
{
// Match prefix.
MatchForSuggestions(m_prefix);
MatchForSuggestions(m_prefix, res);
}
else if (m_tokens.size() == 1)
{
@ -612,19 +699,20 @@ void Query::SuggestStrings()
tokenAndPrefix.append(m_prefix.begin(), m_prefix.end());
}
MatchForSuggestions(tokenAndPrefix);
MatchForSuggestions(tokenAndPrefix, res);
}
}
}
void Query::MatchForSuggestions(strings::UniString const & token)
void Query::MatchForSuggestions(strings::UniString const & token, Results & res)
{
StringsToSuggestVectorT::const_iterator it = m_pStringsToSuggest->begin();
for (; it != m_pStringsToSuggest->end(); ++it)
{
strings::UniString const & s = it->first;
if (it->second <= token.size() && StartsWith(s.begin(), s.end(), token.begin(), token.end()))
AddResult(ValueT(new impl::IntermediateResult(strings::ToUtf8(s), it->second)));
res.AddResult(impl::PreResult2(strings::ToUtf8(s), it->second).
GenerateFinalResult(m_pInfoGetter, m_pCategories));
}
}

View file

@ -28,11 +28,12 @@ namespace search
struct CategoryInfo;
class LangKeywordsScorer;
namespace impl
{
class IntermediateResult;
class FeatureLoader;
class BestNameFinder;
class PreResult2Maker;
}
class Query
@ -43,8 +44,6 @@ public:
// Vector of pairs (string_to_suggest, min_prefix_length_to_suggest).
typedef vector<pair<strings::UniString, uint8_t> > StringsToSuggestVectorT;
typedef trie::ValueReader::ValueType TrieValueT;
Query(Index const * pIndex,
CategoriesMapT const * pCategories,
StringsToSuggestVectorT const * pStringsToSuggest,
@ -67,25 +66,25 @@ public:
struct CancelException {};
private:
friend class impl::FeatureLoader;
friend class impl::BestNameFinder;
friend class impl::PreResult2Maker;
typedef impl::IntermediateResult ResultT;
typedef shared_ptr<ResultT> ValueT;
void AddResult(ValueT const & result);
void AddFeatureResult(FeatureType const & f, TrieValueT const & val, string const & fName);
void FlushResults(Results & res);
void UpdateViewportOffsets();
typedef trie::ValueReader::ValueType TrieValueT;
void AddResultFromTrie(TrieValueT const & val, size_t mwmID);
void FlushResults(Results & res);
void SearchFeatures();
void SearchFeatures(vector<vector<strings::UniString> > const & tokens,
vector<MwmInfo> const & mwmInfo,
unordered_set<int8_t> const & langs,
bool onlyInViewport);
void SuggestStrings();
void MatchForSuggestions(strings::UniString const & token);
void SuggestStrings(Results & res);
void MatchForSuggestions(strings::UniString const & token, Results & res);
void GetBestMatchName(FeatureType const & f, uint32_t & penalty, string & name);
@ -102,8 +101,7 @@ private:
buffer_vector<strings::UniString, 32> m_tokens;
strings::UniString m_prefix;
m2::RectD m_viewport;
m2::RectD m_viewportExtended;
m2::RectD m_viewport, m_viewportExtended;
m2::PointD m_position;
scoped_ptr<LangKeywordsScorer> m_pKeywordsScorer;
@ -111,9 +109,9 @@ private:
bool m_bOffsetsCacheIsValid;
vector<vector<uint32_t> > m_offsetsInViewport;
class CompareT
template <class ParamT> class CompareT
{
typedef bool (*FunctionT) (ResultT const &, ResultT const &);
typedef bool (*FunctionT) (ParamT const &, ParamT const &);
FunctionT m_fn;
public:
@ -126,7 +124,7 @@ private:
}
};
typedef my::limited_priority_queue<ValueT, CompareT> QueueT;
typedef my::limited_priority_queue<shared_ptr<impl::PreResult1>, CompareT<impl::PreResult1> > QueueT;
public:
static const size_t m_qCount = 3;