forked from organicmaps/organicmaps
[editor] Integration with search by feature’s name.
This commit is contained in:
parent
52a447d605
commit
172ae59ca5
3 changed files with 99 additions and 28 deletions
|
@ -5,11 +5,13 @@
|
|||
#include "interval_set.hpp"
|
||||
#include "mwm_traits.hpp"
|
||||
#include "search_index_values.hpp"
|
||||
#include "search_string_utils.hpp"
|
||||
#include "search_trie.hpp"
|
||||
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_algo.hpp"
|
||||
#include "indexer/index.hpp"
|
||||
#include "indexer/osm_editor.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
#include "indexer/trie_reader.hpp"
|
||||
|
||||
|
@ -25,6 +27,8 @@
|
|||
#include "std/cmath.hpp"
|
||||
#include "std/limits.hpp"
|
||||
|
||||
using osm::Editor;
|
||||
|
||||
namespace search
|
||||
{
|
||||
namespace
|
||||
|
@ -53,17 +57,58 @@ void CoverRect(m2::RectD const & rect, int scale, covering::IntervalsT & result)
|
|||
result.insert(result.end(), intervals.begin(), intervals.end());
|
||||
}
|
||||
|
||||
bool MatchFeatureByName(FeatureType const & ft, SearchQueryParams const & params)
|
||||
{
|
||||
bool matched = false;
|
||||
auto const matcher = [&](int8_t /*lang*/, string const & utf8Name) -> bool
|
||||
{
|
||||
auto const name = search::NormalizeAndSimplifyString(utf8Name);
|
||||
for (auto const & prefix : params.m_prefixTokens)
|
||||
{
|
||||
if (strings::StartsWith(name, prefix))
|
||||
{
|
||||
matched = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto const & synonyms : params.m_tokens)
|
||||
{
|
||||
for (auto const & token : synonyms)
|
||||
{
|
||||
if (token == name)
|
||||
{
|
||||
matched = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; // To iterate all names.
|
||||
};
|
||||
ft.ForEachName(matcher);
|
||||
return matched;
|
||||
}
|
||||
|
||||
// Retrieves from the search index corresponding to |value| all
|
||||
// features matching to |params|.
|
||||
template <typename TValue>
|
||||
unique_ptr<coding::CompressedBitVector> RetrieveAddressFeaturesImpl(
|
||||
MwmValue & value, my::Cancellable const & cancellable, SearchQueryParams const & params)
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
SearchQueryParams const & params)
|
||||
{
|
||||
serial::CodingParams codingParams(trie::GetCodingParams(value.GetHeader().GetDefCodingParams()));
|
||||
ModelReaderPtr searchReader = value.m_cont.GetReader(SEARCH_INDEX_FILE_TAG);
|
||||
|
||||
auto emptyFilter = [](uint32_t /* featureId */)
|
||||
// Exclude from search all deleted/modified features and match all edited/created features separately.
|
||||
Editor & editor = Editor::Instance();
|
||||
auto const deleted = editor.GetFeaturesByStatus(id, Editor::FeatureStatus::Deleted);
|
||||
// Modified features should be re-matched again.
|
||||
auto const modified = editor.GetFeaturesByStatus(id, Editor::FeatureStatus::Modified);
|
||||
auto const filter = [&](uint32_t featureIndex) -> bool
|
||||
{
|
||||
if (binary_search(deleted.begin(), deleted.end(), featureIndex))
|
||||
return false;
|
||||
if (binary_search(modified.begin(), modified.end(), featureIndex))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -74,29 +119,47 @@ unique_ptr<coding::CompressedBitVector> RetrieveAddressFeaturesImpl(
|
|||
// bit vectors are sorted in the search index.
|
||||
vector<uint64_t> features;
|
||||
uint32_t counter = 0;
|
||||
auto collector = [&](TValue const & value)
|
||||
auto const collector = [&](TValue const & value)
|
||||
{
|
||||
if ((++counter & 0xFF) == 0)
|
||||
BailIfCancelled(cancellable);
|
||||
features.push_back(value.m_featureId);
|
||||
};
|
||||
|
||||
MatchFeaturesInTrie(params, *trieRoot, emptyFilter, collector);
|
||||
MatchFeaturesInTrie(params, *trieRoot, filter, collector);
|
||||
|
||||
// Match all edited/created features separately.
|
||||
auto const matcher = [&](uint32_t featureIndex)
|
||||
{
|
||||
FeatureType ft;
|
||||
VERIFY(editor.GetEditedFeature(id, featureIndex, ft), ());
|
||||
// TODO(AlexZ): Should we match by some feature's metafields too?
|
||||
if (MatchFeatureByName(ft, params))
|
||||
features.push_back(featureIndex);
|
||||
};
|
||||
for_each(modified.begin(), modified.end(), matcher);
|
||||
auto const created = editor.GetFeaturesByStatus(id, Editor::FeatureStatus::Created);
|
||||
for_each(created.begin(), created.end(), matcher);
|
||||
|
||||
return SortFeaturesAndBuildCBV(move(features));
|
||||
}
|
||||
|
||||
// Retrieves from the geometry index corresponding to handle all
|
||||
// features from |coverage|.
|
||||
unique_ptr<coding::CompressedBitVector> RetrieveGeometryFeaturesImpl(
|
||||
MwmValue & value, my::Cancellable const & cancellable, covering::IntervalsT const & coverage,
|
||||
int scale)
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
covering::IntervalsT const & coverage, int scale)
|
||||
{
|
||||
// TODO(AlexZ): Also add created features.
|
||||
auto const deleted = Editor::Instance().GetFeaturesByStatus(id, Editor::FeatureStatus::Deleted);
|
||||
// TODO (@y, @m): remove this code as soon as geometry index will
|
||||
// have native support for bit vectors.
|
||||
vector<uint64_t> features;
|
||||
uint32_t counter = 0;
|
||||
auto collector = [&](uint64_t featureId)
|
||||
auto const collector = [&](uint64_t featureId)
|
||||
{
|
||||
if (binary_search(deleted.begin(), deleted.end(), static_cast<uint32_t>(featureId)))
|
||||
return;
|
||||
if ((++counter & 0xFF) == 0)
|
||||
BailIfCancelled(cancellable);
|
||||
features.push_back(featureId);
|
||||
|
@ -233,8 +296,9 @@ public:
|
|||
{
|
||||
covering::IntervalsT coverage;
|
||||
CoverRect(currViewport, m_coverageScale, coverage);
|
||||
geometryFeatures = RetrieveGeometryFeaturesImpl(*m_handle.GetValue<MwmValue>(), cancellable,
|
||||
coverage, m_coverageScale);
|
||||
geometryFeatures =
|
||||
RetrieveGeometryFeaturesImpl(m_handle.GetId(), *m_handle.GetValue<MwmValue>(),
|
||||
cancellable, coverage, m_coverageScale);
|
||||
for (auto const & interval : coverage)
|
||||
m_visited.Add(interval);
|
||||
}
|
||||
|
@ -267,8 +331,9 @@ public:
|
|||
for (auto const & interval : coverage)
|
||||
m_visited.SubtractFrom(interval, reducedCoverage);
|
||||
|
||||
geometryFeatures = RetrieveGeometryFeaturesImpl(*m_handle.GetValue<MwmValue>(), cancellable,
|
||||
reducedCoverage, m_coverageScale);
|
||||
geometryFeatures =
|
||||
RetrieveGeometryFeaturesImpl(m_handle.GetId(), *m_handle.GetValue<MwmValue>(),
|
||||
cancellable, reducedCoverage, m_coverageScale);
|
||||
|
||||
for (auto const & interval : reducedCoverage)
|
||||
m_visited.Add(interval);
|
||||
|
@ -367,7 +432,8 @@ Retrieval::Retrieval() : m_index(nullptr), m_featuresReported(0) {}
|
|||
|
||||
// static
|
||||
unique_ptr<coding::CompressedBitVector> Retrieval::RetrieveAddressFeatures(
|
||||
MwmValue & value, my::Cancellable const & cancellable, SearchQueryParams const & params)
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
SearchQueryParams const & params)
|
||||
{
|
||||
MwmTraits mwmTraits(value.GetMwmVersion().format);
|
||||
|
||||
|
@ -375,24 +441,25 @@ unique_ptr<coding::CompressedBitVector> Retrieval::RetrieveAddressFeatures(
|
|||
MwmTraits::SearchIndexFormat::FeaturesWithRankAndCenter)
|
||||
{
|
||||
using TValue = FeatureWithRankAndCenter;
|
||||
return RetrieveAddressFeaturesImpl<TValue>(value, cancellable, params);
|
||||
return RetrieveAddressFeaturesImpl<TValue>(id, value, cancellable, params);
|
||||
}
|
||||
else if (mwmTraits.GetSearchIndexFormat() ==
|
||||
MwmTraits::SearchIndexFormat::CompressedBitVector)
|
||||
{
|
||||
using TValue = FeatureIndexValue;
|
||||
return RetrieveAddressFeaturesImpl<TValue>(value, cancellable, params);
|
||||
return RetrieveAddressFeaturesImpl<TValue>(id, value, cancellable, params);
|
||||
}
|
||||
return unique_ptr<coding::CompressedBitVector>();
|
||||
}
|
||||
|
||||
// static
|
||||
unique_ptr<coding::CompressedBitVector> Retrieval::RetrieveGeometryFeatures(
|
||||
MwmValue & value, my::Cancellable const & cancellable, m2::RectD const & rect, int scale)
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
m2::RectD const & rect, int scale)
|
||||
{
|
||||
covering::IntervalsT coverage;
|
||||
CoverRect(rect, scale, coverage);
|
||||
return RetrieveGeometryFeaturesImpl(value, cancellable, coverage, scale);
|
||||
return RetrieveGeometryFeaturesImpl(id, value, cancellable, coverage, scale);
|
||||
}
|
||||
|
||||
void Retrieval::Init(Index & index, vector<shared_ptr<MwmInfo>> const & infos,
|
||||
|
@ -526,8 +593,8 @@ bool Retrieval::InitBucketStrategy(Bucket & bucket, double scale)
|
|||
try
|
||||
{
|
||||
addressFeatures =
|
||||
RetrieveAddressFeatures(*bucket.m_handle.GetValue<MwmValue>(), *this /* cancellable */,
|
||||
m_params);
|
||||
RetrieveAddressFeatures(bucket.m_handle.GetId(), *bucket.m_handle.GetValue<MwmValue>(),
|
||||
*this /* cancellable */, m_params);
|
||||
}
|
||||
catch (CancelException &)
|
||||
{
|
||||
|
|
|
@ -107,11 +107,13 @@ public:
|
|||
// Retrieves from the search index corresponding to |value| all
|
||||
// features matching to |params|.
|
||||
WARN_UNUSED_RESULT static unique_ptr<coding::CompressedBitVector> RetrieveAddressFeatures(
|
||||
MwmValue & value, my::Cancellable const & cancellable, SearchQueryParams const & params);
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
SearchQueryParams const & params);
|
||||
|
||||
// Retrieves from the geometry index corresponding to |value| all features belonging to |rect|.
|
||||
WARN_UNUSED_RESULT static unique_ptr<coding::CompressedBitVector> RetrieveGeometryFeatures(
|
||||
MwmValue & value, my::Cancellable const & cancellable, m2::RectD const & rect, int scale);
|
||||
MwmSet::MwmId const & id, MwmValue & value, my::Cancellable const & cancellable,
|
||||
m2::RectD const & rect, int scale);
|
||||
|
||||
// Initializes retrieval process, sets up internal state, takes all
|
||||
// necessary system resources.
|
||||
|
|
|
@ -460,9 +460,9 @@ void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
|
|||
unique_ptr<coding::CompressedBitVector> viewportCBV;
|
||||
if (inViewport)
|
||||
{
|
||||
viewportCBV = Retrieval::RetrieveGeometryFeatures(
|
||||
m_context->m_value, cancellable,
|
||||
m_params.m_viewport, m_params.m_scale);
|
||||
viewportCBV =
|
||||
Retrieval::RetrieveGeometryFeatures(m_context->m_id, m_context->m_value, cancellable,
|
||||
m_params.m_viewport, m_params.m_scale);
|
||||
}
|
||||
|
||||
// Creates a cache of posting lists for each token.
|
||||
|
@ -472,7 +472,7 @@ void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
|
|||
PrepareRetrievalParams(i, i + 1);
|
||||
|
||||
m_addressFeatures[i] = Retrieval::RetrieveAddressFeatures(
|
||||
m_context->m_value, cancellable, m_retrievalParams);
|
||||
m_context->m_id, m_context->m_value, cancellable, m_retrievalParams);
|
||||
ASSERT(m_addressFeatures[i], ());
|
||||
|
||||
if (viewportCBV)
|
||||
|
@ -535,7 +535,8 @@ void Geocoder::FillLocalitiesTable(MwmContext const & context)
|
|||
{
|
||||
PrepareRetrievalParams(i, i + 1);
|
||||
tokensCBV.push_back(Retrieval::RetrieveAddressFeatures(
|
||||
context.m_value, static_cast<my::Cancellable const &>(*this), m_retrievalParams));
|
||||
context.m_id, context.m_value, static_cast<my::Cancellable const &>(*this),
|
||||
m_retrievalParams));
|
||||
}
|
||||
|
||||
// 2. Get all locality candidates for the continuous token ranges.
|
||||
|
@ -1119,7 +1120,7 @@ coding::CompressedBitVector const * Geocoder::LoadStreets(MwmContext & context)
|
|||
{
|
||||
m_retrievalParams.m_tokens[0][0] = category;
|
||||
auto streets = Retrieval::RetrieveAddressFeatures(
|
||||
context.m_value, *this /* cancellable */,
|
||||
context.m_id, context.m_value, *this /* cancellable */,
|
||||
m_retrievalParams);
|
||||
if (!coding::CompressedBitVector::IsEmpty(streets))
|
||||
streetsList.push_back(move(streets));
|
||||
|
@ -1160,8 +1161,9 @@ coding::CompressedBitVector const * Geocoder::RetrieveGeometryFeatures(MwmContex
|
|||
return v.m_cbv.get();
|
||||
}
|
||||
|
||||
auto cbv = Retrieval::RetrieveGeometryFeatures(
|
||||
context.m_value, static_cast<my::Cancellable const &>(*this), rect, m_params.m_scale);
|
||||
auto cbv = Retrieval::RetrieveGeometryFeatures(context.m_id, context.m_value,
|
||||
static_cast<my::Cancellable const &>(*this), rect,
|
||||
m_params.m_scale);
|
||||
|
||||
auto const * result = cbv.get();
|
||||
features.push_back({m2::Inflate(rect, kComparePoints, kComparePoints), move(cbv), id});
|
||||
|
|
Loading…
Add table
Reference in a new issue