diff --git a/R/RcppExports.R b/R/RcppExports.R index ffb204a..b403a44 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -29,6 +29,14 @@ rcpp_cast_sf <- function(sf, cast_to, close = TRUE) { .Call(`_sfheaders_rcpp_cast_sf`, sf, cast_to, close) } +rcpp_interleave_sfc <- function(sfc) { + .Call(`_sfheaders_rcpp_interleave_sfc`, sfc) +} + +rcpp_interleave_sf <- function(sf) { + .Call(`_sfheaders_rcpp_interleave_sf`, sf) +} + rcpp_fill_list <- function(v, line_ids) { .Call(`_sfheaders_rcpp_fill_list`, v, line_ids) } diff --git a/inst/include/sfheaders/interleave/interleave.hpp b/inst/include/sfheaders/interleave/interleave.hpp index d78df38..299b767 100644 --- a/inst/include/sfheaders/interleave/interleave.hpp +++ b/inst/include/sfheaders/interleave/interleave.hpp @@ -3,6 +3,7 @@ #include #include "sfheaders/df/sfc.hpp" +#include "sfheaders/df/sf.hpp" #include "sfheaders/utils/lists/list.hpp" namespace sfheaders { @@ -66,7 +67,11 @@ namespace interleave { } - inline SEXP interleave( Rcpp::List& sfc ) { + // TODO: unlist - to unlist some columns (like 'stroke_colour') + inline SEXP interleave( + Rcpp::List& sfc, + R_xlen_t& total_coordinates + ) { // the input will be a long data.frame // or an sf object @@ -82,11 +87,10 @@ namespace interleave { R_xlen_t n = sfc.length(); R_xlen_t i; - int stride = ( dim_expected == "XYZ" || dim_expected == "XYM" ? 3 : ( dim_expected == "XYZM" ? 4 : 2 ) ); - - R_xlen_t total_coordinates = 0; + //R_xlen_t total_coordinates = 0; Rcpp::List res_list( sfc.size() ); Rcpp::List res_indices( sfc.size() ); + Rcpp::IntegerVector sfg_coordinates( sfc.size() ); for( i = 0; i < n; ++i ) { @@ -106,7 +110,12 @@ namespace interleave { R_xlen_t n_geometries = coords.nrow(); R_xlen_t n_coordinates = coords( n_geometries - 1, 1 ); - n_coordinates = n_coordinates + 1; + + // n_coordinates is the total number of coordinates for the given sfg + // this is what the data needs to be expanded by. + //n_coordinates = n_coordinates + 1; + sfg_coordinates[ i ] = n_coordinates; + Rcpp::IntegerVector start_indices = coords( Rcpp::_, 0 ); start_indices = start_indices + total_coordinates; @@ -116,36 +125,72 @@ namespace interleave { total_coordinates = total_coordinates + n_coordinates; } - // TODO: expand the property columns - // Rcpp::NumericVector expanded_index( total_coordinates ); - // R_xlen_t n_col = sf.ncol(); - // Rcpp::CharacterVector sf_names = sf.names(); - // R_xlen_t name_position = 0; - // for( i = 0; i < n_col; ++i ) { - // - // if( sf_names[ i ] != geom_column ) { - // - // res_names[ name_position ] = sf_names[ i ]; - // SEXP v = sf[ i ]; - // expand_vector( res, v, expanded_index, name_position ); - // name_position += 1; - // } - // } + int stride = ( dim_expected == "XYZ" || dim_expected == "XYM" ? 3 : ( dim_expected == "XYZM" ? 4 : 2 ) ); return Rcpp::List::create( Rcpp::_["coordinates"] = sfheaders::utils::unlist_list( res_list ), Rcpp::_["start_indices"] = sfheaders::utils::unlist_list( res_indices ), + Rcpp::_["n_coordinates"] = sfg_coordinates, + Rcpp::_["total_coordinates"] = total_coordinates, Rcpp::_["stride"] = stride ); } + inline SEXP interleave( Rcpp::List& sfc ) { + R_xlen_t total_coordinates = 0; + return interleave( sfc, total_coordinates ); + } + // interleaves an `sf` object inline Rcpp::List interleave( Rcpp::DataFrame& sf ) { // and expand rows - std::string sfc_col = sf.attr("sf_column"); - Rcpp::List sfc = sf[ sfc_col ]; + std::string geom_column = sf.attr("sf_column"); + Rcpp::CharacterVector sf_names = sf.names(); + Rcpp::List sfc = sf[ geom_column ]; + R_xlen_t n_col = sf.ncol(); + R_xlen_t n_geometries = sf.nrow(); + R_xlen_t i; + R_xlen_t j; + + R_xlen_t total_coordinates = 0; + Rcpp::List interleaved = interleave( sfc, total_coordinates ); + Rcpp::IntegerVector n_coordinates = interleaved["n_coordinates"]; + + Rcpp::NumericVector expanded_index( total_coordinates ); + R_xlen_t counter = 0; + + for( i = 0; i < n_geometries; ++i ) { + R_xlen_t expand_by = n_coordinates[ i ]; + + for( j = 0; j < expand_by; ++j ) { + expanded_index[ counter + j ] = i; + } + counter = counter + expand_by; + } + + Rcpp::List res( n_col - 1 ); + Rcpp::StringVector res_names( n_col - 1 ); + + R_xlen_t name_position = 0; + + for( i = 0; i < n_col; ++i ) { + + if( sf_names[ i ] != geom_column ) { + + res_names[ name_position ] = sf_names[ i ]; + SEXP v = sf[ i ]; + sfheaders::df::expand_vector( res, v, expanded_index, name_position ); + name_position += 1; + } + } + + //res.names() = res_names; + Rcpp::DataFrame df = sfheaders::utils::make_dataframe( res, total_coordinates, res_names ); + // construct final object + interleaved["data"] = df; + return interleaved; } diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 8f92730..f4cc2d0 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -90,6 +90,28 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// rcpp_interleave_sfc +SEXP rcpp_interleave_sfc(Rcpp::List sfc); +RcppExport SEXP _sfheaders_rcpp_interleave_sfc(SEXP sfcSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP); + rcpp_result_gen = Rcpp::wrap(rcpp_interleave_sfc(sfc)); + return rcpp_result_gen; +END_RCPP +} +// rcpp_interleave_sf +SEXP rcpp_interleave_sf(Rcpp::DataFrame sf); +RcppExport SEXP _sfheaders_rcpp_interleave_sf(SEXP sfSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< Rcpp::DataFrame >::type sf(sfSEXP); + rcpp_result_gen = Rcpp::wrap(rcpp_interleave_sf(sf)); + return rcpp_result_gen; +END_RCPP +} // rcpp_fill_list Rcpp::List rcpp_fill_list(Rcpp::NumericVector v, Rcpp::IntegerMatrix line_ids); RcppExport SEXP _sfheaders_rcpp_fill_list(SEXP vSEXP, SEXP line_idsSEXP) { @@ -834,6 +856,8 @@ static const R_CallMethodDef CallEntries[] = { {"_sfheaders_rcpp_count_new_sfc_objects", (DL_FUNC) &_sfheaders_rcpp_count_new_sfc_objects, 2}, {"_sfheaders_rcpp_cast_sfc", (DL_FUNC) &_sfheaders_rcpp_cast_sfc, 3}, {"_sfheaders_rcpp_cast_sf", (DL_FUNC) &_sfheaders_rcpp_cast_sf, 3}, + {"_sfheaders_rcpp_interleave_sfc", (DL_FUNC) &_sfheaders_rcpp_interleave_sfc, 1}, + {"_sfheaders_rcpp_interleave_sf", (DL_FUNC) &_sfheaders_rcpp_interleave_sf, 1}, {"_sfheaders_rcpp_fill_list", (DL_FUNC) &_sfheaders_rcpp_fill_list, 2}, {"_sfheaders_rcpp_list_sizes", (DL_FUNC) &_sfheaders_rcpp_list_sizes, 1}, {"_sfheaders_rcpp_list_type", (DL_FUNC) &_sfheaders_rcpp_list_type, 1}, diff --git a/src/interleave.cpp b/src/interleave.cpp index e350979..d246417 100644 --- a/src/interleave.cpp +++ b/src/interleave.cpp @@ -7,6 +7,15 @@ void interleave_geometry(SEXP& sfg, Rcpp::NumericVector& res, R_xlen_t& coordina } +// [[Rcpp::export]] +SEXP rcpp_interleave_sfc( Rcpp::List sfc ) { + return sfheaders::interleave::interleave( sfc ); +} + +// [[Rcpp::export]] +SEXP rcpp_interleave_sf( Rcpp::DataFrame sf ) { + return sfheaders::interleave::interleave( sf ); +} // SEXP rcpp_interleave( Rcpp::List sfc ) { //