mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-20 05:13:58 +00:00
Organic Maps sources as of 02.04.2025 (fad26bbf22ac3da75e01e62aa01e5c8e11861005)
To expand with full Organic Maps and Maps.ME commits history run: git remote add om-historic [om-historic.git repo url] git fetch --tags om-historic git replace squashed-history historic-commits
This commit is contained in:
225
indexer/map_object.cpp
Normal file
225
indexer/map_object.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
#include "map_object.hpp"
|
||||
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_algo.hpp"
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
#include "indexer/road_shields_parser.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "platform/localization.hpp"
|
||||
#include "platform/measurement_utils.hpp"
|
||||
#include "platform/distance.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
namespace osm
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
void MapObject::SetFromFeatureType(FeatureType & ft)
|
||||
{
|
||||
m_mercator = feature::GetCenter(ft);
|
||||
m_name = ft.GetNames();
|
||||
|
||||
Classificator const & cl = classif();
|
||||
m_types = feature::TypesHolder(ft);
|
||||
m_types.RemoveIf([&cl](uint32_t t)
|
||||
{
|
||||
return !cl.IsTypeValid(t);
|
||||
});
|
||||
// Actually, we can't select object on map with invalid (non-drawable or deprecated) type.
|
||||
// TODO: in android prod a user will see an "empty" PP if a spot is selected in old mwm
|
||||
// where a deprecated feature was; and could crash if play with routing to it, bookmarking it..
|
||||
// A desktop/qt prod segfaults when trying to select such spots.
|
||||
ASSERT(!m_types.Empty(), ());
|
||||
|
||||
m_metadata = ft.GetMetadata();
|
||||
m_houseNumber = ft.GetHouseNumber();
|
||||
m_roadShields = ftypes::GetRoadShieldsNames(ft);
|
||||
m_featureID = ft.GetID();
|
||||
m_geomType = ft.GetGeomType();
|
||||
m_layer = ft.GetLayer();
|
||||
|
||||
// TODO: BEST_GEOMETRY is likely needed for some special cases only,
|
||||
// i.e. matching an edited OSM feature, in other cases like opening
|
||||
// a place page WORST_GEOMETRY is going to be enough?
|
||||
if (m_geomType == feature::GeomType::Area)
|
||||
assign_range(m_triangles, ft.GetTrianglesAsPoints(FeatureType::BEST_GEOMETRY));
|
||||
else if (m_geomType == feature::GeomType::Line)
|
||||
assign_range(m_points, ft.GetPoints(FeatureType::BEST_GEOMETRY));
|
||||
|
||||
// Fill runtime metadata
|
||||
m_metadata.Set(feature::Metadata::EType::FMD_WHEELCHAIR, feature::GetReadableWheelchairType(m_types));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (ftypes::IsWifiChecker::Instance()(ft))
|
||||
ASSERT(m_metadata.Has(MetadataID::FMD_INTERNET), ());
|
||||
#endif
|
||||
}
|
||||
|
||||
FeatureID const & MapObject::GetID() const { return m_featureID; }
|
||||
ms::LatLon MapObject::GetLatLon() const { return mercator::ToLatLon(m_mercator); }
|
||||
m2::PointD const & MapObject::GetMercator() const { return m_mercator; }
|
||||
vector<m2::PointD> const & MapObject::GetTriangesAsPoints() const { return m_triangles; }
|
||||
vector<m2::PointD> const & MapObject::GetPoints() const { return m_points; }
|
||||
feature::TypesHolder const & MapObject::GetTypes() const { return m_types; }
|
||||
|
||||
string_view MapObject::GetDefaultName() const
|
||||
{
|
||||
string_view name;
|
||||
UNUSED_VALUE(m_name.GetString(StringUtf8Multilang::kDefaultCode, name));
|
||||
return name;
|
||||
}
|
||||
|
||||
StringUtf8Multilang const & MapObject::GetNameMultilang() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
string const & MapObject::GetHouseNumber() const { return m_houseNumber; }
|
||||
|
||||
std::string_view MapObject::GetPostcode() const
|
||||
{
|
||||
return m_metadata.Get(MetadataID::FMD_POSTCODE);
|
||||
}
|
||||
|
||||
std::string MapObject::GetLocalizedType() const
|
||||
{
|
||||
ASSERT(!m_types.Empty(), ());
|
||||
feature::TypesHolder copy(m_types);
|
||||
copy.SortBySpec();
|
||||
|
||||
return platform::GetLocalizedTypeName(classif().GetReadableObjectName(copy.GetBestType()));
|
||||
}
|
||||
|
||||
std::string MapObject::GetLocalizedAllTypes(bool withMainType) const
|
||||
{
|
||||
ASSERT(!m_types.Empty(), ());
|
||||
feature::TypesHolder copy(m_types);
|
||||
copy.SortBySpec();
|
||||
|
||||
auto const & isPoi = ftypes::IsPoiChecker::Instance();
|
||||
auto const & amenityChecker = ftypes::IsAmenityChecker::Instance();
|
||||
|
||||
std::ostringstream oss;
|
||||
bool isMainType = true;
|
||||
bool isFirst = true;
|
||||
for (auto const type : copy)
|
||||
{
|
||||
if (isMainType && !withMainType)
|
||||
{
|
||||
isMainType = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore types that are not POI
|
||||
if (!isMainType && !isPoi(type))
|
||||
continue;
|
||||
|
||||
// Ignore general amenity
|
||||
if (!isMainType && amenityChecker.GetType() == type)
|
||||
continue;
|
||||
|
||||
isMainType = false;
|
||||
|
||||
// Add fields separator between types
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
oss << feature::kFieldsSeparator;
|
||||
|
||||
oss << platform::GetLocalizedTypeName(classif().GetReadableObjectName(type));
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string MapObject::GetAllReadableTypes() const
|
||||
{
|
||||
ASSERT(!m_types.Empty(), ());
|
||||
feature::TypesHolder copy(m_types);
|
||||
copy.SortBySpec();
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
for (auto const type : copy)
|
||||
oss << classif().GetReadableObjectName(type) << feature::kFieldsSeparator;
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string_view MapObject::GetMetadata(MetadataID type) const
|
||||
{
|
||||
return m_metadata.Get(type);
|
||||
}
|
||||
|
||||
std::string_view MapObject::GetOpeningHours() const
|
||||
{
|
||||
return m_metadata.Get(MetadataID::FMD_OPEN_HOURS);
|
||||
}
|
||||
|
||||
feature::Internet MapObject::GetInternet() const
|
||||
{
|
||||
return feature::InternetFromString(m_metadata.Get(MetadataID::FMD_INTERNET));
|
||||
}
|
||||
|
||||
vector<string> MapObject::GetCuisines() const { return feature::GetCuisines(m_types); }
|
||||
|
||||
vector<string> MapObject::GetLocalizedCuisines() const
|
||||
{
|
||||
return feature::GetLocalizedCuisines(m_types);
|
||||
}
|
||||
|
||||
vector<string> MapObject::GetRecyclingTypes() const { return feature::GetRecyclingTypes(m_types); }
|
||||
|
||||
vector<string> MapObject::GetLocalizedRecyclingTypes() const
|
||||
{
|
||||
return feature::GetLocalizedRecyclingTypes(m_types);
|
||||
}
|
||||
|
||||
string MapObject::GetLocalizedFeeType() const
|
||||
{
|
||||
return feature::GetLocalizedFeeType(m_types);
|
||||
}
|
||||
|
||||
bool MapObject::HasAtm() const
|
||||
{
|
||||
return feature::HasAtm(m_types);
|
||||
}
|
||||
|
||||
bool MapObject::HasToilets() const
|
||||
{
|
||||
return feature::HasToilets(m_types);
|
||||
}
|
||||
|
||||
string MapObject::FormatCuisines() const
|
||||
{
|
||||
return strings::JoinStrings(GetLocalizedCuisines(), feature::kFieldsSeparator);
|
||||
}
|
||||
|
||||
string MapObject::FormatRoadShields() const
|
||||
{
|
||||
return strings::JoinStrings(m_roadShields, feature::kFieldsSeparator);
|
||||
}
|
||||
|
||||
int MapObject::GetStars() const
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
auto const sv = m_metadata.Get(MetadataID::FMD_STARS);
|
||||
if (!sv.empty())
|
||||
{
|
||||
if (!strings::to_uint(sv, count))
|
||||
count = 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool MapObject::IsPointType() const { return m_geomType == feature::GeomType::Point; }
|
||||
bool MapObject::IsBuilding() const { return ftypes::IsBuildingChecker::Instance()(m_types); }
|
||||
bool MapObject::IsPublicTransportStop() const { return ftypes::IsPublicTransportStopChecker::Instance()(m_types); }
|
||||
|
||||
} // namespace osm
|
||||
Reference in New Issue
Block a user