forked from organicmaps/organicmaps-tmp
[search] Divide IntermediateResukt into PreResult1 and PreResult2. Do not load features, while making PreResult1.
This commit is contained in:
parent
b07616b315
commit
a2273f714f
4 changed files with 367 additions and 283 deletions
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue