R package for downloading OpenStreetMap data
at main 182 lines 6.8 kB view raw
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;