From ac3b67b9b03993d949764350e9687c435d05d18f Mon Sep 17 00:00:00 2001 From: David Date: Sun, 19 Apr 2020 19:03:19 +1000 Subject: [PATCH] starting interleaving #78 --- R/RcppExports.R | 4 + inst/include/sfheaders/df/sfc.hpp | 6 -- .../sfheaders/interleave/interleave.hpp | 78 +++++++++++++++++++ src/RcppExports.cpp | 12 +++ src/interleave.cpp | 70 +++++++++++++++++ 5 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 inst/include/sfheaders/interleave/interleave.hpp create mode 100644 src/interleave.cpp diff --git a/R/RcppExports.R b/R/RcppExports.R index ffb204a..d5530d2 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -29,6 +29,10 @@ rcpp_cast_sf <- function(sf, cast_to, close = TRUE) { .Call(`_sfheaders_rcpp_cast_sf`, sf, cast_to, close) } +rcpp_interleave <- function(sfc) { + .Call(`_sfheaders_rcpp_interleave`, sfc) +} + rcpp_fill_list <- function(v, line_ids) { .Call(`_sfheaders_rcpp_fill_list`, v, line_ids) } diff --git a/inst/include/sfheaders/df/sfc.hpp b/inst/include/sfheaders/df/sfc.hpp index 0b348c3..27fdccd 100644 --- a/inst/include/sfheaders/df/sfc.hpp +++ b/inst/include/sfheaders/df/sfc.hpp @@ -293,9 +293,6 @@ namespace df { columns[ M_COLUMN ] = true; } - // Rcpp::Rcout << "dim: " << dim << std::endl; - // Rcpp::Rcout << "columns: " << columns << std::endl; - sfg_class = cls[1]; sfg_type = get_sfg_type( sfg_class ); sfg_column_idx = get_sfg_column_index( sfg_class ); @@ -355,9 +352,6 @@ namespace df { R_xlen_t i; std::string dim; - - // TODO: change this - // needs to be dependant on 'dim' Rcpp::StringVector col_names = {"sfg_id","point_id","x","y","z","m"}; Rcpp::NumericVector x( total_coordinates, Rcpp::NumericVector::get_na() ); diff --git a/inst/include/sfheaders/interleave/interleave.hpp b/inst/include/sfheaders/interleave/interleave.hpp new file mode 100644 index 0000000..e635ae1 --- /dev/null +++ b/inst/include/sfheaders/interleave/interleave.hpp @@ -0,0 +1,78 @@ +#ifndef R_SFHEADERS_INTERLEAVE_H +#define R_SFHEADERS_INTERLEAVE_H + +#include "sfheaders/df/sfc.hpp" +#include + +namespace sfheaders { +namespace interleave { + + template < int RTYPE > + inline SEXP interleave( Rcpp::Matrix< RTYPE >& mat ) { + R_xlen_t n_col = mat.ncol(); + R_xlen_t n_row = mat.nrow(); + Rcpp::Vector< RTYPE > res( n_col * n_row ); + R_xlen_t i, j; + for( i = 0; i < n_row; ++i ) { + for( j = 0; j < n_col; ++j ) { + res[ j ] = mat( i, j ); + } + } + return res; + } + + inline SEXP interleave( Rcpp::List& lst) { + R_xlen_t i; + R_xlen_t n = lst.length(); + + + Rcpp::NumericMatrix sfc_coordinates = sfheaders::df::sfc_n_coordinates( lst ); + R_xlen_t n_geometries = sfc_coordinates.nrow(); + R_xlen_t total_coordinates = sfc_coordinates( n_geometries - 1 , 1 ); + total_coordinates = total_coordinates + 1; + + //Rcpp::Rcout << "sfc_coordinates: " << sfc_coordinates << std::endl; + + for( i = 0; i < n; ++i ) { + //SEXP sfg = sfc[ i ]; + + } + return Rcpp::List::create(); + } + + inline SEXP interleave( SEXP& sfg ) { + switch( TYPEOF ( sfg ) ) { + case INTSXP: { + if( Rf_isMatrix( sfg ) ) { + Rcpp::IntegerMatrix im = Rcpp::as< Rcpp::IntegerMatrix >( sfg ); + return interleave( im ); + } else { + return sfg; // it's already a vector + } + } + case REALSXP: { + if( Rf_isMatrix( sfg ) ) { + Rcpp::NumericMatrix im = Rcpp::as< Rcpp::NumericMatrix >( sfg ); + return interleave( im ); + } else { + return sfg; // it's already a vector + } + } + case VECSXP: { + if( Rf_isNewList( sfg ) ) { + Rcpp::List lst = Rcpp::as< Rcpp::List >( sfg ); + return interleave( lst ); + } + } + default: { + Rcpp::stop("sfheaders - can not interleave this type of object"); + } + } + return Rcpp::List::create(); + } + +} // interleave +} // sfheaders + + +#endif diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 8f92730..4662c9c 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -90,6 +90,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// rcpp_interleave +SEXP rcpp_interleave(Rcpp::List sfc); +RcppExport SEXP _sfheaders_rcpp_interleave(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)); + 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 +845,7 @@ 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", (DL_FUNC) &_sfheaders_rcpp_interleave, 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 new file mode 100644 index 0000000..08bd2ad --- /dev/null +++ b/src/interleave.cpp @@ -0,0 +1,70 @@ +#include +#include "sfheaders/df/sfc.hpp" +#include "sfheaders/interleave/interleave.hpp" + + +void interleave_geometry(SEXP& sfg, Rcpp::NumericVector& res, R_xlen_t& coordinate_counter ) { + +} + +// [[Rcpp::export]] +SEXP rcpp_interleave( Rcpp::List sfc ) { + + // the input will be a long data.frame + // or an sf object + // if it's a data.frame, it needs id columns and geometry columns + // can probably do this one later? + // and focus on the 'sf', because it doesn't need any extra headers / thought / logic + + //Rcpp::NumericMatrix sfc_coordinates = sfheaders::df::sfc_n_coordinates( sfc ); + + //return sfc_coordinates; + + // the STRIDE depends on the dimension being the same for every pair of coordinates + + + Rcpp::CharacterVector cls; + std::string dim_expected; + std::string dim; + + R_xlen_t n = sfc.length(); + R_xlen_t i; + Rcpp::IntegerVector n_coordinates( n ); + R_xlen_t sfg_count = 0; // move outside loop so it's cumulative + for( i = 0; i < n; ++i ) { + SEXP sfg = sfc[ i ]; + + cls = sfheaders::utils::getSfgClass( sfg ); + if( i == 0 ) { + dim_expected = cls[0]; + } else { + dim = cls[0]; + if ( dim != dim_expected ) { + Rcpp::stop("sfheaders - interleaving only works when all geometries have the same dimension (XY(Z(M)))"); + } + } + + n_coordinates[ i ] = sfg_count; + sfheaders::df::sfg_n_coordinates( sfg, sfg_count ); + } + // the last iteration gives the total number of coordinates + // which will be the length of the vector (* stride (dim) ); + Rcpp::Rcout << "total coordinates: " << sfg_count << std::endl; + + int stride = ( dim_expected == "XYZ" || dim_expected == "XYM" ? 3 : ( dim_expected == "XYZM" ? 4 : 2 ) ); + R_xlen_t total_coordinates = sfg_count * stride; + Rcpp::NumericVector res( total_coordinates ); + R_xlen_t coordinate_counter = 0; + // now fill this vector with all the coorinates from the coordinates + for( i = 0; i < n; ++i ) { + SEXP sfg = sfc[ i ]; + // depending on the GEOMETRY + // get each coordinate + // do I iterate each row? + SEXP temp = sfheaders::interleave::interleave( sfg ); + } + + return res; +} + +