diff --git a/R/get-osmdata.R b/R/get-osmdata.R index 3d616177..55006ecb 100644 --- a/R/get-osmdata.R +++ b/R/get-osmdata.R @@ -381,34 +381,32 @@ osmdata_sc <- function(q, doc, directed = FALSE, quiet=TRUE, encoding) { message ('converting OSM data to sc format') res <- rcpp_osmdata_sc (temp$doc) - # res has the $vertex, $edge and $object_link_edge tables ready to go. The - # $object table is mostly just key-val pairs, but the relations have - # additional members - called "ref" and "role" entries. The key-val tables - # are therefore expanded to add these two columns before rbind-ing the whole - # lot to the one table: - if (nrow (res$obj_rel) > 0) - res$obj_rel$obj_type <- "relation" - res$rel_kv$obj_type <- "relation" + # res has the $vertex, $edge and $object_link_edge tables ready to go. + # The rest are (node, way, rel) key-val tables which can just be rbind-ed, + # except for `obj_rel_memb`, which maps relations members onto roles and + # requires this bit of fidding: + if (nrow (res$obj_rel_memb) > 0) + { + res$obj_rel_memb <- data.frame ("object_" = res$obj_rel_memb$object_, + "key" = paste0 (res$obj_rel_memb$type, "_", + res$obj_rel_memb$role), + "val" = res$obj_rel_memb$ref, + "obj_type" = "relation", + stringsAsFactors = FALSE) + } + if (nrow (res$obj_rel_kv) > 0) + res$obj_rel_kv$obj_type <- "relation" if (nrow (res$obj_way) > 0) res$obj_way$obj_type <- "way" if (nrow (res$obj_node) > 0) res$obj_node$obj_type <- "node" - #if (nrow (res$rel) > 0) - #{ - # # Change res$rel from ("ref", "role") to ("value", "key") - # res$rel <- data.frame (object_ = res$rel$object, - # key = paste0 ("rel_role_", res$rel$role), - # value = res$rel$ref, - # obj_type = "relation", - # stringsAsFactors = FALSE) - #} - res$object_link_edge$native_ <- TRUE #res <- duplicate_twoway_edges (res, directed) obj <- list () # SC **does not** use osmdata class definition - obj$object <- tibble::as.tibble (rbind (res$obj_rel, + obj$object <- tibble::as.tibble (rbind (res$obj_rel_memb, + res$obj_rel_kv, res$obj_way, res$obj_node)) obj$object_link_edge <- tibble::as.tibble (res$object_link_edge) diff --git a/src/osmdata-sc.cpp b/src/osmdata-sc.cpp index 5a64e1ed..c5738448 100644 --- a/src/osmdata-sc.cpp +++ b/src/osmdata-sc.cpp @@ -311,23 +311,32 @@ Rcpp::List rcpp_osmdata_sc (const std::string& st) Rcpp::Named ("val") = xml.get_way_val (), Rcpp::_["stringsAsFactors"] = false ); - Rcpp::DataFrame obj_rel = Rcpp::DataFrame::create ( + Rcpp::DataFrame obj_rel_memb = Rcpp::DataFrame::create ( + Rcpp::Named ("object_") = xml.get_rel_memb_id (), + Rcpp::Named ("type") = xml.get_rel_memb_type (), + Rcpp::Named ("ref") = xml.get_rel_ref (), + Rcpp::Named ("role") = xml.get_rel_role (), + Rcpp::_["stringsAsFactors"] = false ); + + Rcpp::DataFrame obj_rel_kv = Rcpp::DataFrame::create ( Rcpp::Named ("object_") = xml.get_rel_kv_id (), Rcpp::Named ("key") = xml.get_rel_key (), Rcpp::Named ("val") = xml.get_rel_val (), Rcpp::_["stringsAsFactors"] = false ); - Rcpp::List ret (6); + Rcpp::List ret (7); ret [0] = vertex; ret [1] = edge; ret [2] = oXe; ret [3] = obj_node; ret [4] = obj_way; - ret [5] = obj_rel; + ret [5] = obj_rel_memb; + ret [6] = obj_rel_kv; std::vector retnames {"vertex", "edge", "object_link_edge", - "obj_node", "obj_way", "obj_rel"}; + "obj_node", "obj_way", + "obj_rel_memb", "obj_rel_kv"}; ret.attr ("names") = retnames; return ret; diff --git a/src/osmdata-sc.h b/src/osmdata-sc.h index 79420610..cc06fca3 100644 --- a/src/osmdata-sc.h +++ b/src/osmdata-sc.h @@ -109,10 +109,6 @@ class XmlDataSC zeroCounters (counters); getSizes (p->first_node ()); vectorsResize (vectors, counters); - Rcpp::Rcout << "n(nodes, ways, rels, edges) = (" << counters.nnodes << ", " << - counters.nways << ", " << counters.nrels << ", " << counters.nedges << "); kv = (" << - counters.nnode_kv << ", " << counters.nway_kv << ", " << counters.nrel_kv << ")" << - std::endl; zeroCounters (counters); traverseWays (p->first_node ()); @@ -133,13 +129,16 @@ class XmlDataSC const std::vector & get_rel_kv_id() const { return vectors.rel_kv_id; } const std::vector & get_rel_key() const { return vectors.rel_key; } const std::vector & get_rel_val() const { return vectors.rel_val; } + const std::vector & get_rel_memb_id() const { return vectors.rel_memb_id; } const std::vector & get_rel_memb_type() const { return vectors.rel_memb_type; } const std::vector & get_rel_ref() const { return vectors.rel_ref; } const std::vector & get_rel_role() const { return vectors.rel_role; } + const std::vector & get_way_id() const { return vectors.way_id; } const std::vector & get_way_key() const { return vectors.way_key; } const std::vector & get_way_val() const { return vectors.way_val; } + const std::vector & get_node_id() const { return vectors.node_id; } const std::vector & get_node_key() const { return vectors.node_key; } const std::vector & get_node_val() const { return vectors.node_val; } @@ -167,8 +166,8 @@ class XmlDataSC void traverseWays (XmlNodePtr pt); // The primary function - void traverseRelation (XmlNodePtr pt); - void traverseWay (XmlNodePtr pt, int& node_num); + void traverseRelation (XmlNodePtr pt, std::string &id); + void traverseWay (XmlNodePtr pt, int& node_num, std::string& id); void traverseNode (XmlNodePtr pt); }; // end Class::XmlDataSC @@ -345,7 +344,7 @@ inline void XmlDataSC::countNode (XmlNodePtr pt) inline void XmlDataSC::traverseWays (XmlNodePtr pt) { - RawWay rway; + std::string this_id; for (XmlNodePtr it = pt->first_node (); it != nullptr; it = it->next_sibling()) @@ -365,13 +364,12 @@ inline void XmlDataSC::traverseWays (XmlNodePtr pt) } else if (!strcmp (it->name(), "way")) { int node_num = 0; - traverseWay (it, node_num); - counters.nedges--; + traverseWay (it, node_num, this_id); counters.nways++; } else if (!strcmp (it->name(), "relation")) { - traverseRelation (it); + traverseRelation (it, this_id); counters.nrels++; } else @@ -391,22 +389,27 @@ inline void XmlDataSC::traverseWays (XmlNodePtr pt) ************************************************************************ ************************************************************************/ -inline void XmlDataSC::traverseRelation (XmlNodePtr pt) +inline void XmlDataSC::traverseRelation (XmlNodePtr pt, std::string& id) { for (XmlAttrPtr it = pt->first_attribute (); it != nullptr; it = it->next_attribute()) { if (!strcmp (it->name(), "id")) { - vectors.rel_kv_id [counters.nrel_kv] = it->value(); - vectors.rel_memb_id [counters.nrel_memb] = it->value(); + // These values are always first, so all other clauses are executed + // after this one + id = it->value(); } else if (!strcmp (it->name(), "k")) + { + vectors.rel_kv_id [counters.nrel_kv] = id; vectors.rel_key [counters.nrel_kv] = it->value(); - else if (!strcmp (it->name(), "v")) + } else if (!strcmp (it->name(), "v")) vectors.rel_val [counters.nrel_kv++] = it->value(); else if (!strcmp (it->name(), "type")) + { vectors.rel_memb_type [counters.nrel_memb] = it->value(); - else if (!strcmp (it->name(), "ref")) + vectors.rel_memb_id [counters.nrel_memb] = id; + } else if (!strcmp (it->name(), "ref")) vectors.rel_ref [counters.nrel_memb] = it->value(); else if (!strcmp (it->name(), "role")) vectors.rel_role [counters.nrel_memb++] = it->value(); @@ -414,7 +417,7 @@ inline void XmlDataSC::traverseRelation (XmlNodePtr pt) // allows for >1 child nodes for (XmlNodePtr it = pt->first_node(); it != nullptr; it = it->next_sibling()) { - traverseRelation (it); + traverseRelation (it, id); } } // end function XmlDataSC::traverseRelation @@ -427,18 +430,22 @@ inline void XmlDataSC::traverseRelation (XmlNodePtr pt) ************************************************************************ ************************************************************************/ -inline void XmlDataSC::traverseWay (XmlNodePtr pt, int& node_num) +inline void XmlDataSC::traverseWay (XmlNodePtr pt, int& node_num, + std::string& id) { for (XmlAttrPtr it = pt->first_attribute (); it != nullptr; it = it->next_attribute()) { if (!strcmp (it->name(), "id")) { - vectors.way_id [counters.nway_kv] = it->value(); - vectors.object [counters.nedges] = it->value(); + // These values are always first, so all other clauses are executed + // after this one + id = it->value(); } else if (!strcmp (it->name(), "k")) + { + vectors.way_id [counters.nway_kv] = id; vectors.way_key [counters.nway_kv] = it->value(); - else if (!strcmp (it->name(), "v")) + } else if (!strcmp (it->name(), "v")) vectors.way_val [counters.nway_kv++] = it->value(); else if (!strcmp (it->name(), "ref")) { @@ -447,10 +454,15 @@ inline void XmlDataSC::traverseWay (XmlNodePtr pt, int& node_num) else { vectors.vx1 [counters.nedges] = it->value(); + vectors.object [counters.nedges] = id; vectors.edge [counters.nedges] = random_id (10); - if (node_num != waySizes.at (counters.nways)) - vectors.vx0 [counters.nedges + 1] = it->value(); counters.nedges++; + // TODO: Very last value has nedges > vx0.size() - why? + if (node_num < waySizes.at (counters.nways) & + counters.nedges < vectors.vx0.size ()) + { + vectors.vx0 [counters.nedges] = it->value(); + } } node_num++; } @@ -459,7 +471,7 @@ inline void XmlDataSC::traverseWay (XmlNodePtr pt, int& node_num) // allows for >1 child nodes for (XmlNodePtr it = pt->first_node(); it != nullptr; it = it->next_sibling()) { - traverseWay (it, node_num); + traverseWay (it, node_num, id); } } // end function XmlDataSC::traverseWay @@ -489,6 +501,7 @@ inline void XmlDataSC::traverseNode (XmlNodePtr pt) { vectors.node_val [counters.nnode_kv] = it->value(); vectors.node_id [counters.nnode_kv] = vectors.vert_id [counters.nnodes]; // will always be pre-set + counters.nnode_kv++; } } // allows for >1 child nodes