R package for downloading OpenStreetMap data

add C++ implementation of osmdata_data_frame

+340
+55
R/RcppExports.R
··· 1 1 # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 2 # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 3 4 + #' get_osm_relations 5 + #' 6 + #' Return a dual Rcpp::List containing all OSM relations, the firmt element of 7 + #' which holds `multipolygon` relations, while the second holds all others, 8 + #' which are stored as `multilinestring` objects. 9 + #' 10 + #' @param rels Pointer to the vector of Relation objects 11 + #' @param nodes Pointer to the vector of node objects 12 + #' @param ways Pointer to the vector of way objects 13 + #' @param unique_vals Pointer to a UniqueVals object containing std::sets of all 14 + #' unique IDs and keys for each kind of OSM object (nodes, ways, rels). 15 + #' 16 + #' @return A dual Rcpp::List, the first of which contains the multipolygon 17 + #' relations; the second the multilinestring relations. 18 + #' 19 + #' @noRd 20 + NULL 21 + 22 + #' get_osm_ways 23 + #' 24 + #' Store key-val pairs for OSM ways as a list/data.frame 25 + #' 26 + #' @param kv_df Pointer to Rcpp::DataFrame to hold key-value pairs 27 + #' @param way_ids Vector of <osmid_t> IDs of ways to trace 28 + #' @param ways Pointer to all ways in data set 29 + #' @param nodes Pointer to all nodes in data set 30 + #' @param unique_vals pointer to all unique values (OSM IDs and keys) in data set 31 + #' 32 + #' @noRd 33 + NULL 34 + 35 + #' get_osm_nodes 36 + #' 37 + #' Store OSM nodes as `sf::POINT` objects 38 + #' 39 + #' @param kv_df Pointer to Rcpp::DataFrame to hold key-value pairs 40 + #' @param nodes Pointer to all nodes in data set 41 + #' @param unique_vals pointer to all unique values (OSM IDs and keys) in data set 42 + #' 43 + #' @noRd 44 + NULL 45 + 46 + #' rcpp_osmdata_df 47 + #' 48 + #' Return OSM data key-value pairs in series of data.frame objects, without any 49 + #' spatial/geometrtic information. 50 + #' 51 + #' @param st Text contents of an overpass API query 52 + #' @return Rcpp::List objects of OSM data 53 + #' 54 + #' @noRd 55 + rcpp_osmdata_df <- function(st) { 56 + .Call(`_osmdata_rcpp_osmdata_df`, st) 57 + } 58 + 4 59 #' rcpp_osmdata_sc 5 60 #' 6 61 #' Return OSM data in silicate (SC) format
+11
src/RcppExports.cpp
··· 10 10 Rcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); 11 11 #endif 12 12 13 + // rcpp_osmdata_df 14 + Rcpp::List rcpp_osmdata_df(const std::string& st); 15 + RcppExport SEXP _osmdata_rcpp_osmdata_df(SEXP stSEXP) { 16 + BEGIN_RCPP 17 + Rcpp::RObject rcpp_result_gen; 18 + Rcpp::RNGScope rcpp_rngScope_gen; 19 + Rcpp::traits::input_parameter< const std::string& >::type st(stSEXP); 20 + rcpp_result_gen = Rcpp::wrap(rcpp_osmdata_df(st)); 21 + return rcpp_result_gen; 22 + END_RCPP 23 + } 13 24 // rcpp_osmdata_sc 14 25 Rcpp::List rcpp_osmdata_sc(const std::string& st); 15 26 RcppExport SEXP _osmdata_rcpp_osmdata_sc(SEXP stSEXP) {
+259
src/osmdata-data_frame.cpp
··· 1 + /*************************************************************************** 2 + * Project: osmdata 3 + * File: osmdata-data_frame.cpp 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 + * osmdata. If not, see <https://www.gnu.org/licenses/>. 18 + * 19 + * Author: Mark Padgham 20 + * E-Mail: mark.padgham@email.com 21 + * 22 + * Description: Modified version of 'osmdata-sf' to extract OSM data from an 23 + * object of class XmlData and return it in Rcpp::List format, 24 + * but in this case ignoring the actual geometric data. The 25 + * returned object contains key-value data only, for return 26 + * from the R function 'osmdata_data_frame'. 27 + * 28 + * Limitations: 29 + * 30 + * Dependencies: none (rapidXML header included in osmdata) 31 + * 32 + * Compiler Options: -std=c++11 33 + ***************************************************************************/ 34 + 35 + #include "osmdata.h" 36 + 37 + #include <Rcpp.h> 38 + 39 + // Note: This code uses explicit index counters within most loops which use Rcpp 40 + // objects, because these otherwise require a 41 + // static_cast <size_t> (std::distance (...)). This operation copies each 42 + // instance and can slow the loops down by several orders of magnitude! 43 + 44 + /************************************************************************ 45 + ************************************************************************ 46 + ** ** 47 + ** 1. PRIMARY FUNCTIONS TO TRACE WAYS AND RELATIONS ** 48 + ** ** 49 + ************************************************************************ 50 + ************************************************************************/ 51 + 52 + 53 + //' get_osm_relations 54 + //' 55 + //' Return a dual Rcpp::List containing all OSM relations, the firmt element of 56 + //' which holds `multipolygon` relations, while the second holds all others, 57 + //' which are stored as `multilinestring` objects. 58 + //' 59 + //' @param rels Pointer to the vector of Relation objects 60 + //' @param nodes Pointer to the vector of node objects 61 + //' @param ways Pointer to the vector of way objects 62 + //' @param unique_vals Pointer to a UniqueVals object containing std::sets of all 63 + //' unique IDs and keys for each kind of OSM object (nodes, ways, rels). 64 + //' 65 + //' @return A dual Rcpp::List, the first of which contains the multipolygon 66 + //' relations; the second the multilinestring relations. 67 + //' 68 + //' @noRd 69 + Rcpp::DataFrame osm_df::get_osm_relations (const Relations &rels, 70 + const UniqueVals &unique_vals) 71 + { 72 + std::vector <std::string> ids_mp, rel_id_mp; 73 + std::vector <std::string> roles; 74 + 75 + const unsigned int nmp = rels.size (); 76 + 77 + size_t ncol = unique_vals.k_rel.size (); 78 + rel_id_mp.reserve (nmp); 79 + 80 + Rcpp::CharacterMatrix kv_mat (Rcpp::Dimension (nmp, ncol)); 81 + unsigned int count = 0; 82 + 83 + for (auto itr = rels.begin (); itr != rels.end (); ++itr) 84 + { 85 + Rcpp::checkUserInterrupt (); 86 + 87 + rel_id_mp.push_back (std::to_string (itr->id)); 88 + 89 + osm_convert::get_value_mat_rel (itr, unique_vals, kv_mat, count++); 90 + } 91 + 92 + Rcpp::DataFrame kv_df; 93 + if (rel_id_mp.size () > 0) 94 + { 95 + kv_mat.attr ("names") = unique_vals.k_rel; 96 + kv_mat.attr ("dimnames") = Rcpp::List::create (rel_id_mp, unique_vals.k_rel); 97 + kv_df = osm_convert::restructure_kv_mat (kv_mat, false); 98 + } else 99 + kv_df = R_NilValue; 100 + 101 + return kv_df; 102 + } 103 + 104 + //' get_osm_ways 105 + //' 106 + //' Store key-val pairs for OSM ways as a list/data.frame 107 + //' 108 + //' @param kv_df Pointer to Rcpp::DataFrame to hold key-value pairs 109 + //' @param way_ids Vector of <osmid_t> IDs of ways to trace 110 + //' @param ways Pointer to all ways in data set 111 + //' @param nodes Pointer to all nodes in data set 112 + //' @param unique_vals pointer to all unique values (OSM IDs and keys) in data set 113 + //' 114 + //' @noRd 115 + void osm_df::get_osm_ways (Rcpp::DataFrame &kv_df, 116 + const std::set <osmid_t> &way_ids, const Ways &ways, 117 + const UniqueVals &unique_vals) 118 + { 119 + 120 + size_t nrow = way_ids.size (), ncol = unique_vals.k_way.size (); 121 + std::vector <std::string> waynames; 122 + waynames.reserve (way_ids.size ()); 123 + 124 + Rcpp::CharacterMatrix kv_mat (Rcpp::Dimension (nrow, ncol)); 125 + std::fill (kv_mat.begin (), kv_mat.end (), NA_STRING); 126 + unsigned int count = 0; 127 + for (auto wi = way_ids.begin (); wi != way_ids.end (); ++wi) 128 + { 129 + Rcpp::checkUserInterrupt (); 130 + waynames.push_back (std::to_string (*wi)); 131 + auto wj = ways.find (*wi); 132 + osm_convert::get_value_mat_way (wj, unique_vals, kv_mat, count); 133 + count++; 134 + } 135 + 136 + kv_df = R_NilValue; 137 + if (way_ids.size () > 0) 138 + { 139 + kv_mat.attr ("names") = unique_vals.k_way; 140 + kv_mat.attr ("dimnames") = Rcpp::List::create (waynames, unique_vals.k_way); 141 + if (kv_mat.nrow () > 0 && kv_mat.ncol () > 0) 142 + kv_df = osm_convert::restructure_kv_mat (kv_mat, false); 143 + } 144 + } 145 + 146 + //' get_osm_nodes 147 + //' 148 + //' Store OSM nodes as `sf::POINT` objects 149 + //' 150 + //' @param kv_df Pointer to Rcpp::DataFrame to hold key-value pairs 151 + //' @param nodes Pointer to all nodes in data set 152 + //' @param unique_vals pointer to all unique values (OSM IDs and keys) in data set 153 + //' 154 + //' @noRd 155 + void osm_df::get_osm_nodes (Rcpp::DataFrame &kv_df, 156 + const Nodes &nodes, const UniqueVals &unique_vals) 157 + { 158 + size_t nrow = nodes.size (), ncol = unique_vals.k_point.size (); 159 + 160 + Rcpp::CharacterMatrix kv_mat (Rcpp::Dimension (nrow, ncol)); 161 + std::fill (kv_mat.begin (), kv_mat.end (), NA_STRING); 162 + 163 + std::vector <std::string> ptnames; 164 + ptnames.reserve (nodes.size ()); 165 + unsigned int count = 0; 166 + for (auto ni = nodes.begin (); ni != nodes.end (); ++ni) 167 + { 168 + if (count % 1000 == 0) 169 + Rcpp::checkUserInterrupt (); 170 + 171 + ptnames.push_back (std::to_string (ni->first)); 172 + for (auto kv_iter = ni->second.key_val.begin (); 173 + kv_iter != ni->second.key_val.end (); ++kv_iter) 174 + { 175 + const std::string &key = kv_iter->first; 176 + unsigned int ndi = unique_vals.k_point_index.at (key); 177 + kv_mat (count, ndi) = kv_iter->second; 178 + } 179 + count++; 180 + } 181 + if (unique_vals.k_point.size () > 0) 182 + { 183 + kv_mat.attr ("dimnames") = Rcpp::List::create (ptnames, unique_vals.k_point); 184 + kv_df = osm_convert::restructure_kv_mat (kv_mat, false); 185 + } else 186 + kv_df = R_NilValue; 187 + 188 + ptnames.clear (); 189 + } 190 + 191 + 192 + /************************************************************************ 193 + ************************************************************************ 194 + ** ** 195 + ** THE FINAL RCPP FUNCTION CALLED BY osmdata_df ** 196 + ** ** 197 + ************************************************************************ 198 + ************************************************************************/ 199 + 200 + //' rcpp_osmdata_df 201 + //' 202 + //' Return OSM data key-value pairs in series of data.frame objects, without any 203 + //' spatial/geometrtic information. 204 + //' 205 + //' @param st Text contents of an overpass API query 206 + //' @return Rcpp::List objects of OSM data 207 + //' 208 + //' @noRd 209 + // [[Rcpp::export]] 210 + Rcpp::List rcpp_osmdata_df (const std::string& st) 211 + { 212 + XmlData xml (st); 213 + 214 + const std::map <osmid_t, Node>& nodes = xml.nodes (); 215 + const std::map <osmid_t, OneWay>& ways = xml.ways (); 216 + const std::vector <Relation>& rels = xml.relations (); 217 + const UniqueVals& unique_vals = xml.unique_vals (); 218 + 219 + /* -------------------------------------------------------------- 220 + * 1. Extract OSM Relations 221 + * --------------------------------------------------------------*/ 222 + 223 + Rcpp::DataFrame kv_rels = osm_df::get_osm_relations (rels, unique_vals); 224 + 225 + /* -------------------------------------------------------------- 226 + * 2. Extract OSM ways 227 + * --------------------------------------------------------------*/ 228 + 229 + std::set <osmid_t> way_ids; 230 + for (auto itw = ways.begin (); itw != ways.end (); ++itw) 231 + { 232 + way_ids.insert ((*itw).first); 233 + } 234 + 235 + Rcpp::List polyList (way_ids.size ()); 236 + Rcpp::DataFrame kv_df_ways; 237 + osm_df::get_osm_ways (kv_df_ways, way_ids, ways, unique_vals); 238 + 239 + /* -------------------------------------------------------------- 240 + * 3. Extract OSM nodes 241 + * --------------------------------------------------------------*/ 242 + 243 + Rcpp::DataFrame kv_df_points; 244 + osm_df::get_osm_nodes (kv_df_points, nodes, unique_vals); 245 + 246 + /* -------------------------------------------------------------- 247 + * 4. Collate all data 248 + * --------------------------------------------------------------*/ 249 + 250 + Rcpp::List ret (3); 251 + ret [0] = kv_df_points; 252 + ret [1] = kv_df_ways; 253 + ret [2] = kv_rels; 254 + 255 + std::vector <std::string> retnames {"points_kv", "ways_kv", "rels_kv"}; 256 + ret.attr ("names") = retnames; 257 + 258 + return ret; 259 + }
+13
src/osmdata.h
··· 487 487 } // end namespace osm_sc 488 488 489 489 Rcpp::List rcpp_osmdata_sc (const std::string& st); 490 + 491 + namespace osm_df { 492 + 493 + Rcpp::DataFrame get_osm_relations (const Relations &rels, 494 + const UniqueVals &unique_vals); 495 + void get_osm_ways (Rcpp::DataFrame &kv_df, const std::set <osmid_t> &way_ids, 496 + const Ways &ways, const UniqueVals &unique_vals); 497 + void get_osm_nodes (Rcpp::DataFrame &kv_df, 498 + const Nodes &nodes, const UniqueVals &unique_vals); 499 + 500 + } // end namespace osm_df 501 + 502 + Rcpp::List rcpp_osmdata_df (const std::string& st);
+2
src/osmdata_init.c
··· 8 8 */ 9 9 10 10 /* .Call calls */ 11 + extern SEXP _osmdata_rcpp_osmdata_df(SEXP); 11 12 extern SEXP _osmdata_rcpp_osmdata_sc(SEXP); 12 13 extern SEXP _osmdata_rcpp_osmdata_sf(SEXP); 13 14 extern SEXP _osmdata_rcpp_osmdata_sp(SEXP); 14 15 15 16 static const R_CallMethodDef CallEntries[] = { 17 + {"_osmdata_rcpp_osmdata_df", (DL_FUNC) &_osmdata_rcpp_osmdata_df, 1}, 16 18 {"_osmdata_rcpp_osmdata_sc", (DL_FUNC) &_osmdata_rcpp_osmdata_sc, 1}, 17 19 {"_osmdata_rcpp_osmdata_sf", (DL_FUNC) &_osmdata_rcpp_osmdata_sf, 1}, 18 20 {"_osmdata_rcpp_osmdata_sp", (DL_FUNC) &_osmdata_rcpp_osmdata_sp, 1},