blob: fb7c022714b7f6421d9ff176158847e6f330d7a1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#pragma once
#include "search/intermediate_result.hpp"
#include "search/nested_rects_cache.hpp"
#include "search/ranker.hpp"
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"
#include "base/macros.hpp"
#include <algorithm>
#include <cstddef>
#include <random>
#include <set>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
class DataSource;
namespace search
{
// Fast and simple pre-ranker for search results.
class PreRanker
{
public:
struct Params
{
// Minimal distance between search results in mercators, needed for
// filtering of viewport search results.
double m_minDistanceOnMapBetweenResults = 0.0;
// This is different from geocoder's pivot because pivot is
// usually a rectangle created by radius and center and, due to
// precision loss, its center may differ from
// |m_accuratePivotCenter|. Therefore the pivot should be used for
// fast filtering of features outside of the rectangle, while
// |m_accuratePivotCenter| should be used when it's needed to
// compute the distance from a feature to the pivot.
m2::PointD m_accuratePivotCenter;
boost::optional<m2::PointD> m_position;
m2::RectD m_viewport;
int m_scale = 0;
size_t m_batchSize = 100;
// The maximum total number of results to be emitted in all batches.
size_t m_limit = 0;
bool m_viewportSearch = false;
bool m_categorialRequest = false;
};
PreRanker(DataSource const & dataSource, Ranker & ranker);
void Init(Params const & params);
void Finish(bool cancelled);
template <typename... Args>
void Emplace(Args &&... args)
{
if (m_numSentResults >= Limit())
return;
m_results.emplace_back(std::forward<Args>(args)...);
}
// Computes missing fields for all pre-results.
void FillMissingFieldsInPreResults();
void Filter(bool viewportSearch);
// Emit a new batch of results up the pipeline (i.e. to ranker).
// Use |lastUpdate| to indicate that no more results will be added.
void UpdateResults(bool lastUpdate);
inline size_t Size() const { return m_results.size(); }
inline size_t BatchSize() const { return m_params.m_batchSize; }
inline size_t NumSentResults() const { return m_numSentResults; }
inline size_t Limit() const { return m_params.m_limit; }
template <typename Fn>
void ForEach(Fn && fn)
{
std::for_each(m_results.begin(), m_results.end(), std::forward<Fn>(fn));
}
void ClearCaches();
private:
void FilterForViewportSearch();
void FilterRelaxedResults(bool lastUpdate);
DataSource const & m_dataSource;
Ranker & m_ranker;
std::vector<PreRankerResult> m_results;
std::vector<PreRankerResult> m_relaxedResults;
Params m_params;
// Amount of results sent up the pipeline.
size_t m_numSentResults = 0;
// Cache of nested rects used to estimate distance from a feature to the pivot.
NestedRectsCache m_pivotFeatures;
// A set of ids for features that are emitted during the current search session.
std::set<FeatureID> m_currEmit;
// A set of ids for features that were emitted during the previous
// search session. They're used for filtering of current search in
// viewport results, because we need to give more priority to
// results that were on map previously.
std::set<FeatureID> m_prevEmit;
std::minstd_rand m_rng;
DISALLOW_COPY_AND_MOVE(PreRanker);
};
} // namespace search
|