[indexer] Several FeatureType enhancements.

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
Viktor Govako 2022-02-13 19:21:22 +03:00
parent 93ad046f23
commit c3fb65a653
9 changed files with 94 additions and 122 deletions

View file

@ -286,14 +286,8 @@ void FeatureBuilder::RemoveUselessNames()
{
if (!m_params.name.IsEmpty() && !IsCoastCell())
{
// Use lambda syntax to correctly compile according to standard:
// http://en.cppreference.com/w/cpp/algorithm/remove
// The signature of the predicate function should be equivalent to the following:
// bool pred(const Type &a);
// Without it on clang-libc++ on Linux we get:
// candidate template ignored: substitution failure
// [with _Tp = bool (unsigned int) const]: reference to function type 'bool (unsigned int) const' cannot have 'const'
// qualifier
// Remove names for boundary-administrative-* features.
// AFAIR, they were very messy in search because they contain places' names.
auto const typeRemover = [](uint32_t type)
{
static TypeSetChecker const checkBoundary({ "boundary", "administrative" });
@ -303,6 +297,7 @@ void FeatureBuilder::RemoveUselessNames()
auto types = GetTypesHolder();
if (types.RemoveIf(typeRemover))
{
// Remove only if there are no other text-style types in feature (e.g. highway).
pair<int, int> const range = GetDrawableScaleRangeForRules(types, RULE_ANY_TEXT);
if (range.first == -1)
m_params.name.Clear();
@ -623,20 +618,25 @@ bool FeatureBuilder::IsDrawableInRange(int lowScale, int highScale) const
bool FeatureBuilder::PreSerializeAndRemoveUselessNamesForMwm(SupportingData const & data)
{
// make flags actual before header serialization
// We don't need empty features without geometry.
GeomType const geomType = m_params.GetGeomType();
if (geomType == GeomType::Line)
{
if (data.m_ptsMask == 0 && data.m_innerPts.empty())
{
LOG(LWARNING, ("Skip feature with empty geometry", GetMostGenericOsmId()));
return false;
}
}
else if (geomType == GeomType::Area)
{
if (data.m_trgMask == 0 && data.m_innerTrg.empty())
{
LOG(LWARNING, ("Skip feature with empty geometry", GetMostGenericOsmId()));
return false;
}
}
// we don't need empty features without geometry
return PreSerializeAndRemoveUselessNamesForIntermediate();
}
@ -784,7 +784,7 @@ string DebugPrint(FeatureBuilder const & fb)
out << " " << DebugPrint(fb.GetLimitRect())
<< " " << DebugPrint(fb.GetParams())
<< " " << ::DebugPrint(fb.GetOsmIds());
<< " " << ::DebugPrint(fb.m_osmIds);
return out.str();
}

View file

@ -54,7 +54,8 @@ public:
bool IsValid() const;
// To work with geometry.
/// @name To work with geometry.
///@{
void AddPoint(m2::PointD const & p);
void SetHoles(Geometry const & holes);
void AddPolygon(std::vector<m2::PointD> & poly);
@ -68,7 +69,7 @@ public:
m2::PointD GetKeyPoint() const;
size_t GetPointsCount() const;
size_t GetPolygonsCount() const { return m_polygons.size(); }
size_t GetTypesCount() const { return m_params.m_types.size(); }
///@}
template <class ToDo>
void ForEachPoint(ToDo && toDo) const
@ -117,7 +118,8 @@ public:
bool IsLine() const { return GetGeomType() == GeomType::Line; }
bool IsArea() const { return GetGeomType() == GeomType::Area; }
// To work with types.
/// @name To work with types.
///@{
void SetType(uint32_t type) { m_params.SetType(type); }
void AddType(uint32_t type) { m_params.AddType(type); }
bool PopExactType(uint32_t type) { return m_params.PopExactType(type); }
@ -133,6 +135,8 @@ public:
bool HasType(uint32_t t, uint8_t level) const { return m_params.IsTypeExist(t, level); }
uint32_t FindType(uint32_t comp, uint8_t level) const { return m_params.FindType(comp, level); }
FeatureParams::Types const & GetTypes() const { return m_params.m_types; }
size_t GetTypesCount() const { return m_params.m_types.size(); }
///@}
// To work with additional information.
void SetRank(uint8_t rank);
@ -160,7 +164,8 @@ public:
int GetMinFeatureDrawScale() const;
bool IsDrawableInRange(int lowScale, int highScale) const;
// Serialization.
/// @name Serialization.
///@{
bool PreSerialize();
bool PreSerializeAndRemoveUselessNamesForIntermediate();
void SerializeForIntermediate(Buffer & data) const;
@ -176,11 +181,13 @@ public:
void SerializeLocalityObject(serial::GeometryCodingParams const & params,
SupportingData & data) const;
void SerializeForMwm(SupportingData & data, serial::GeometryCodingParams const & params) const;
///@}
// Get common parameters of feature.
TypesHolder GetTypesHolder() const;
// To work with osm ids.
/// @name To work with osm ids.
///@{
void AddOsmId(base::GeoObjectId id);
void SetOsmId(base::GeoObjectId id);
base::GeoObjectId GetFirstOsmId() const;
@ -190,12 +197,14 @@ public:
base::GeoObjectId GetMostGenericOsmId() const;
bool HasOsmId(base::GeoObjectId const & id) const;
bool HasOsmIds() const { return !m_osmIds.empty(); }
std::vector<base::GeoObjectId> const & GetOsmIds() const { return m_osmIds; }
///@}
// To work with coasts.
void SetCoastCell(int64_t iCell) { m_coastCell = iCell; }
bool IsCoastCell() const { return (m_coastCell != -1); }
friend std::string DebugPrint(FeatureBuilder const & fb);
protected:
// Can be one of the following:
// - point in point-feature
@ -211,8 +220,6 @@ protected:
int64_t m_coastCell;
};
std::string DebugPrint(FeatureBuilder const & fb);
// SerializationPolicy serialization and deserialization.
namespace serialization_policy
{

View file

@ -577,18 +577,15 @@ LocalizedStreet const & EditableMapObject::GetStreet() const { return m_street;
void EditableMapObject::SetCuisines(vector<string> const & cuisines)
{
FeatureParams params;
params.m_types.insert(params.m_types.begin(), m_types.begin(), m_types.end());
params.m_types.assign(m_types.begin(), m_types.end());
Classificator const & cl = classif();
for (auto const & cuisine : cuisines)
params.m_types.push_back(classif().GetTypeByPath({"cuisine", cuisine}));
params.m_types.push_back(cl.GetTypeByPath({"cuisine", cuisine}));
// Move useless types to the end and resize to fit TypesHolder.
params.FinishAddingTypes();
feature::TypesHolder types;
for (auto const t : params.m_types)
types.Add(t);
m_types = types;
m_types.Assign(params.m_types.begin(), params.m_types.end());
}
void EditableMapObject::SetOpeningHours(string const & openingHours)

View file

@ -585,7 +585,8 @@ string FeatureType::DebugString(int scale)
Classificator const & c = classif();
string res = "Types";
for (size_t i = 0; i < GetTypesCount(); ++i)
uint32_t const count = GetTypesCount();
for (size_t i = 0; i < count; ++i)
res += (" : " + c.GetReadableObjectName(m_types[i]));
res += "\n";

View file

@ -26,7 +26,7 @@ using namespace std::placeholders;
namespace feature
{
string DebugPrint(TypesHolder const & holder)
template <class ContT> string TypesToString(ContT const & holder)
{
Classificator const & c = classif();
string s;
@ -37,6 +37,11 @@ string DebugPrint(TypesHolder const & holder)
return s;
}
std::string DebugPrint(TypesHolder const & holder)
{
return TypesToString(holder);
}
TypesHolder::TypesHolder(FeatureType & f) : m_size(0), m_geomType(f.GetGeomType())
{
f.ForEachType([this](uint32_t type)
@ -45,18 +50,6 @@ TypesHolder::TypesHolder(FeatureType & f) : m_size(0), m_geomType(f.GetGeomType(
});
}
// static
TypesHolder TypesHolder::FromTypesIndexes(std::vector<uint32_t> const & indexes)
{
TypesHolder result;
for (auto index : indexes)
{
result.Add(classif().GetTypeForIndex(index));
}
return result;
}
void TypesHolder::Remove(uint32_t type)
{
UNUSED_VALUE(RemoveIf(base::EqualFunctor<uint32_t>(type)));
@ -67,13 +60,16 @@ bool TypesHolder::Equals(TypesHolder const & other) const
if (m_size != other.m_size)
return false;
vector<uint32_t> my(this->begin(), this->end());
vector<uint32_t> his(other.begin(), other.end());
// Dynamic vector + sort for kMaxTypesCount array is a huge overhead.
sort(::begin(my), ::end(my));
sort(::begin(his), ::end(his));
return my == his;
auto const b = begin();
auto const e = end();
for (auto t : other)
{
if (std::find(b, e, t) == e)
return false;
}
return true;
}
} // namespace feature
@ -402,24 +398,6 @@ void FeatureParams::SetRwSubwayType(char const * cityName)
}
}
void FeatureParams::AddTypes(FeatureParams const & rhs, uint32_t skipType2)
{
if (skipType2 == 0)
{
m_types.insert(m_types.end(), rhs.m_types.begin(), rhs.m_types.end());
}
else
{
for (size_t i = 0; i < rhs.m_types.size(); ++i)
{
uint32_t t = rhs.m_types[i];
ftype::TruncValue(t, 2);
if (t != skipType2)
m_types.push_back(rhs.m_types[i]);
}
}
}
bool FeatureParams::FinishAddingTypes()
{
base::SortUnique(m_types);
@ -524,12 +502,7 @@ void FeatureBuilderParams::AddPostcode(string const & s)
string DebugPrint(FeatureParams const & p)
{
Classificator const & c = classif();
string res = "Types: ";
for (size_t i = 0; i < p.m_types.size(); ++i)
res = res + c.GetReadableObjectName(p.m_types[i]) + "; ";
string res = "Types: " + TypesToString(p.m_types) + "; ";
return (res + p.DebugString());
}
@ -539,6 +512,6 @@ string DebugPrint(FeatureBuilderParams const & p)
oss << "ReversedGeometry: " << (p.GetReversedGeometry() ? "true" : "false") << "; ";
oss << DebugPrint(p.GetMetadata()) << "; ";
oss << DebugPrint(p.GetAddressData()) << "; ";
oss << DebugPrint(FeatureParams(p));
oss << DebugPrint(static_cast<FeatureParams const &>(p));
return oss.str();
}

View file

@ -62,32 +62,36 @@ namespace feature
explicit TypesHolder(GeomType geomType) : m_geomType(geomType) {}
explicit TypesHolder(FeatureType & f);
static TypesHolder FromTypesIndexes(std::vector<uint32_t> const & indexes);
void Assign(uint32_t type)
{
m_types[0] = type;
m_size = 1;
}
/// Accumulation function.
template <class IterT> void Assign(IterT beg, IterT end)
{
m_size = std::distance(beg, end);
CHECK_LESS_OR_EQUAL(m_size, kMaxTypesCount, ());
std::copy(beg, end, m_types.begin());
}
void Add(uint32_t type)
{
ASSERT_LESS(m_size, kMaxTypesCount, ());
if (m_size < kMaxTypesCount)
m_types[m_size++] = type;
CHECK_LESS(m_size, kMaxTypesCount, ());
m_types[m_size++] = type;
}
GeomType GetGeomType() const { return m_geomType; }
size_t Size() const { return m_size; }
bool Empty() const { return (m_size == 0); }
Types::const_iterator cbegin() const { return m_types.cbegin(); }
Types::const_iterator cend() const { return m_types.cbegin() + m_size; }
Types::const_iterator begin() const { return m_types.cbegin(); }
Types::const_iterator end() const { return m_types.cbegin() + m_size; }
Types::iterator begin() { return m_types.begin(); }
Types::iterator end() { return m_types.begin() + m_size; }
auto cbegin() const { return m_types.cbegin(); }
auto cend() const { return m_types.cbegin() + m_size; }
auto begin() const { return m_types.cbegin(); }
auto end() const { return m_types.cbegin() + m_size; }
auto begin() { return m_types.begin(); }
auto end() { return m_types.begin() + m_size; }
/// Assume that m_types is already sorted by SortBySpec function.
uint32_t GetBestType() const
@ -114,8 +118,6 @@ namespace feature
/// Sort types by it's specification (more detailed type goes first).
void SortBySpec();
/// Returns true if this->m_types and other.m_types contain same values
/// in any order. Works in O(n log n).
bool Equals(TypesHolder const & other) const;
std::vector<std::string> ToObjectNames() const;
@ -133,7 +135,6 @@ namespace feature
FeatureParamsBase const & params);
} // namespace feature
/// Feature description struct.
struct FeatureParamsBase
{
StringUtf8Multilang name;
@ -236,10 +237,6 @@ public:
/// the special subway type for the correspondent city.
void SetRwSubwayType(char const * cityName);
/// @param skipType2 Do not accumulate this type if skipType2 != 0.
/// '2' means 2-level type in classificator tree (also skip child types).
void AddTypes(FeatureParams const & rhs, uint32_t skipType2);
bool FinishAddingTypes();
void SetType(uint32_t t);

View file

@ -2,8 +2,6 @@
#include "std/target_os.hpp"
#include <sstream>
using namespace std;
namespace feature
@ -207,9 +205,8 @@ string ToString(Metadata::EType type)
string DebugPrint(Metadata const & metadata)
{
ostringstream oss;
bool first = true;
oss << "Metadata [";
std::string res = "Metadata [";
for (uint8_t i = 0; i < static_cast<uint8_t>(Metadata::FMD_COUNT); ++i)
{
auto const t = static_cast<Metadata::EType>(i);
@ -219,21 +216,19 @@ string DebugPrint(Metadata const & metadata)
if (first)
first = false;
else
oss << "; ";
res += "; ";
oss << DebugPrint(t) << "=" << s;
res = res + DebugPrint(t) + "=" + s;
}
}
oss << "]";
return oss.str();
res += "]";
return res;
}
string DebugPrint(feature::AddressData const & addressData)
{
ostringstream oss;
oss << "AddressData [";
oss << "Street = \"" << addressData.Get(AddressData::Type::Street) << "\"; ";
oss << "Postcode = \"" << addressData.Get(AddressData::Type::Postcode) << "\"]";
return oss.str();
return std::string("AddressData [") +
"Street = \"" + addressData.Get(AddressData::Type::Street) + "\"; " +
"Postcode = \"" + addressData.Get(AddressData::Type::Postcode) + "\"]";
}
} // namespace feature

