diff --git a/data/copyright.html b/data/copyright.html
index 0324a1932..86351c37a 100644
--- a/data/copyright.html
+++ b/data/copyright.html
@@ -275,6 +275,8 @@
Code2000 Font
© 1998–2003 James Kass; Shareware
+ Panoramax
+ © 2023 Adrien Pavie; CC BY 4.0 License
We also use these icons on the map:
diff --git a/feature_list/feature_list.cpp b/feature_list/feature_list.cpp
index 85a98f71a..50a7da03c 100644
--- a/feature_list/feature_list.cpp
+++ b/feature_list/feature_list.cpp
@@ -270,6 +270,7 @@ public:
string const opening_hours(meta.Get(feature::Metadata::FMD_OPEN_HOURS));
string const wikipedia(meta.Get(feature::Metadata::FMD_WIKIPEDIA));
string const wikimedia_commons(meta.Get(feature::Metadata::FMD_WIKIMEDIA_COMMONS));
+ string const panoramax(meta.Get(feature::Metadata::FMD_PANORAMAX));
string const floor(meta.Get(feature::Metadata::FMD_LEVEL));
string const fee = category.ends_with("-fee") ? "yes" : "";
string const atm = HasAtm(f) ? "yes" : "";
@@ -278,7 +279,7 @@ public:
osmId, uid, lat, lon, mwmName, category, name, std::string(city),
addrStreet, addrHouse, phone, website, stars, std::string(metaOperator), internet,
denomination, wheelchair, opening_hours, wikipedia, floor, fee, atm, contact_facebook,
- contact_instagram, contact_twitter, contact_vk, contact_line, contact_fediverse, contact_bluesky, wikimedia_commons};
+ contact_instagram, contact_twitter, contact_vk, contact_line, contact_fediverse, contact_bluesky, wikimedia_commons, panoramax};
AppendNames(f, columns);
PrintAsCSV(columns, ';', cout);
@@ -292,7 +293,7 @@ void PrintHeader()
"phone", "website", "cuisines", "stars", "operator",
"internet", "denomination", "wheelchair", "opening_hours", "wikipedia",
"floor", "fee", "atm", "contact_facebook", "contact_instagram",
- "contact_twitter", "contact_vk", "contact_line", "contact_fediverse", "contact_bluesky", "wikimedia_commons"};
+ "contact_twitter", "contact_vk", "contact_line", "contact_fediverse", "contact_bluesky", "wikimedia_commons", "panoramax"};
// Append all supported name languages in order.
for (uint8_t idx = 1; idx < kLangCount; idx++)
columns.push_back("name_" + string(StringUtf8Multilang::GetLangByCode(idx)));
diff --git a/generator/osm2meta.cpp b/generator/osm2meta.cpp
index e92a93a85..1f4f689e0 100644
--- a/generator/osm2meta.cpp
+++ b/generator/osm2meta.cpp
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
@@ -309,6 +310,22 @@ std::string MetadataTagProcessorImpl::ValidateAndFormat_wikimedia_commons(std::s
return {};
}
+std::string MetadataTagProcessorImpl::ValidateAndFormat_panoramax(std::string v)
+{
+ static auto const s_panoramaxRegex = std::regex(R"(^([a-z0-9]{8}(-[a-z0-9]{4}){3}-[a-z0-9]{12})$)");
+
+ if (std::regex_match(v, s_panoramaxRegex))
+ return v;
+ url::Url const parsedUrl = url::Url::FromString(v);
+ if (const std::string* paramValue = parsedUrl.GetParamValue("pic"))
+ {
+ if (std::regex_match(*paramValue, s_panoramaxRegex))
+ return v;
+ }
+ LOG(LDEBUG, ("Invalid Panoramax tag value:", v));
+ return {};
+}
+
std::string MetadataTagProcessorImpl::ValidateAndFormat_airport_iata(std::string const & v) const
{
if (!ftypes::IsAirportChecker::Instance()(m_params.m_types))
@@ -548,6 +565,7 @@ void MetadataTagProcessor::operator()(std::string const & k, std::string const &
case Metadata::FMD_POSTCODE: valid = ValidateAndFormat_postcode(v); break;
case Metadata::FMD_WIKIPEDIA: valid = ValidateAndFormat_wikipedia(v); break;
case Metadata::FMD_WIKIMEDIA_COMMONS: valid = ValidateAndFormat_wikimedia_commons(v); break;
+ case Metadata::FMD_PANORAMAX: valid = ValidateAndFormat_panoramax(v); break;
case Metadata::FMD_FLATS: valid = ValidateAndFormat_flats(v); break;
case Metadata::FMD_MIN_HEIGHT: // The same validator as for height.
case Metadata::FMD_HEIGHT: valid = ValidateAndFormat_height(v); break;
diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp
index 3a6e43eb1..2e3834912 100644
--- a/generator/osm2meta.hpp
+++ b/generator/osm2meta.hpp
@@ -33,6 +33,7 @@ struct MetadataTagProcessorImpl
static std::string ValidateAndFormat_denomination(std::string const & v) ;
static std::string ValidateAndFormat_wikipedia(std::string v) ;
static std::string ValidateAndFormat_wikimedia_commons(std::string v) ;
+ static std::string ValidateAndFormat_panoramax(std::string v) ;
std::string ValidateAndFormat_airport_iata(std::string const & v) const;
static std::string ValidateAndFormat_brand(std::string const & v);
std::string ValidateAndFormat_duration(std::string const & v) const;
diff --git a/indexer/feature_meta.cpp b/indexer/feature_meta.cpp
index c8057befe..7108856ed 100644
--- a/indexer/feature_meta.cpp
+++ b/indexer/feature_meta.cpp
@@ -124,6 +124,8 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType)
outType = Metadata::FMD_WIKIPEDIA;
else if (k == "wikimedia_commons")
outType = Metadata::FMD_WIKIMEDIA_COMMONS;
+ else if (k == "panoramax")
+ outType = Metadata::FMD_PANORAMAX;
else if (k == "addr:flats")
outType = Metadata::FMD_FLATS;
else if (k == "height")
@@ -275,6 +277,7 @@ string ToString(Metadata::EType type)
case Metadata::FMD_JUNCTION_REF: return "junction:ref";
case Metadata::FMD_BUILDING_MIN_LEVEL: return "building:min_level";
case Metadata::FMD_WIKIMEDIA_COMMONS: return "wikimedia_commons";
+ case Metadata::FMD_PANORAMAX: return "panoramax";
case Metadata::FMD_CAPACITY: return "capacity";
case Metadata::FMD_WHEELCHAIR: return "wheelchair";
case Metadata::FMD_LOCAL_REF: return "local_ref";
diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp
index b085421b1..a5bd21fe9 100644
--- a/indexer/feature_meta.hpp
+++ b/indexer/feature_meta.hpp
@@ -157,6 +157,7 @@ public:
FMD_NETWORK = 49,
FMD_CONTACT_FEDIVERSE = 50,
FMD_CONTACT_BLUESKY = 51,
+ FMD_PANORAMAX = 52,
FMD_COUNT
};