diff options
Diffstat (limited to 'generator/first_pass_parser.hpp')
-rw-r--r-- | generator/first_pass_parser.hpp | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/generator/first_pass_parser.hpp b/generator/first_pass_parser.hpp new file mode 100644 index 0000000000..cbea6fac04 --- /dev/null +++ b/generator/first_pass_parser.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include "xml_element.hpp" + +#include "../indexer/osm_decl.hpp" +#include "../indexer/mercator.hpp" + +#include "../base/string_utils.hpp" + + +template <class THolder> +class FirstPassParser : public BaseOSMParser +{ + THolder & m_holder; + +public: + FirstPassParser(THolder & holder) : m_holder(holder) + { + static char const * tags[] = { "osm", "node", "way", "relation" }; + SetTags(tags); + } + +protected: + virtual void EmitElement(XMLElement * p) + { + uint64_t id; + VERIFY ( utils::to_uint64(p->attrs["id"], id), ("Unknown element with invalid id : ", p->attrs["id"]) ); + + if (p->name == "node") + { + // store point + + double lat, lng; + VERIFY ( utils::to_double(p->attrs["lat"], lat), ("Bad node lat : ", p->attrs["lat"]) ); + VERIFY ( utils::to_double(p->attrs["lon"], lng), ("Bad node lon : ", p->attrs["lon"]) ); + + // convert to mercator + lat = MercatorBounds::LatToY(lat); + lng = MercatorBounds::LonToX(lng); + + m_holder.AddNode(id, lat, lng); + } + else if (p->name == "way") + { + // store way + + WayElement e; + bool bUnite = false; + bool bEmptyTags = true; + + for (size_t i = 0; i < p->childs.size(); ++i) + { + if (p->childs[i].name == "nd") + { + uint64_t ref; + VERIFY ( utils::to_uint64(p->childs[i].attrs["ref"], ref), ("Bad node ref in way : ", p->childs[i].attrs["ref"]) ); + e.nodes.push_back(ref); + } + else if (!bUnite && (p->childs[i].name == "tag")) + { + bEmptyTags = false; + + // process way's tags to define - if we need to join ways + string const & k = p->childs[i].attrs["k"]; + string const & v = p->childs[i].attrs["v"]; + bUnite = feature::NeedUnite(k, v); + } + } + + if (e.IsValid()) + { + m_holder.AddWay(id, e); + if (bUnite || bEmptyTags) + m_holder.AddMappedWay(id, e, bEmptyTags); + } + } + else if (p->name == "relation") + { + // store relation + + RelationElement e; + for (size_t i = 0; i < p->childs.size(); ++i) + { + if (p->childs[i].name == "member") + { + uint64_t ref; + VERIFY ( utils::to_uint64(p->childs[i].attrs["ref"], ref), ("Bad ref in relation : ", p->childs[i].attrs["ref"]) ); + + string const & type = p->childs[i].attrs["type"]; + string const & role = p->childs[i].attrs["role"]; + if (type == "node") + e.nodes.push_back(make_pair(ref, role)); + else + e.ways.push_back(make_pair(ref, role)); + } + else if (p->childs[i].name == "tag") + { + // relation tags writing as is + e.tags.insert(make_pair(p->childs[i].attrs["k"], p->childs[i].attrs["v"])); + } + } + + if (e.IsValid()) + m_holder.AddRelation(id, e); + } + } +}; |