forked from organicmaps/organicmaps
Merge pull request #22 from syershov/new-add-city-tag
[generator] Add preprocessing of subway station image type-tag by coordinate matching
This commit is contained in:
commit
c0a444935d
1 changed files with 139 additions and 56 deletions
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/feature_visibility.hpp"
|
||||
#include "indexer/mercator.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
@ -332,71 +333,94 @@ namespace ftype
|
|||
} while (true);
|
||||
}
|
||||
|
||||
void GetNameAndType(OsmElement * p, FeatureParams & params)
|
||||
string MatchCity(OsmElement const * p)
|
||||
{
|
||||
static map<string, m2::RectD> const cities = {
|
||||
{"amsterdam", {4.65682983398, 52.232846171, 5.10040283203, 52.4886341706}},
|
||||
{"baires", {-58.9910888672, -35.1221551064, -57.8045654297, -34.2685661867}},
|
||||
{"barcelona", {1.94458007812, 41.2489025224, 2.29614257812, 41.5414776668}},
|
||||
{"beijing", {115.894775391, 39.588757277, 117.026367187, 40.2795256688}},
|
||||
{"berlin", {13.0352783203, 52.3051199211, 13.7933349609, 52.6963610783}},
|
||||
{"brussel", {4.2448425293, 50.761653413, 4.52499389648, 50.9497757762}},
|
||||
{"budapest", {18.7509155273, 47.3034470439, 19.423828125, 47.7023684666}},
|
||||
{"chicago", {-88.3163452148, 41.3541338721, -87.1270751953, 42.2691794924}},
|
||||
{"delhi", {76.8026733398, 28.3914003758, 77.5511169434, 28.9240352884}},
|
||||
{"dnepro", {34.7937011719, 48.339820521, 35.2798461914, 48.6056737841}},
|
||||
{"ekb", {60.3588867188, 56.6622647682, 61.0180664062, 57.0287738515}},
|
||||
{"frankfurt", {8.36334228516, 49.937079757, 8.92364501953, 50.2296379179}},
|
||||
{"hamburg", {9.75860595703, 53.39151869, 10.2584838867, 53.6820686709}},
|
||||
{"helsinki", {24.3237304688, 59.9989861206, 25.48828125, 60.44638186}},
|
||||
{"kazan", {48.8067626953, 55.6372985742, 49.39453125, 55.9153515154}},
|
||||
{"kiev", {30.1354980469, 50.2050332649, 31.025390625, 50.6599083609}},
|
||||
{"lisboa", {-9.42626953125, 38.548165423, -8.876953125, 38.9166815364}},
|
||||
{"london", {-0.4833984375, 51.3031452592, 0.2197265625, 51.6929902115}},
|
||||
{"madrid", {-4.00451660156, 40.1536868578, -3.32885742188, 40.6222917831}},
|
||||
{"mexico", {-99.3630981445, 19.2541083164, -98.879699707, 19.5960192403}},
|
||||
{"milan", {9.02252197266, 45.341528405, 9.35760498047, 45.5813674681}},
|
||||
{"minsk", {27.2845458984, 53.777934972, 27.8393554688, 54.0271334441}},
|
||||
{"moscow", {36.9964599609, 55.3962717136, 38.1884765625, 56.1118730004}},
|
||||
{"munchen", {11.3433837891, 47.9981928195, 11.7965698242, 48.2530267576}},
|
||||
{"newyork", {-74.4104003906, 40.4134960497, -73.4600830078, 41.1869224229}},
|
||||
{"nnov", {43.6431884766, 56.1608472541, 44.208984375, 56.4245355509}},
|
||||
{"novosibirsk", {82.4578857422, 54.8513152597, 83.2983398438, 55.2540770671}},
|
||||
{"osaka", {134.813232422, 34.1981730963, 136.076660156, 35.119908571}},
|
||||
{"oslo", {10.3875732422, 59.7812868211, 10.9286499023, 60.0401604652}},
|
||||
{"paris", {2.09014892578, 48.6637569323, 2.70538330078, 49.0414689141}},
|
||||
{"roma", {12.3348999023, 41.7672146942, 12.6397705078, 42.0105298189}},
|
||||
{"sanfran", {-122.72277832, 37.1690715771, -121.651611328, 38.0307856938}},
|
||||
{"seoul", {126.540527344, 37.3352243593, 127.23815918, 37.6838203267}},
|
||||
{"shanghai", {119.849853516, 30.5291450367, 122.102050781, 32.1523618947}},
|
||||
{"spb", {29.70703125, 59.5231755354, 31.3110351562, 60.2725145948}},
|
||||
{"stockholm", {17.5726318359, 59.1336814082, 18.3966064453, 59.5565918857}},
|
||||
{"sydney", {150.42755127, -34.3615762875, 151.424560547, -33.4543597895}},
|
||||
{"tokyo", {139.240722656, 35.2186974963, 140.498657227, 36.2575628263}},
|
||||
{"warszawa", {20.7202148438, 52.0322181041, 21.3024902344, 52.4091212523}},
|
||||
{"washington", {-77.4920654297, 38.5954071994, -76.6735839844, 39.2216149801}},
|
||||
{"wien", {16.0894775391, 48.0633965378, 16.6387939453, 48.3525987075}},
|
||||
};
|
||||
|
||||
m2::PointD const pt(p->lon, p->lat);
|
||||
|
||||
for (auto const & city : cities)
|
||||
{
|
||||
if (city.second.IsPointInside(pt))
|
||||
return city.first;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
void PreprocessElement(OsmElement * p, FeatureParams & params)
|
||||
{
|
||||
// Stage1: Preprocess tags.
|
||||
bool hasLayer = false;
|
||||
char const * layer = nullptr;
|
||||
|
||||
bool isSubwayEntrance = false;
|
||||
bool isSubwayStation = false;
|
||||
|
||||
TagProcessor(p).ApplyRules
|
||||
({
|
||||
{ "bridge", "yes", [&layer] { layer = "1"; }},
|
||||
{ "tunnel", "yes", [&layer] { layer = "-1"; }},
|
||||
{ "layer", "*", [&hasLayer] { hasLayer = true; }},
|
||||
|
||||
{ "railway", "subway_entrance", [&isSubwayEntrance] { isSubwayEntrance = true; }},
|
||||
{ "station", "subway", [&isSubwayStation] { isSubwayStation = true; }},
|
||||
});
|
||||
|
||||
if (!hasLayer && layer)
|
||||
p->AddTag("layer", layer);
|
||||
|
||||
// Stage2: Process feature name on all languages.
|
||||
ForEachTag<bool>(p, NamesExtractor(params));
|
||||
// Tag 'city' is needed for correct selection of metro icons.
|
||||
if (isSubwayEntrance || isSubwayStation)
|
||||
{
|
||||
string const & city = MatchCity(p);
|
||||
if (!city.empty())
|
||||
p->AddTag("city", city);
|
||||
}
|
||||
}
|
||||
|
||||
// Stage3: Process base feature tags.
|
||||
TagProcessor(p).ApplyRules<void(string &, string &)>
|
||||
({
|
||||
{ "atm", "yes", [](string & k, string & v) { k.swap(v); k = "amenity"; }},
|
||||
{ "restaurant", "yes", [](string & k, string & v) { k.swap(v); k = "amenity"; }},
|
||||
{ "hotel", "yes", [](string & k, string & v) { k.swap(v); k = "tourism"; }},
|
||||
{ "addr:housename", "*", [¶ms](string & k, string & v) { params.AddHouseName(v); k.clear(); v.clear();}},
|
||||
{ "addr:street", "*", [¶ms](string & k, string & v) { params.AddStreetAddress(v); k.clear(); v.clear();}},
|
||||
{ "addr:flats", "*", [¶ms](string & k, string & v) { params.flats = v; k.clear(); v.clear();}},
|
||||
{ "addr:housenumber", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Treat "numbers" like names if it's not an actual number.
|
||||
if (!params.AddHouseNumber(v))
|
||||
params.AddHouseName(v);
|
||||
k.clear(); v.clear();
|
||||
}},
|
||||
{ "population", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get population rank.
|
||||
uint64_t n;
|
||||
if (strings::to_uint64(v, n))
|
||||
params.rank = static_cast<uint8_t>(log(double(n)) / log(1.1));
|
||||
k.clear(); v.clear();
|
||||
}},
|
||||
{ "ref", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get reference (we process road numbers only).
|
||||
params.ref = v;
|
||||
k.clear(); v.clear();
|
||||
}},
|
||||
{ "layer", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get layer.
|
||||
if (params.layer == 0)
|
||||
{
|
||||
params.layer = atoi(v.c_str());
|
||||
int8_t const bound = 10;
|
||||
params.layer = my::clamp(params.layer, -bound, bound);
|
||||
}
|
||||
}},
|
||||
});
|
||||
|
||||
// Stage4: Match tags to classificator for find feature types.
|
||||
MatchTypes(p, params);
|
||||
|
||||
// Stage5: Postrocess feature types.
|
||||
void PostprocessElement(OsmElement * p, FeatureParams & params)
|
||||
{
|
||||
static CachedTypes const types;
|
||||
|
||||
if (!params.house.IsEmpty())
|
||||
|
@ -422,8 +446,8 @@ namespace ftype
|
|||
{
|
||||
if (!highwayDone && types.IsHighway(vTypes[i]))
|
||||
{
|
||||
TagProcessor(p).ApplyRules(
|
||||
{
|
||||
TagProcessor(p).ApplyRules
|
||||
({
|
||||
{ "oneway", "yes", [¶ms] { params.AddType(types.Get(CachedTypes::ONEWAY)); }},
|
||||
{ "oneway", "1", [¶ms] { params.AddType(types.Get(CachedTypes::ONEWAY)); }},
|
||||
{ "oneway", "-1", [¶ms] { params.AddType(types.Get(CachedTypes::ONEWAY)); params.m_reverseGeometry = true; }},
|
||||
|
@ -443,8 +467,8 @@ namespace ftype
|
|||
|
||||
if (!subwayDone && types.IsRwSubway(vTypes[i]))
|
||||
{
|
||||
TagProcessor(p).ApplyRules(
|
||||
{
|
||||
TagProcessor(p).ApplyRules
|
||||
({
|
||||
{ "network", "London Underground", [¶ms] { params.SetRwSubwayType("london"); }},
|
||||
{ "network", "New York City Subway", [¶ms] { params.SetRwSubwayType("newyork"); }},
|
||||
{ "network", "Московский метрополитен", [¶ms] { params.SetRwSubwayType("moscow"); }},
|
||||
|
@ -470,14 +494,73 @@ namespace ftype
|
|||
|
||||
if (!subwayDone && !railwayDone && types.IsRwStation(vTypes[i]))
|
||||
{
|
||||
TagProcessor(p).ApplyRules(
|
||||
{
|
||||
TagProcessor(p).ApplyRules
|
||||
({
|
||||
{ "network", "London Underground", [¶ms] { params.SetRwSubwayType("london"); }},
|
||||
});
|
||||
|
||||
railwayDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetNameAndType(OsmElement * p, FeatureParams & params)
|
||||
{
|
||||
// Stage1: Preprocess tags.
|
||||
PreprocessElement(p, params);
|
||||
|
||||
// Stage2: Process feature name on all languages.
|
||||
ForEachTag<bool>(p, NamesExtractor(params));
|
||||
|
||||
// Stage3: Process base feature tags.
|
||||
TagProcessor(p).ApplyRules<void(string &, string &)>
|
||||
({
|
||||
{ "atm", "yes", [](string & k, string & v) { k.swap(v); k = "amenity"; }},
|
||||
{ "restaurant", "yes", [](string & k, string & v) { k.swap(v); k = "amenity"; }},
|
||||
{ "hotel", "yes", [](string & k, string & v) { k.swap(v); k = "tourism"; }},
|
||||
{ "addr:housename", "*", [¶ms](string & k, string & v) { params.AddHouseName(v); k.clear(); v.clear();}},
|
||||
{ "addr:street", "*", [¶ms](string & k, string & v) { params.AddStreetAddress(v); k.clear(); v.clear();}},
|
||||
{ "addr:flats", "*", [¶ms](string & k, string & v) { params.flats = v; k.clear(); v.clear();}},
|
||||
{ "addr:housenumber", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Treat "numbers" like names if it's not an actual number.
|
||||
if (!params.AddHouseNumber(v))
|
||||
params.AddHouseName(v);
|
||||
k.clear(); v.clear();
|
||||
}},
|
||||
{ "population", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get population rank.
|
||||
// TODO: similar formula with indexer/feature.cpp, possible need refactoring
|
||||
uint64_t n;
|
||||
if (strings::to_uint64(v, n))
|
||||
params.rank = static_cast<uint8_t>(log(double(n)) / log(1.1));
|
||||
k.clear();
|
||||
v.clear();
|
||||
}},
|
||||
{ "ref", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get reference (we process road numbers only).
|
||||
params.ref = v;
|
||||
k.clear(); v.clear();
|
||||
}},
|
||||
{ "layer", "*", [¶ms](string & k, string & v)
|
||||
{
|
||||
// Get layer.
|
||||
if (params.layer == 0)
|
||||
{
|
||||
params.layer = atoi(v.c_str());
|
||||
int8_t const bound = 10;
|
||||
params.layer = my::clamp(params.layer, -bound, bound);
|
||||
}
|
||||
}},
|
||||
});
|
||||
|
||||
// Stage4: Match tags to classificator for find feature types.
|
||||
MatchTypes(p, params);
|
||||
|
||||
// Stage5: Postprocess feature types.
|
||||
PostprocessElement(p, params);
|
||||
|
||||
params.FinishAddingTypes();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue