R package for downloading OpenStreetMap data
1/***************************************************************************
2 * Project: osmdata
3 * File: common.h
4 * Language: C++
5 *
6 * osmdata is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * osmdata is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * osm-router. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * Author: Mark Padgham / Andrew Smith
20 * E-Mail: mark.padgham@email.com / andrew@casacazaz.net
21 *
22 * Description: Common header file for get-points/lines/polygons
23 *
24 * Limitations:
25 *
26 * Dependencies: none (rapidXML header included in osmdata)
27 *
28 * Compiler Options: -std=c++11
29 ***************************************************************************/
30
31#pragma once
32
33// These lines suppress two classes of warnings from rapidxml, but note that
34// this is forbidden on CRAN:
35// https://cran.r-project.org/web/packages/policies.html
36
37// #pragma GCC diagnostic push
38// #pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
39// #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
40#include "rapidxml.h"
41// #pragma GCC diagnostic pop
42
43#include <Rcpp.h> // Only for 'NA_REAL'
44
45// APS not good pratice to have all the headers included here, adds to compile time
46// better to #include as and where needed, ideally in source rather than headers,
47// and use fwd declarations wherever possible
48
49#include <limits>
50#include <memory>
51#include <string>
52
53#include <vector>
54#include <map>
55#include <set>
56#include <unordered_set>
57#include <cstring>
58#include <sstream>
59
60// APS uncomment to save xml input string to a file
61//#define DUMP_INPUT
62#ifdef DUMP_INPUT
63#include <fstream>
64#endif
65
66
67// make clear the id type
68typedef long long osmid_t;
69
70typedef std::vector <std::vector <float> > float_arr2;
71typedef std::vector <std::vector <std::vector <float> > > float_arr3;
72typedef std::vector <std::vector <double> > double_arr2;
73typedef std::vector <std::vector <std::vector <double> > > double_arr3;
74typedef std::vector <std::vector <std::string> > string_arr2;
75typedef std::vector <std::vector <std::vector <std::string> > > string_arr3;
76typedef std::vector <std::vector <osmid_t> > osmt_arr2;
77typedef std::vector <std::pair <osmid_t, std::string> > osm_str_vec;
78typedef std::vector <std::pair <osmid_t, std::string> >::iterator it_osm_str_vec;
79
80constexpr float FLOAT_MAX = std::numeric_limits<float>::max ();
81constexpr double DOUBLE_MAX = std::numeric_limits<double>::max ();
82
83// Convenience typedefs for some rapidxml types
84typedef std::unique_ptr<rapidxml::xml_document<> > XmlDocPtr;
85typedef const rapidxml::xml_node<>* XmlNodePtr;
86typedef const rapidxml::xml_attribute<>* XmlAttrPtr;
87
88// ----- functions in common.cpp
89XmlDocPtr parseXML (const std::string& xmlString);
90// ----- end functions in common.cpp
91
92struct UniqueVals
93{
94 // OSM IDs are sometimes duplicated, even though they ought not be. Unique
95 // IDs are stored in the following sets, ensuring that only the first
96 // instance of any given ID will be extracted. Using set.find in constructed
97 // takes 45ms for trial code; time without these finds = 60ms - HUH?
98 // NOTE: Previous code converted <osmid_t> IDs to std::string and added
99 // decimal places to generate unique IDs. This could be re-instated?
100 std::set <osmid_t> id_node, id_way, id_rel;
101 // Unique keys are also stored to provide column names. Although std::set
102 // is slower than an unordered_set, it is useful to have keys alphabetically
103 // ordered.
104 std::set <std::string> k_point, k_way, k_rel;
105 // A numeric index is also constructed to enable direct indexing into
106 // key-val matrices. This is an unsigned int for indexing into Rcpp objects.
107 std::map <std::string, unsigned int> k_point_index, k_way_index, k_rel_index;
108};
109
110struct RawNode
111{
112 osmid_t id;
113 std::string _version = "", _timestamp = "", _changeset = "", _uid = "", _user = ""; // metadata
114 std::vector <std::string> key, value;
115 double lat = NA_REAL, lon = NA_REAL;
116};
117
118struct Node
119{
120 osmid_t id;
121 std::string _version = "", _timestamp = "", _changeset = "", _uid = "", _user = ""; // metadata
122 std::map <std::string, std::string> key_val;
123 double lat = NA_REAL, lon = NA_REAL;
124};
125
126/* Traversing the XML tree means keys and values are read sequentially and
127 * cannot be processed simultaneously. Each way is thus initially read as a
128 * RawWay with separate vectors for keys and values. These are subsequently
129 * converted in Way to a vector of <std::pair>. */
130struct RawWay
131{
132 osmid_t id;
133 std::string _version, _timestamp, _changeset, _uid, _user; // metadata
134 double _lat = NA_REAL, _lon = NA_REAL; // center
135 std::vector <std::string> key, value;
136 std::vector <osmid_t> nodes;
137};
138
139struct OneWay
140{
141 osmid_t id;
142 std::string _version, _timestamp, _changeset, _uid, _user; // metadata
143 double _lat = NA_REAL, _lon = NA_REAL; // center
144 std::map <std::string, std::string> key_val;
145 std::vector <osmid_t> nodes;
146};
147
148struct RawRelation
149{
150 bool ispoly;
151 osmid_t id;
152 std::string member_type;
153 std::string _version, _timestamp, _changeset, _uid, _user; // metadata
154 double _lat = NA_REAL, _lon = NA_REAL; // center
155 // APS would (key,value) be better in a std::map?
156 std::vector <std::string> key, value, role_node, role_way, role_relation;
157 std::vector <osmid_t> nodes;
158 std::vector <osmid_t> ways;
159 std::vector <osmid_t> relations; // relations can contain relations
160};
161
162struct Relation
163{
164 bool ispoly;
165 osmid_t id;
166 std::string rel_type;
167 std::string _version, _timestamp, _changeset, _uid, _user; // metadata
168 double _lat = NA_REAL, _lon = NA_REAL; // center
169 std::map <std::string, std::string> key_val;
170 // Relations may have nodes as members, but these are not used here.
171 std::vector <std::pair <osmid_t, std::string> > nodes; // str = role
172 std::vector <std::pair <osmid_t, std::string> > ways; // str = role
173 std::vector <std::pair <osmid_t, std::string> > relations; // str = role
174};
175
176typedef std::vector <Relation> Relations;
177typedef std::map <osmid_t, OneWay> Ways;
178
179// MP: osmid_t (long long) is Node.id, and thus repetitive, but traverseNode has
180// to store the ID in the Node struct first, before this can be used to make the
181// map of Nodes. TODO: Is there a better way?
182typedef std::map <osmid_t, Node> Nodes;