View file

@ -83,18 +83,13 @@ protected:
// TODO: Change uint8_t to appropriate type when FMD_COUNT reaches 256.
void Set(uint8_t type, std::string const & value)
{
auto found = m_metadata.find(type);
if (found == m_metadata.end())
{
if (!value.empty())
m_metadata[type] = value;
}
if (value.empty())
m_metadata.erase(type);
else
{
if (value.empty())
m_metadata.erase(found);
else
found->second = value;
auto res = m_metadata.try_emplace(type, value);
if (!res.second)
res.first->second = value;
}
}

View file

@ -578,9 +578,22 @@ kml::MarkGroupId Framework::AddCategory(string const & categoryName)
void Framework::FillPointInfoForBookmark(Bookmark const & bmk, place_page::Info & info) const
{
auto types = feature::TypesHolder::FromTypesIndexes(bmk.GetData().m_featureTypes);
FillPointInfo(info, bmk.GetPivot(), {} /* customTitle */, [&types](FeatureType & ft) {
return !types.Empty() && feature::TypesHolder(ft).Equals(types);
// Convert indices to sorted classifier types.
Classificator const & cl = classif();
buffer_vector<uint8_t, 8> types;
for (uint32_t i : bmk.GetData().m_featureTypes)
types.push_back(cl.GetTypeForIndex(i));
std::sort(types.begin(), types.end());
FillPointInfo(info, bmk.GetPivot(), {} /* customTitle */, [&types](FeatureType & ft)
{
if (types.empty() || ft.GetTypesCount() != types.size())
return false;
// Strict equal types.
feature::TypesHolder fTypes(ft);
std::sort(fTypes.begin(), fTypes.end());
return std::equal(types.begin(), types.end(), fTypes.begin(), fTypes.end());
});
}
@ -2575,12 +2588,6 @@ void Framework::BlockTapEvents(bool block)
m_drapeEngine->BlockTapEvents(block);
}
namespace feature
{
string GetPrintableTypes(FeatureType & ft) { return DebugPrint(feature::TypesHolder(ft)); }
uint32_t GetBestType(FeatureType & ft) { return feature::TypesHolder(ft).GetBestType(); }
}
bool Framework::ParseDrapeDebugCommand(string const & query)
{
MapStyle desiredStyle = MapStyleCount;