R package for downloading OpenStreetMap data
1/***************************************************************************
2 * Project: osmdata
3 * File: osmdata-sc.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 * osm-router. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * Author: Mark Padgham
20 * E-Mail: mark.padgham@email.com
21 *
22 * Description: Extract OSM data from an object of class XmlData and return
23 * it in Rcpp::List format.
24 *
25 * Limitations:
26 *
27 * Dependencies: none (rapidXML header included in osmdata)
28 *
29 * Compiler Options: -std=c++11
30 ***************************************************************************/
31
32#include "osmdata.h"
33#include "osmdata-sc.h"
34
35// Function to generate IDs for the edges in each way
36std::string random_id (size_t len) {
37 auto randchar = []() -> char
38 {
39 const char charset[] = \
40 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
41 const size_t max_index = (sizeof(charset) - 1);
42 //return charset [ rand() % max_index ];
43 size_t i = static_cast <size_t> (floor (Rcpp::runif (1) [0] * max_index));
44 return charset [i];
45 };
46 std::string str (len, 0);
47 std::generate_n (str.begin(), len, randchar);
48 return str;
49}
50
51Rcpp::List rel_membs_as_list (XmlDataSC &xml)
52{
53 std::unordered_map <std::string, std::vector <std::string> >
54 rel_membs = xml.get_rel_membs ();
55
56 Rcpp::List ret (rel_membs.size ());
57 std::vector <std::string> retnames (rel_membs.size ());
58
59 size_t i1 = 0; // std::vector index is size_t
60 int i2 = 0; // Rcpp index is int
61 for (auto m: rel_membs)
62 {
63 retnames [i1++] = m.first;
64 ret [i2++] = m.second;
65 }
66 ret.attr ("names") = retnames;
67
68 return ret;
69}
70
71Rcpp::List way_membs_as_list (XmlDataSC &xml)
72{
73 std::unordered_map <std::string, std::vector <std::string> >
74 way_membs = xml.get_way_membs ();
75
76 Rcpp::List ret (way_membs.size ());
77 std::vector <std::string> retnames (way_membs.size ());
78
79 size_t i1 = 0;
80 int i2 = 0;
81 for (auto m: way_membs)
82 {
83 retnames [i1] = m.first;
84 ret [i2++] = m.second;
85 }
86 ret.attr ("names") = retnames;
87
88 return ret;
89}
90
91//' rcpp_osmdata_sc
92//'
93//' Return OSM data in silicate (SC) format
94//'
95//' @param st Text contents of an overpass API query
96//' @return Rcpp::List objects of OSM data
97//'
98//' @noRd
99// [[Rcpp::export]]
100Rcpp::List rcpp_osmdata_sc (const std::string& st)
101{
102#ifdef DUMP_INPUT
103 {
104 std::ofstream dump ("./osmdata-sf.xml");
105 if (dump.is_open())
106 {
107 dump.write (st.c_str(), st.size());
108 }
109 }
110#endif
111
112 XmlDataSC xml (st);
113
114 Rcpp::DataFrame vertex = Rcpp::DataFrame::create (
115 Rcpp::Named ("x_") = xml.get_vx (),
116 Rcpp::Named ("y_") = xml.get_vy (),
117 Rcpp::Named ("vertex_") = xml.get_vert_id (),
118 Rcpp::_["stringsAsFactors"] = false );
119
120 Rcpp::DataFrame edge = Rcpp::DataFrame::create (
121 Rcpp::Named (".vx0") = xml.get_vx0 (),
122 Rcpp::Named (".vx1") = xml.get_vx1 (),
123 Rcpp::Named ("edge_") = xml.get_edge (),
124 Rcpp::_["stringsAsFactors"] = false );
125
126 Rcpp::DataFrame oXe = Rcpp::DataFrame::create (
127 Rcpp::Named ("edge_") = xml.get_edge (),
128 Rcpp::Named ("object_") = xml.get_object (),
129 Rcpp::_["stringsAsFactors"] = false );
130
131 Rcpp::DataFrame obj_node = Rcpp::DataFrame::create (
132 Rcpp::Named ("vertex_") = xml.get_node_id (),
133 Rcpp::Named ("key") = xml.get_node_key (),
134 Rcpp::Named ("value") = xml.get_node_val (),
135 Rcpp::_["stringsAsFactors"] = false );
136
137 Rcpp::DataFrame obj_way = Rcpp::DataFrame::create (
138 Rcpp::Named ("object_") = xml.get_way_id (),
139 Rcpp::Named ("key") = xml.get_way_key (),
140 Rcpp::Named ("value") = xml.get_way_val (),
141 Rcpp::_["stringsAsFactors"] = false );
142
143 Rcpp::DataFrame obj_rel_memb = Rcpp::DataFrame::create (
144 Rcpp::Named ("relation_") = xml.get_rel_memb_id (),
145 Rcpp::Named ("member") = xml.get_rel_ref (),
146 Rcpp::Named ("type") = xml.get_rel_memb_type (),
147 Rcpp::Named ("role") = xml.get_rel_role (),
148 Rcpp::_["stringsAsFactors"] = false );
149
150 Rcpp::DataFrame obj_rel_kv = Rcpp::DataFrame::create (
151 Rcpp::Named ("relation_") = xml.get_rel_kv_id (),
152 Rcpp::Named ("key") = xml.get_rel_key (),
153 Rcpp::Named ("value") = xml.get_rel_val (),
154 Rcpp::_["stringsAsFactors"] = false );
155
156 Rcpp::List rel_membs = rel_membs_as_list (xml),
157 way_membs = way_membs_as_list (xml);
158
159 Rcpp::List ret (9);
160 ret [0] = vertex;
161 ret [1] = edge;
162 ret [2] = oXe;
163 ret [3] = obj_node;
164 ret [4] = obj_way; // The SC object table
165 ret [5] = obj_rel_memb;
166 ret [6] = obj_rel_kv;
167 ret [7] = Rcpp::as <Rcpp::List> (way_membs);
168 ret [8] = Rcpp::as <Rcpp::List> (rel_membs);
169
170 std::vector <std::string> retnames {"vertex",
171 "edge", "object_link_edge",
172 "nodes", "object",
173 "relation_members",
174 "relation_properties",
175 "way_membs", "rel_membs"};
176 ret.attr ("names") = retnames;
177
178 return ret;
179}