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>2014-11-14 16:34:00 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:33:19 +0300
commit48ecb3a58742404f15d9e78eff75109f388ffd3a (patch)
tree6d6828c35040c338a0cfa2aee7d117b8e110c0d9 /generator
parent50035f452fee699254c84d3608b1a98e54bebe64 (diff)
[generator] Better process of parent relation tags for generated feature.
Diffstat (limited to 'generator')
-rw-r--r--generator/feature_generator.cpp9
-rw-r--r--generator/osm_element.hpp169
2 files changed, 76 insertions, 102 deletions
diff --git a/generator/feature_generator.cpp b/generator/feature_generator.cpp
index 5d602fa4ec..b75a45164e 100644
--- a/generator/feature_generator.cpp
+++ b/generator/feature_generator.cpp
@@ -41,8 +41,8 @@ class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileRea
template <class TElement, class ToDo> struct process_base
{
- reader_t & m_reader;
protected:
+ reader_t & m_reader;
ToDo & m_toDo;
public:
process_base(reader_t & reader, ToDo & toDo) : m_reader(reader), m_toDo(toDo) {}
@@ -73,12 +73,7 @@ class FileHolder : public cache::BaseFileHolder<TNodesHolder, cache::DataFileRea
bool operator() (uint64_t id)
{
- switch (this->m_toDo(id))
- {
- case 1: return true;
- case -1: return false;
- default: return base_type::operator()(id);
- }
+ return this->m_toDo(id, this->m_reader);
}
};
diff --git a/generator/osm_element.hpp b/generator/osm_element.hpp
index 4b60a02987..b69bf578f5 100644
--- a/generator/osm_element.hpp
+++ b/generator/osm_element.hpp
@@ -11,6 +11,7 @@
#include "../base/string_utils.hpp"
#include "../base/logging.hpp"
#include "../base/stl_add.hpp"
+#include "../base/cache.hpp"
#include "../std/unordered_map.hpp"
#include "../std/list.hpp"
@@ -98,144 +99,122 @@ class SecondPassParser : public BaseOSMParser
holes_list_t & GetHoles() { return m_holes.GetHoles(); }
};
- /// Feature types processor.
- class type_processor
+ /// Generated features should include parent relation tags to make
+ /// full types matching and storing any additional info.
+ class RelationTagsProcessor
{
- static void MakeXMLElement(RelationElement const & rel, XMLElement & out)
- {
- for (auto i = rel.tags.begin(); i != rel.tags.end(); ++i)
- if (i->first != "type")
- out.AddKV(i->first, i->second);
- }
-
- /// @param[in] ID of processing feature.
uint64_t m_featureID;
+ XMLElement * m_current;
- /// @param[out] Feature value as result.
- FeatureParams * m_val;
+ my::Cache<uint64_t, RelationElement> m_cache;
- /// Cache: relation id -> feature value (for fast feature parsing)
- struct RelationValue
- {
- FeatureParams m_p;
- RelationElement * m_e;
-
- RelationValue() : m_e(0) {}
- };
-
- typedef unordered_map<uint64_t, RelationValue> RelationCacheT;
- RelationCacheT m_typeCache;
-
- bool IsAcceptBoundaryTypes(RelationElement const & rel) const
+ bool IsAcceptBoundary(RelationElement const & e) const
{
string role;
- if (!rel.FindWay(m_featureID, role))
- {
- // This case is possible when we found the relation by node (just skip it).
- CHECK ( rel.FindNode(m_featureID, role), (m_featureID) );
- return false;
- }
+ CHECK(e.FindWay(m_featureID, role), (m_featureID));
- // Do not accumulate boundary types (boundary-administrative-*) for inner polygons.
+ // 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).
return (role != "inner");
}
- uint32_t const m_boundaryType;
- uint32_t GetSkipBoundaryType(RelationElement const * rel) const
- {
- return ((rel == 0 || IsAcceptBoundaryTypes(*rel)) ? 0 : m_boundaryType);
- }
-
- public:
- type_processor() : m_boundaryType(ftype::GetBoundaryType2())
+ bool HasName() const
{
- }
+ for (auto p : m_current->childs)
+ {
+ if (p.name == "tag")
+ for (auto a : p.attrs)
+ if (strings::StartsWith(a.first, "name"))
+ return true;
+ }
- ~type_processor()
- {
- for (auto & r : m_typeCache)
- delete r.second.m_e;
+ return false;
}
- /// Start process new feature.
- void Reset(uint64_t fID, FeatureParams * val)
+ void Process(RelationElement const & e)
{
- m_featureID = fID;
- m_val = val;
- }
+ string const type = e.GetType();
- /// 1. "initial relation" process
- int operator() (uint64_t id)
- {
- auto const i = m_typeCache.find(id);
- if (i != m_typeCache.end())
+ /// @todo Skip special relation types.
+ if (type == "multipolygon" ||
+ type == "route" ||
+ type == "bridge" ||
+ type == "restriction")
{
- m_val->AddTypes(i->second.m_p, GetSkipBoundaryType(i->second.m_e));
- return -1; // continue process relations
+ return;
}
- return 0; // read relation from file (see next operator)
- }
- /// 2. "relation from file" process
- /// param[in] rel Get non-const reference to Swap inner data
- bool operator() (uint64_t id, RelationElement & rel)
- {
- string const type = rel.GetType();
- if (type == "multipolygon")
+ bool const isWay = (m_current->name == "way");
+ bool const isBoundary = isWay && (type == "boundary") && IsAcceptBoundary(e);
+ bool const hasName = HasName();
+
+ for (auto p : e.tags)
{
- // we will process multipolygons later
- return false;
- }
- bool const isBoundary = (type == "boundary");
+ /// @todo Skip common key tags.
+ if (p.first == "type" || p.first == "route")
+ continue;
- // make XMLElement struct from relation's tags for GetNameAndType function.
- XMLElement e;
- MakeXMLElement(rel, e);
+ if (hasName && strings::StartsWith(p.first, "name"))
+ continue;
- // process types of relation and add them to m_val
- RelationValue val;
- ftype::GetNameAndType(&e, val.m_p);
- if (val.m_p.IsValid())
- {
- m_val->AddTypes(val.m_p, GetSkipBoundaryType(isBoundary ? &rel : 0));
+ if (!isBoundary && p.first == "boundary")
+ continue;
- if (isBoundary)
- {
- val.m_e = new RelationElement();
- val.m_e->Swap(rel);
- }
+ if (isWay && p.first == "place")
+ continue;
+
+ m_current->AddKV(p.first, p.second);
}
+ }
+
+ public:
+ RelationTagsProcessor()
+ : m_cache(14)
+ {
+ }
- m_typeCache[id] = val;
+ void Reset(uint64_t fID, XMLElement * p)
+ {
+ m_featureID = fID;
+ m_current = p;
+ }
- // continue process relations
+ 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_typeProcessor;
+ } m_relationsProcess;
bool ParseType(XMLElement * p, uint64_t & id, FeatureParams & params)
{
- CHECK ( strings::to_uint64(p->attrs["id"], id), (p->attrs["id"]) );
-
- // try to get type from element tags
- ftype::GetNameAndType(p, params);
+ CHECK(strings::to_uint64(p->attrs["id"], id), (p->attrs["id"]));
- // try to get type from relations tags
- m_typeProcessor.Reset(id, &params);
+ // Get tags from parent relations.
+ m_relationsProcess.Reset(id, p);
- if (p->name == "node" && !params.IsValid())
+ if (p->name == "node")
{
// additional process of nodes ONLY if there is no native types
- m_holder.ForEachRelationByNodeCached(id, m_typeProcessor);
+ FeatureParams fp;
+ ftype::GetNameAndType(p, fp);
+ if (!ftype::IsValidTypes(fp))
+ m_holder.ForEachRelationByNodeCached(id, m_relationsProcess);
}
else if (p->name == "way")
{
// always make additional process of ways
- m_holder.ForEachRelationByWayCached(id, m_typeProcessor);
+ m_holder.ForEachRelationByWayCached(id, m_relationsProcess);
}
+ // Get params from element tags.
+ ftype::GetNameAndType(p, params);
params.FinishAddingTypes();
return ftype::IsValidTypes(params);
}