forked from organicmaps/organicmaps
Base class MapObject to store feature properties and query them in UI code.
This commit is contained in:
parent
2cf158a887
commit
9ec64c31e4
3 changed files with 321 additions and 0 deletions
|
@ -41,6 +41,7 @@ SOURCES += \
|
|||
geometry_serialization.cpp \
|
||||
index.cpp \
|
||||
index_builder.cpp \
|
||||
map_object.cpp \
|
||||
map_style.cpp \
|
||||
map_style_reader.cpp \
|
||||
mwm_set.cpp \
|
||||
|
@ -92,6 +93,7 @@ HEADERS += \
|
|||
interval_index.hpp \
|
||||
interval_index_builder.hpp \
|
||||
interval_index_iface.hpp \
|
||||
map_object.hpp \
|
||||
map_style.hpp \
|
||||
map_style_reader.hpp \
|
||||
mwm_set.hpp \
|
||||
|
|
172
indexer/map_object.cpp
Normal file
172
indexer/map_object.cpp
Normal file
|
@ -0,0 +1,172 @@
|
|||
#include "map_object.hpp"
|
||||
|
||||
#include "indexer/categories_holder.hpp"
|
||||
#include "indexer/cuisines.hpp"
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_algo.hpp"
|
||||
|
||||
#include "platform/measurement_utils.hpp"
|
||||
#include "platform/preferred_languages.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
namespace osm
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr char const * kWlan = "wlan";
|
||||
constexpr char const * kWired = "wired";
|
||||
constexpr char const * kYes = "yes";
|
||||
constexpr char const * kNo = "no";
|
||||
}
|
||||
|
||||
string DebugPrint(osm::Internet internet)
|
||||
{
|
||||
switch (internet)
|
||||
{
|
||||
case Internet::No: return kNo;
|
||||
case Internet::Yes: return kYes;
|
||||
case Internet::Wlan: return kWlan;
|
||||
case Internet::Wired: return kWired;
|
||||
case Internet::Unknown: break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
string DebugPrint(Props props)
|
||||
{
|
||||
string k;
|
||||
switch (props)
|
||||
{
|
||||
case osm::Props::Phone: k = "phone"; break;
|
||||
case osm::Props::Fax: k = "fax"; break;
|
||||
case osm::Props::Email: k = "email"; break;
|
||||
case osm::Props::Website: k = "website"; break;
|
||||
case osm::Props::Internet: k = "internet_access"; break;
|
||||
case osm::Props::Cuisine: k = "cuisine"; break;
|
||||
case osm::Props::OpeningHours: k = "opening_hours"; break;
|
||||
case osm::Props::Stars: k = "stars"; break;
|
||||
case osm::Props::Operator: k = "operator"; break;
|
||||
case osm::Props::Elevation: k = "ele"; break;
|
||||
case osm::Props::Wikipedia: k = "wikipedia"; break;
|
||||
case osm::Props::Flats: k = "addr:flats"; break;
|
||||
case osm::Props::BuildingLevels: k = "building:levels"; break;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
void MapObject::SetFromFeatureType(FeatureType const & ft)
|
||||
{
|
||||
m_mercator = feature::GetCenter(ft);
|
||||
m_name = ft.GetNames();
|
||||
m_types = feature::TypesHolder(ft);
|
||||
m_metadata = ft.GetMetadata();
|
||||
m_featureID = ft.GetID();
|
||||
ASSERT(m_featureID.IsValid(), ());
|
||||
}
|
||||
|
||||
FeatureID const & MapObject::GetID() const { return m_featureID; }
|
||||
ms::LatLon MapObject::GetLatLon() const { return MercatorBounds::ToLatLon(m_mercator); }
|
||||
m2::PointD const & MapObject::GetMercator() const { return m_mercator; }
|
||||
feature::TypesHolder const & MapObject::GetTypes() const { return m_types; }
|
||||
string MapObject::GetDefaultName() const
|
||||
{
|
||||
string name;
|
||||
UNUSED_VALUE(m_name.GetString(StringUtf8Multilang::kDefaultCode, name));
|
||||
return name;
|
||||
}
|
||||
|
||||
string MapObject::GetLocalizedType() const
|
||||
{
|
||||
ASSERT(!m_types.Empty(), ());
|
||||
feature::TypesHolder copy(m_types);
|
||||
copy.SortBySpec();
|
||||
CategoriesHolder const & categories = GetDefaultCategories();
|
||||
return categories.GetReadableFeatureType(
|
||||
*copy.begin(), categories.MapLocaleToInteger(languages::GetCurrentOrig()));
|
||||
}
|
||||
|
||||
vector<osm::Props> MapObject::AvailableProperties() const
|
||||
{
|
||||
return MetadataToProps(m_metadata.GetPresentTypes());
|
||||
}
|
||||
|
||||
string MapObject::GetPhone() const { return m_metadata.Get(feature::Metadata::FMD_PHONE_NUMBER); }
|
||||
string MapObject::GetFax() const { return m_metadata.Get(feature::Metadata::FMD_FAX_NUMBER); }
|
||||
string MapObject::GetEmail() const { return m_metadata.Get(feature::Metadata::FMD_EMAIL); }
|
||||
string MapObject::GetWebsite() const
|
||||
{
|
||||
string website = m_metadata.Get(feature::Metadata::FMD_WEBSITE);
|
||||
if (website.empty())
|
||||
website = m_metadata.Get(feature::Metadata::FMD_URL);
|
||||
return website;
|
||||
}
|
||||
|
||||
Internet MapObject::GetInternet() const
|
||||
{
|
||||
string inet = m_metadata.Get(feature::Metadata::FMD_INTERNET);
|
||||
strings::AsciiToLower(inet);
|
||||
// Most popular case.
|
||||
if (inet.empty())
|
||||
return Internet::Unknown;
|
||||
if (inet.find(kWlan) != string::npos)
|
||||
return Internet::Wlan;
|
||||
if (inet.find(kWired) != string::npos)
|
||||
return Internet::Wired;
|
||||
if (inet == kYes)
|
||||
return Internet::Yes;
|
||||
if (inet == kNo)
|
||||
return Internet::No;
|
||||
return Internet::Unknown;
|
||||
}
|
||||
|
||||
vector<string> MapObject::GetCuisines() const
|
||||
{
|
||||
vector<string> localized;
|
||||
Cuisines::Instance().ParseAndLocalize(m_metadata.Get(feature::Metadata::FMD_CUISINE), localized);
|
||||
return localized;
|
||||
}
|
||||
|
||||
string MapObject::FormatCuisines() const { return strings::JoinStrings(GetCuisines(), " • "); }
|
||||
string MapObject::GetOpeningHours() const
|
||||
{
|
||||
return m_metadata.Get(feature::Metadata::FMD_OPEN_HOURS);
|
||||
}
|
||||
|
||||
string MapObject::GetOperator() const { return m_metadata.Get(feature::Metadata::FMD_OPERATOR); }
|
||||
int MapObject::GetStars() const
|
||||
{
|
||||
// Most popular case.
|
||||
if (m_metadata.Has(feature::Metadata::FMD_STARS))
|
||||
{
|
||||
int count;
|
||||
if (strings::to_int(m_metadata.Get(feature::Metadata::FMD_STARS), count))
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string MapObject::GetElevation() const
|
||||
{
|
||||
if (m_metadata.Has(feature::Metadata::FMD_ELE))
|
||||
{
|
||||
double value;
|
||||
if (strings::to_double(m_metadata.Get(feature::Metadata::FMD_ELE), value))
|
||||
return MeasurementUtils::FormatAltitude(value);
|
||||
else
|
||||
LOG(LWARNING,
|
||||
("Invalid metadata for elevation:", m_metadata.Get(feature::Metadata::FMD_ELE)));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
string MapObject::GetWikipediaLink() const { return m_metadata.GetWikiURL(); }
|
||||
string MapObject::GetFlats() const { return m_metadata.Get(feature::Metadata::FMD_FLATS); }
|
||||
string MapObject::GetBuildingLevels() const
|
||||
{
|
||||
return m_metadata.Get(feature::Metadata::FMD_BUILDING_LEVELS);
|
||||
}
|
||||
|
||||
feature::Metadata const & MapObject::GetMetadata() const { return m_metadata; }
|
||||
} // namespace osm
|
147
indexer/map_object.hpp
Normal file
147
indexer/map_object.hpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
#pragma once
|
||||
|
||||
#include "indexer/feature_data.hpp"
|
||||
#include "indexer/feature_decl.hpp"
|
||||
#include "indexer/feature_meta.hpp"
|
||||
|
||||
#include "geometry/latlon.hpp"
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "coding/multilang_utf8_string.hpp"
|
||||
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include "std/string.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
class FeatureType;
|
||||
|
||||
namespace osm
|
||||
{
|
||||
class EditableMapObject;
|
||||
/// OSM internet_access tag values.
|
||||
enum class Internet
|
||||
{
|
||||
Unknown, //!< Internet state is unknown (default).
|
||||
Wlan, //!< Wireless Internet access is present.
|
||||
Wired, //!< Wired Internet access is present.
|
||||
Yes, //!< Unspecified Internet access is available.
|
||||
No //!< There is definitely no any Internet access.
|
||||
};
|
||||
string DebugPrint(Internet internet);
|
||||
|
||||
/// Metadata fields in the sorted order, visible to users.
|
||||
enum class Props
|
||||
{
|
||||
OpeningHours,
|
||||
Phone,
|
||||
Fax,
|
||||
Website,
|
||||
Email,
|
||||
Cuisine,
|
||||
Stars,
|
||||
Operator,
|
||||
Elevation,
|
||||
Internet,
|
||||
Wikipedia,
|
||||
Flats,
|
||||
BuildingLevels
|
||||
};
|
||||
string DebugPrint(Props props);
|
||||
|
||||
class MapObject
|
||||
{
|
||||
public:
|
||||
void SetFromFeatureType(FeatureType const & ft);
|
||||
|
||||
FeatureID const & GetID() const;
|
||||
|
||||
ms::LatLon GetLatLon() const;
|
||||
m2::PointD const & GetMercator() const;
|
||||
|
||||
/// @returns "the best" type to display in UI.
|
||||
string GetLocalizedType() const;
|
||||
feature::TypesHolder const & GetTypes() const;
|
||||
string GetDefaultName() const;
|
||||
|
||||
/// @name Metadata fields.
|
||||
//@{
|
||||
vector<Props> AvailableProperties() const;
|
||||
string GetPhone() const;
|
||||
string GetFax() const;
|
||||
string GetEmail() const;
|
||||
string GetWebsite() const;
|
||||
Internet GetInternet() const;
|
||||
/// @returns translated cuisine(s).
|
||||
vector<string> GetCuisines() const;
|
||||
/// @returns translated and formatted cuisines.
|
||||
string FormatCuisines() const;
|
||||
string GetOpeningHours() const;
|
||||
string GetOperator() const;
|
||||
int GetStars() const;
|
||||
/// @returns formatted elevation in feet or meters, or empty string.
|
||||
string GetElevation() const;
|
||||
/// @returns URL to Wikipedia or empty string.
|
||||
string GetWikipediaLink() const;
|
||||
string GetFlats() const;
|
||||
string GetBuildingLevels() const;
|
||||
//@}
|
||||
|
||||
// TODO(Vlad, yunikkk): Use Props enum + getters instead of direct metadata access.
|
||||
// TODO: Remove this method.
|
||||
feature::Metadata const & GetMetadata() const;
|
||||
|
||||
protected:
|
||||
FeatureID m_featureID;
|
||||
m2::PointD m_mercator;
|
||||
StringUtf8Multilang m_name;
|
||||
feature::TypesHolder m_types;
|
||||
feature::Metadata m_metadata;
|
||||
};
|
||||
|
||||
/// Helper to convert internal feature::Metadata::FMD_* enum into a users-visible one.
|
||||
template <class T>
|
||||
vector<Props> MetadataToProps(vector<T> const & metadata)
|
||||
{
|
||||
vector<Props> res;
|
||||
using feature::Metadata;
|
||||
for (auto const type : metadata)
|
||||
{
|
||||
switch (static_cast<Metadata::EType>(type))
|
||||
{
|
||||
case Metadata::FMD_CUISINE: res.push_back(Props::Cuisine); break;
|
||||
case Metadata::FMD_OPEN_HOURS: res.push_back(Props::OpeningHours); break;
|
||||
case Metadata::FMD_PHONE_NUMBER: res.push_back(Props::Phone); break;
|
||||
case Metadata::FMD_FAX_NUMBER: res.push_back(Props::Fax); break;
|
||||
case Metadata::FMD_STARS: res.push_back(Props::Stars); break;
|
||||
case Metadata::FMD_OPERATOR:
|
||||
res.push_back(Props::Operator);
|
||||
break;
|
||||
// Url is not used in UI and should be matched to Website.
|
||||
case Metadata::FMD_URL:
|
||||
case Metadata::FMD_WEBSITE: res.push_back(Props::Website); break;
|
||||
case Metadata::FMD_INTERNET: res.push_back(Props::Internet); break;
|
||||
case Metadata::FMD_ELE: res.push_back(Props::Elevation); break;
|
||||
case Metadata::FMD_EMAIL: res.push_back(Props::Email); break;
|
||||
case Metadata::FMD_WIKIPEDIA: res.push_back(Props::Wikipedia); break;
|
||||
case Metadata::FMD_FLATS: res.push_back(Props::Flats); break;
|
||||
case Metadata::FMD_BUILDING_LEVELS: res.push_back(Props::BuildingLevels); break;
|
||||
case Metadata::FMD_TURN_LANES:
|
||||
case Metadata::FMD_TURN_LANES_FORWARD:
|
||||
case Metadata::FMD_TURN_LANES_BACKWARD:
|
||||
// Postcode should be processed separately, in the address.
|
||||
case Metadata::FMD_POSTCODE:
|
||||
case Metadata::FMD_MAXSPEED:
|
||||
case Metadata::FMD_HEIGHT:
|
||||
case Metadata::FMD_MIN_HEIGHT:
|
||||
case Metadata::FMD_DENOMINATION:
|
||||
case Metadata::FMD_TEST_ID:
|
||||
case Metadata::FMD_COUNT:
|
||||
break;
|
||||
// Please add new cases when compiler issues an "unhandled switch case" warning here.
|
||||
}
|
||||
}
|
||||
my::SortUnique(res);
|
||||
return res;
|
||||
}
|
||||
} // namespace osm
|
Loading…
Add table
Reference in a new issue