Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvng <viktor.govako@gmail.com>2015-08-19 16:58:20 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 03:03:08 +0300
commitcc4562035c7da5f61c3f82d9a3414deb225f3d6b (patch)
treea2049a48977b202a7aaa4ed5e6da3089f961d480 /generator
parentf80125b9d0829b83636806621475aa0c147e1d72 (diff)
[generator] Process railway-station-subway for some special cities.
Diffstat (limited to 'generator')
-rw-r--r--generator/generator_tests/osm_type_test.cpp83
-rw-r--r--generator/osm2type.cpp52
-rw-r--r--generator/osm_element.hpp129
-rw-r--r--generator/osm_source.cpp3
-rw-r--r--generator/osm_source.hpp2
5 files changed, 213 insertions, 56 deletions
diff --git a/generator/generator_tests/osm_type_test.cpp b/generator/generator_tests/osm_type_test.cpp
index 813fe22f33..2a4d520bb7 100644
--- a/generator/generator_tests/osm_type_test.cpp
+++ b/generator/generator_tests/osm_type_test.cpp
@@ -643,3 +643,86 @@ UNIT_TEST(OsmType_Dibrugarh)
TEST(params.name.GetString(StringUtf8Multilang::DEFAULT_CODE, name), (params));
TEST_EQUAL(name, "Dibrugarh", (params));
}
+
+UNIT_TEST(OsmType_Subway)
+{
+ {
+ char const * arr[][2] = {
+ { "network", "Московский метрополитен" },
+ { "operator", "ГУП «Московский метрополитен»" },
+ { "railway", "station" },
+ { "station", "subway" },
+ { "transport", "subway" },
+ };
+
+ XMLElement e;
+ FillXmlElement(arr, ARRAY_SIZE(arr), &e);
+
+ FeatureParams params;
+ ftype::GetNameAndType(&e, params);
+
+ TEST_EQUAL(params.m_Types.size(), 1, (params));
+ TEST(params.IsTypeExist(GetType({"railway", "station", "subway", "moscow"})), (params));
+ }
+
+ {
+ char const * arr[][2] = {
+ { "name", "14th Street-8th Avenue (A,C,E,L)" },
+ { "network", "New York City Subway" },
+ { "railway", "station" },
+ { "wheelchair", "yes" },
+ { "route", "subway" },
+ };
+
+ XMLElement e;
+ FillXmlElement(arr, ARRAY_SIZE(arr), &e);
+
+ FeatureParams params;
+ ftype::GetNameAndType(&e, params);
+
+ TEST_EQUAL(params.m_Types.size(), 1, (params));
+ TEST(params.IsTypeExist(GetType({"railway", "station", "subway", "newyork"})), (params));
+ }
+
+ {
+ char const * arr[][2] = {
+ { "name", "S Landsberger Allee" },
+ { "phone", "030 29743333" },
+ { "public_transport", "stop_position" },
+ { "railway", "station" },
+ { "network", "New York City Subway" },
+ { "station", "light_rail" },
+ };
+
+ XMLElement e;
+ FillXmlElement(arr, ARRAY_SIZE(arr), &e);
+
+ FeatureParams params;
+ ftype::GetNameAndType(&e, params);
+
+ TEST_EQUAL(params.m_Types.size(), 1, (params));
+ TEST(params.IsTypeExist(GetType({"railway", "station", "light_rail"})), (params));
+ }
+
+ {
+ char const * arr[][2] = {
+ { "monorail", "yes" },
+ { "name", "Улица Академика Королёва" },
+ { "network", "Московский метрополитен" },
+ { "operator", "ГУП «Московский метрополитен»" },
+ { "public_transport", "stop_position" },
+ { "railway", "station" },
+ { "station", "monorail" },
+ { "transport", "monorail" },
+ };
+
+ XMLElement e;
+ FillXmlElement(arr, ARRAY_SIZE(arr), &e);
+
+ FeatureParams params;
+ ftype::GetNameAndType(&e, params);
+
+ TEST_EQUAL(params.m_Types.size(), 1, (params));
+ TEST(params.IsTypeExist(GetType({"railway", "station", "monorail"})), (params));
+ }
+}
diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp
index b2bc46818b..33c02114f5 100644
--- a/generator/osm2type.cpp
+++ b/generator/osm2type.cpp
@@ -383,7 +383,8 @@ namespace ftype
buffer_vector<uint32_t, 16> m_types;
public:
- enum EType { ENTRANCE, HIGHWAY, ADDRESS, ONEWAY, PRIVATE, LIT, NOFOOT, YESFOOT };
+ enum EType { ENTRANCE, HIGHWAY, ADDRESS, ONEWAY, PRIVATE, LIT, NOFOOT, YESFOOT,
+ RW_STATION_SUBWAY };
CachedTypes()
{
@@ -399,6 +400,8 @@ namespace ftype
};
for (auto const & e : arr)
m_types.push_back(c.GetTypeByPath(e));
+
+ m_types.push_back(c.GetTypeByPath({ "railway", "station", "subway" }));
}
uint32_t Get(EType t) const { return m_types[t]; }
@@ -407,6 +410,12 @@ namespace ftype
ftype::TruncValue(t, 1);
return t == Get(HIGHWAY);
}
+ bool IsRwStation(uint32_t t) const
+ {
+ // check the exact match with possible types
+ ftype::TruncValue(t, 3);
+ return t == Get(RW_STATION_SUBWAY);
+ }
};
void GetNameAndType(XMLElement * p, FeatureParams & params)
@@ -483,15 +492,23 @@ namespace ftype
}
}
- for (size_t i = 0; i < params.m_Types.size(); ++i)
- if (types.IsHighway(params.m_Types[i]))
+ bool highwayDone = false;
+ bool subwayDone = false;
+
+ // Get a copy of source types, because we will modify params in the loop;
+ FeatureParams::TTypes const vTypes = params.m_Types;
+ for (size_t i = 0; i < vTypes.size(); ++i)
+ {
+ if (!highwayDone && types.IsHighway(vTypes[i]))
{
TagProcessor(p).ApplyRules(
{
{ "oneway", "yes", [&params]() { params.AddType(types.Get(CachedTypes::ONEWAY)); }},
{ "oneway", "1", [&params]() { params.AddType(types.Get(CachedTypes::ONEWAY)); }},
{ "oneway", "-1", [&params]() { params.AddType(types.Get(CachedTypes::ONEWAY)); params.m_reverseGeometry = true; }},
+
{ "access", "private", [&params]() { params.AddType(types.Get(CachedTypes::PRIVATE)); }},
+
{ "lit", "~", [&params]() { params.AddType(types.Get(CachedTypes::LIT)); }},
{ "foot", "!", [&params]() { params.AddType(types.Get(CachedTypes::NOFOOT)); }},
@@ -499,9 +516,36 @@ namespace ftype
{ "foot", "~", [&params]() { params.AddType(types.Get(CachedTypes::YESFOOT)); }},
{ "sidewalk", "~", [&params]() { params.AddType(types.Get(CachedTypes::YESFOOT)); }},
});
- break;
+
+ highwayDone = true;
}
+ if (!subwayDone && types.IsRwStation(vTypes[i]))
+ {
+ TagProcessor(p).ApplyRules(
+ {
+ { "network", "London Underground", [&params]() { params.SetRwStationType("london"); }},
+ { "network", "New York City Subway", [&params]() { params.SetRwStationType("newyork"); }},
+ { "network", "Московский метрополитен", [&params]() { params.SetRwStationType("moscow"); }},
+ { "network", "Verkehrsverbund Berlin-Brandenburg", [&params]() { params.SetRwStationType("berlin"); }},
+ { "network", "Минский метрополитен", [&params]() { params.SetRwStationType("minsk"); }},
+
+ { "network", "Київський метрополітен", [&params]() { params.SetRwStationType("kiev"); }},
+ { "operator", "КП «Київський метрополітен»", [&params]() { params.SetRwStationType("kiev"); }},
+
+ { "network", "RATP", [&params]() { params.SetRwStationType("paris"); }},
+ { "network", "Metro de Barcelona", [&params]() { params.SetRwStationType("barcelona"); }},
+
+ { "network", "Metro de Madrid", [&params]() { params.SetRwStationType("madrid"); }},
+ { "operator", "Metro de Madrid", [&params]() { params.SetRwStationType("madrid"); }},
+
+ { "network", "Metropolitana di Roma", [&params]() { params.SetRwStationType("roma"); }},
+ });
+
+ subwayDone = true;
+ }
+ }
+
params.FinishAddingTypes();
// Collect addidtional information about feature such as
diff --git a/generator/osm_element.hpp b/generator/osm_element.hpp
index 5260d08733..2ae4457169 100644
--- a/generator/osm_element.hpp
+++ b/generator/osm_element.hpp
@@ -104,17 +104,81 @@ class SecondPassParser
/// Generated features should include parent relation tags to make
/// full types matching and storing any additional info.
- class RelationTagsProcessor
+ class RelationTagsBase
{
+ public:
+ RelationTagsBase() : m_cache(14) {}
+
+ void Reset(uint64_t fID, XMLElement * p)
+ {
+ m_featureID = fID;
+ m_current = p;
+ }
+
+ template <class ReaderT> bool operator() (uint64_t id, ReaderT & reader)
+ {
+ bool exists = false;
+ RelationElement & e = m_cache.Find(id, exists);
+ if (!exists)
+ CHECK(reader.Read(id, e), (id));
+
+ Process(e);
+ return false;
+ }
+
+ protected:
+ static bool IsSkipRelation(string const & type)
+ {
+ /// @todo Skip special relation types.
+ return (type == "multipolygon" || type == "bridge" || type == "restriction");
+ }
+
+ bool IsKeyTagExists(string const & key) const
+ {
+ for (auto const & p : m_current->m_tags)
+ if (p.key == key)
+ return true;
+ return false;
+ }
+
+ virtual void Process(RelationElement const & e) = 0;
+
+ protected:
uint64_t m_featureID;
XMLElement * m_current;
+ private:
my::Cache<uint64_t, RelationElement> m_cache;
+ };
+
+ class RelationTagsNode : public RelationTagsBase
+ {
+ typedef RelationTagsBase TBase;
+
+ protected:
+ void Process(RelationElement const & e) override
+ {
+ if (TBase::IsSkipRelation(e.GetType()))
+ return;
+
+ for (auto const & p : e.tags)
+ {
+ // Store only this tags to use it in railway stations processing for the particular city.
+ if (p.first == "network" || p.first == "operator" || p.first == "route")
+ if (!TBase::IsKeyTagExists(p.first))
+ TBase::m_current->AddTag(p.first, p.second);
+ }
+ }
+ } m_nodeRelations;
+
+ class RelationTagsWay : public RelationTagsBase
+ {
+ typedef RelationTagsBase TBase;
bool IsAcceptBoundary(RelationElement const & e) const
{
string role;
- CHECK(e.FindWay(m_featureID, role), (m_featureID));
+ CHECK(e.FindWay(TBase::m_featureID, role), (TBase::m_featureID));
// Do not accumulate boundary types (boundary=administrative) for inner polygons.
// Example: Minsk city border (admin_level=8) is inner for Minsk area border (admin_level=4).
@@ -124,25 +188,21 @@ class SecondPassParser
typedef unordered_set<string> NameKeysT;
void GetNameKeys(NameKeysT & keys) const
{
- for (auto const & p : m_current->m_tags)
+ for (auto const & p : TBase::m_current->m_tags)
if (strings::StartsWith(p.key, "name"))
keys.insert(p.key);
}
- void Process(RelationElement const & e)
+ protected:
+ void Process(RelationElement const & e) override
{
+ /// @todo Review route relations in future.
+ /// Actually, now they give a lot of dummy tags.
string const type = e.GetType();
-
- /// @todo Skip special relation types.
- if (type == "multipolygon" ||
- type == "route" ||
- type == "bridge" ||
- type == "restriction")
- {
+ if (TBase::IsSkipRelation(type) || type == "route")
return;
- }
- bool const isWay = (m_current->type == XMLElement::EntityType::Way);
+ bool const isWay = (TBase::m_current->type == XMLElement::EntityType::Way);
bool const isBoundary = isWay && (type == "boundary") && IsAcceptBoundary(e);
NameKeysT nameKeys;
@@ -154,7 +214,7 @@ class SecondPassParser
if (p.first == "type" || p.first == "route")
continue;
- /// Skip already existing "name" tags.
+ // Skip already existing "name" tags.
if (nameKeys.count(p.first) != 0)
continue;
@@ -164,52 +224,23 @@ class SecondPassParser
if (isWay && p.first == "place")
continue;
- m_current->AddTag(p.first, p.second);
+ TBase::m_current->AddTag(p.first, p.second);
}
}
-
- public:
- RelationTagsProcessor()
- : m_cache(14)
- {
- }
-
- void Reset(uint64_t fID, XMLElement * p)
- {
- m_featureID = fID;
- m_current = p;
- }
-
- template <class ReaderT> bool operator() (uint64_t id, ReaderT & reader)
- {
- bool exists = false;
- RelationElement & e = m_cache.Find(id, exists);
- if (!exists)
- CHECK(reader.Read(id, e), (id));
-
- Process(e);
- return false;
- }
-
- } m_relationsProcess;
+ } m_wayRelations;
bool ParseType(XMLElement * p, FeatureParams & params)
{
// Get tags from parent relations.
- m_relationsProcess.Reset(p->id, p);
-
if (p->type == XMLElement::EntityType::Node)
{
- // additional process of nodes ONLY if there is no native types
- FeatureParams fp;
- ftype::GetNameAndType(p, fp);
- if (!ftype::IsValidTypes(fp))
- m_holder.ForEachRelationByNodeCached(p->id, m_relationsProcess);
+ m_nodeRelations.Reset(p->id, p);
+ m_holder.ForEachRelationByNodeCached(p->id, m_nodeRelations);
}
else if (p->type == XMLElement::EntityType::Way)
{
- // always make additional process of ways
- m_holder.ForEachRelationByWayCached(p->id, m_relationsProcess);
+ m_wayRelations.Reset(p->id, p);
+ m_holder.ForEachRelationByWayCached(p->id, m_wayRelations);
}
// Get params from element tags.
diff --git a/generator/osm_source.cpp b/generator/osm_source.cpp
index 245adb7640..207ef7387e 100644
--- a/generator/osm_source.cpp
+++ b/generator/osm_source.cpp
@@ -20,14 +20,13 @@
#include "defines.hpp"
SourceReader::SourceReader()
-: m_file(unique_ptr<istream,Deleter>(&cin, Deleter(false)))
+: m_file(unique_ptr<istream, Deleter>(&cin, Deleter(false)))
{
LOG_SHORT(LINFO, ("Reading OSM data from stdin"));
}
SourceReader::SourceReader(string const & filename)
{
- CHECK(!filename.empty() , ("Filename can't be empty"));
m_file = unique_ptr<istream, Deleter>(new ifstream(filename), Deleter());
CHECK(static_cast<ifstream *>(m_file.get())->is_open() , ("Can't open file:", filename));
LOG_SHORT(LINFO, ("Reading OSM data from", filename));
diff --git a/generator/osm_source.hpp b/generator/osm_source.hpp
index 9a12daacb0..e3b5b07894 100644
--- a/generator/osm_source.hpp
+++ b/generator/osm_source.hpp
@@ -24,7 +24,7 @@ class SourceReader
public:
SourceReader();
- SourceReader(string const & filename);
+ explicit SourceReader(string const & filename);
explicit SourceReader(istringstream & stream);
uint64_t Read(char * buffer, uint64_t bufferSize);