diff --git a/DESCRIPTION b/DESCRIPTION index 1cd772a0f..516e648bf 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -15,7 +15,10 @@ SystemRequirements: C++11 Depends: R (>= 3.3.0) Imports: Rcpp (>= 0.12.13) -LinkingTo: Rcpp, BH +LinkingTo: + Rcpp, + BH, + sfheaders RoxygenNote: 6.1.0 Suggests: covr, diff --git a/R/Encode.R b/R/Encode.R index 784d9d640..ef6daa422 100644 --- a/R/Encode.R +++ b/R/Encode.R @@ -85,8 +85,8 @@ encode <- function(obj, ...) UseMethod("encode") encode.sf <- function(obj, strip = FALSE, ...) { geomCol <- sfGeometryColumn(obj) - lst <- rcpp_encodeSfGeometry(obj[[geomCol]], strip) - + ##lst <- rcpp_encodeSfGeometry(obj[[geomCol]], strip) + lst <- rcpp_encode_sfc( obj[[geomCol]], strip) if(!strip) sfAttrs <- sfGeometryAttributes(obj) # obj[[geomCol]] <- lst[['XY']] @@ -126,8 +126,8 @@ encode.sf <- function(obj, strip = FALSE, ...) { #' @export encode.sfc <- function(obj, strip = FALSE, ...) { - lst <- rcpp_encodeSfGeometry(obj, strip) - + ##lst <- rcpp_encodeSfGeometry(obj, strip) + lst <- rcpp_encode_sfc( obj, strip ) # ## TODO(remove this vapply step and return from rcpp a flag if the ZM attrs are attached) # if (all(vapply(lst[['ZM']], length, 0L)) == 0) { # diff --git a/R/RcppExports.R b/R/RcppExports.R index c505461e2..64ddfaa7d 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -1,8 +1,8 @@ # Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 -rcpp_encodeSfGeometry <- function(sfc, strip) { - .Call('_googlePolylines_rcpp_encodeSfGeometry', PACKAGE = 'googlePolylines', sfc, strip) +rcpp_encode_sfc <- function(sfc, strip) { + .Call('_googlePolylines_rcpp_encode_sfc', PACKAGE = 'googlePolylines', sfc, strip) } rcpp_decode_polyline_list <- function(encodedList, attribute) { diff --git a/inst/include/googlePolylines.h b/inst/include/googlePolylines.h index 5b429d03f..960b3e7e7 100644 --- a/inst/include/googlePolylines.h +++ b/inst/include/googlePolylines.h @@ -39,7 +39,7 @@ void split(const std::string &s, char delim, Out result); void split(const std::string &s, char delim); -Rcpp::CharacterVector getSfClass(SEXP sf); +//Rcpp::CharacterVector getSfClass(SEXP sf); Rcpp::List decode_polyline(std::string encoded, std::vector& col_headers, @@ -57,7 +57,7 @@ void EncodeSignedNumber(std::ostringstream& os, int num); std::string encode_polyline(); Rcpp::List decode_data(Rcpp::StringVector pl, - const char *cls = NULL); + const char *cls = NULL); namespace global_vars { diff --git a/inst/include/googlepolylines/decode.hpp b/inst/include/googlepolylines/decode.hpp new file mode 100644 index 000000000..f716f5a32 --- /dev/null +++ b/inst/include/googlepolylines/decode.hpp @@ -0,0 +1,51 @@ +#ifndef R_GOOGLEPOLYLINES_DECODE_H +#define R_GOOGLEPOLYLINES_DECODE_H + +namespace googlepolylines { +namespace decode { + + inline void decode( + std::string& encoded, + std::vector& pointsLat, + std::vector& pointsLon + ) { + + R_xlen_t len = encoded.size(); + R_xlen_t index = 0; + float lat = 0; + float lng = 0; + + pointsLat.clear(); + pointsLon.clear(); + + while (index < len){ + char b; + unsigned int shift = 0; + int result = 0; + do { + b = encoded.at(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + float dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lat += dlat; + + shift = 0; + result = 0; + do { + b = encoded.at(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + float dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lng += dlng; + + pointsLat.push_back(lat * (float)1e-5); + pointsLon.push_back(lng * (float)1e-5); + } + } + +} // decode +} // googlepolylines + +#endif \ No newline at end of file diff --git a/inst/include/googlepolylines/encode.hpp b/inst/include/googlepolylines/encode.hpp new file mode 100644 index 000000000..0c6e0c34d --- /dev/null +++ b/inst/include/googlepolylines/encode.hpp @@ -0,0 +1,253 @@ +#ifndef R_GOOGLEPOLYLINES_ENCODE_H +#define R_GOOGLEPOLYLINES_ENCODE_H + +#include +#include "googlepolylines/googlepolylines.h" + +#include "sfheaders/df/sfg.hpp" + +namespace googlepolylines { +namespace encode { + + // inline void add_to_stream( + // std::ostringstream& os, + // std::string& encoded_string + // ) { + // os << encoded_string << ' '; + // } + + inline void encode_number( + std::ostringstream& os, + int num + ) { + + std::string out_str; + + while(num >= 0x20){ + out_str += (char)(0x20 | (int)(num & 0x1f)) + 63; + num >>= 5; + } + + out_str += char(num + 63); + os << out_str; + } + + inline void encode_signed_number( + std::ostringstream& os, + int num + ) { + + unsigned int ui = num; //3 + ui <<= 1; //4 + ui = (num < 0) ? ~ui : ui; //5 + encode_number(os, ui); + } + + inline void encode( + Rcpp::NumericVector& lons, + Rcpp::NumericVector& lats, + std::ostringstream& os + ) { + int plat = 0; + int plon = 0; + int late5; + int lone5; + + R_xlen_t i; + R_xlen_t n = lats.size(); + + for( i = 0; i < n; i++){ + + late5 = lats[ i ] * 1e5; + lone5 = lons[ i ] * 1e5; + + encode_signed_number(os, late5 - plat); + encode_signed_number(os, lone5 - plon); + + plat = late5; + plon = lone5; + } + } + + inline std::string encode( + Rcpp::NumericVector& lons, + Rcpp::NumericVector& lats + ) { + std::ostringstream os; + encode( lons, lats, os ); + Rcpp::Rcout << "os" << os.str() << std::endl; + return os.str(); + } + + inline std::string encode( + Rcpp::NumericMatrix& mat + ) { + if( mat.ncol() < 2 ) { + Rcpp::stop("googlepolylines - expecting at least 2 columns in a matrix"); + } + + Rcpp::Rcout << "n_row: " << mat.nrow() << std::endl; + + Rcpp::NumericVector lons = mat( Rcpp::_, 0 ); + Rcpp::NumericVector lats = mat( Rcpp::_, 1 ); + return encode( lons, lats ); + } + + // encode sfg objects + inline std::string encode_point( + Rcpp::NumericVector& sfg + ) { + + //Rcpp::DataFrame df = sfheaders::df::sfg_to_df(sfg); + // but I don't know what type of sfg it is yet... + + if( sfg.length() < 2 ) { + Rcpp::stop("googlepolylines - not enough values in a point"); + } + Rcpp::NumericVector lons(1); + Rcpp::NumericVector lats(1); + lons[0] = sfg[0]; + lats[0] = sfg[1]; + return encode( lons, lats ); + } + + inline Rcpp::StringVector encode_multipoint( + Rcpp::NumericMatrix& sfg + ) { + + if( sfg.ncol() < 2 ) { + Rcpp::stop("googlepolylines - not enough columns in the matrix"); + } + R_xlen_t n = sfg.nrow(); + Rcpp::Rcout << "n: " << n << std::endl; + R_xlen_t i; + Rcpp::StringVector res( n ); + for( i = 0; i < n; ++i ) { + double lon = sfg( i, 0 ); + double lat = sfg( i, 1 ); + Rcpp::NumericVector lons(1); + Rcpp::NumericVector lats(1); + lons[0] = lon; + lats[0] = lat; + res[i] = encode( lons, lats ); + } + return res; + } + + inline Rcpp::StringVector encode_linestring( + Rcpp::NumericMatrix& sfg + ) { + + R_xlen_t n = sfg.nrow(); + if( n == 0 ) { + return Rcpp::StringVector::create(); + } + return encode( sfg ); + } + + inline Rcpp::StringVector encode_multilinestring( + Rcpp::List& sfg + ) { + int n = sfg.length(); + int i; + Rcpp::StringVector res( n ); + + for( i = 0; i < n; ++i ) { + Rcpp::NumericMatrix line = sfg[ i ]; + res[ i ] = encode( line ); + } + return res; + } + + inline Rcpp::StringVector encode_polygon( + Rcpp::List& sfg + ) { + return encode_multilinestring( sfg ); + } + + inline Rcpp::StringVector encode_multipolygon( + Rcpp::List& sfg + ) { + + int n = sfg.length(); + int i, j; + Rcpp::List polygons( n ); + int line_counter = 0; + + for( i = 0; i < n; ++i ) { + Rcpp::List polygon = sfg[ i ]; + polygons[ i ] = encode_polygon( polygon ); + line_counter = line_counter + polygon.size() + 1; // to add the SPLIT_CHAR "-" to separate polygons + } + + Rcpp::StringVector res( line_counter ); + // unpack the polygon list + int counter = 0; + for( i = 0; i < polygons.size(); ++i ) { + Rcpp::List poly = polygons[ i ]; + for( j = 0; j < poly.size(); ++j ) { + std::string line = poly[ j ]; + res[ counter ] = line; + counter = counter + 1; + } + res[ counter ] = SPLIT_CHAR; + counter = counter + 1; + } + + // remove the final SPLIT_CHAR + res.erase( line_counter - 1 ); + + //return polygons; + return res; + } + + inline Rcpp::List encode_sfc( + Rcpp::List& sfc + ) { + // Rcpp::Rcout << "encode_sfc " << std::endl; + R_xlen_t n = sfc.size(); + R_xlen_t i; + Rcpp::List res( n ); + Rcpp::CharacterVector cls; + std::string geometry; + + // Rcpp::Rcout << "n: " << n << std::endl; + + for( i = 0; i < n; ++i ) { + + SEXP sfg = sfc[ i ]; + cls = sfheaders::df::getSfgClass( sfg ); + geometry = cls[1]; + + // Rcpp::Rcout << "geometry: " << geometry << std::endl; + + if( geometry == "POINT" ) { + Rcpp::NumericVector nv = Rcpp::as< Rcpp::NumericVector >( sfg ); + res[i] = encode_point( nv ); + } else if ( geometry == "MULTIPOINT" ) { + Rcpp::NumericMatrix nm = Rcpp::as< Rcpp::NumericMatrix >( sfg ); + res[i] = encode_multipoint( nm ); + } else if ( geometry == "LINESTRING" ) { + Rcpp::NumericMatrix nm = Rcpp::as< Rcpp::NumericMatrix >( sfg ); + res[i] = encode_linestring( nm ); + } else if ( geometry == "MULTILINESTRING" ) { + Rcpp::List mls = Rcpp::as< Rcpp::List >( sfg ); + res[i] = encode_multilinestring( mls ); + } else if ( geometry == "POLYGON" ) { + Rcpp::List pl = Rcpp::as< Rcpp::List >( sfg ); + res[i] = encode_polygon( pl ); + } else if ( geometry == "MULTIPOLYGON" ) { + Rcpp::List mpl = Rcpp::as< Rcpp::List >( sfg ); + res[i] = encode_multipolygon( mpl ); + } else { + Rcpp::stop("googlepolylines - unknown sfg type"); + } + } + return res; + } + + +} // encode +} // googlepolylines + +#endif \ No newline at end of file diff --git a/inst/include/googlepolylines/googlepolylines.h b/inst/include/googlepolylines/googlepolylines.h new file mode 100644 index 000000000..2bfdc83cf --- /dev/null +++ b/inst/include/googlepolylines/googlepolylines.h @@ -0,0 +1,35 @@ + +#ifndef GOOGLEPOLYLINES_H +#define GOOGLEPOLYLINES_H + +#include + +#define SF_Unknown 0 +#define SF_Point 1 +#define SF_LineString 2 +#define SF_Polygon 3 +#define SF_MultiPoint 4 +#define SF_MultiLineString 5 +#define SF_MultiPolygon 6 +#define SF_GeometryCollection 7 +#define SF_CircularString 8 +#define SF_CompoundCurve 9 +#define SF_CurvePolygon 10 +#define SF_MultiCurve 11 +#define SF_MultiSurface 12 +#define SF_Curve 13 +#define SF_Surface 14 +#define SF_PolyhedralSurface 15 +#define SF_TIN 16 +#define SF_Triangle 17 +#define SF_Geometry 18 + +#define SPLIT_CHAR "-" + +#define XYUNKNOWN 0 +#define XY 2 +#define XYZ 3 +#define XYM 3 +#define XYZM 4 + +#endif \ No newline at end of file diff --git a/inst/include/googlepolylines/sf.hpp b/inst/include/googlepolylines/sf.hpp new file mode 100644 index 000000000..e8ae690e6 --- /dev/null +++ b/inst/include/googlepolylines/sf.hpp @@ -0,0 +1,63 @@ + +#ifndef R_GOOGLEPOLYLINES_SF_H +#define R_GOOGLEPOLYLINES_SF_H + +#include "googlepolylines/googlepolylines.h" + +namespace googlepolylines { +namespace sf { + + inline void make_dim_divisor( + const char *cls, + int *d + ) { + int divisor = 2; + if (strcmp(cls, "XY") == 0) + divisor = XY; + else if (strcmp(cls, "XYZ") == 0) + divisor = XYZ; + else if (strcmp(cls, "XYM") == 0) + divisor = XYM; + else if (strcmp(cls, "XYZM") == 0) + divisor = XYZM; + else + Rcpp::stop("Unknown dimension attribute"); + *d = divisor; + } + + inline void make_type( + const char *cls, + int *tp = NULL, + int srid = 0 + ) { + int type = 0; + if (strstr(cls, "sfc_") == cls) + cls += 4; + if (strcmp(cls, "POINT") == 0) + type = SF_Point; + else if (strcmp(cls, "MULTIPOINT") == 0) + type = SF_MultiPoint; + else if (strcmp(cls, "LINESTRING") == 0) + type = SF_LineString; + else if (strcmp(cls, "POLYGON") == 0) + type = SF_Polygon; + else if (strcmp(cls, "MULTILINESTRING") == 0) + type = SF_MultiLineString; + else if (strcmp(cls, "MULTIPOLYGON") == 0) + type = SF_MultiPolygon; + else if (strcmp(cls, "GEOMETRY") == 0) + type = SF_Geometry; + else if (strcmp(cls, "GEOMETRYCOLLECTION") == 0) + type = SF_GeometryCollection; + else + type = SF_Unknown; + if (tp != NULL) + *tp = type; + // Rcpp::Rcout << "type: " << type << std::endl; + //return type; + } + +} // sf +} // googlepolylines + +#endif \ No newline at end of file diff --git a/inst/include/googlepolylines/utils.hpp b/inst/include/googlepolylines/utils.hpp new file mode 100644 index 000000000..37c944353 --- /dev/null +++ b/inst/include/googlepolylines/utils.hpp @@ -0,0 +1,25 @@ +#ifndef R_GOOGLEPOLYLINES_UTILS_H +#define R_GOOGLEPOLYLINES_UTILS_H + +namespace googlepolylines { +namespace utils { + +// template +// inline void split(const std::string &s, char delim, Out result) { +// std::stringstream ss(s); +// std::string item; +// while (std::getline(ss, item, delim)) { +// *(result++) = item; +// } +// } +// +// inline void split(const std::string &s, char delim, std::vector< std::string >& elems ) { +// //global_vars::elems.clear(); +// split(s, delim, std::back_inserter( elems ) ); +// } + +} // utils +} // googlepolylines + + +#endif \ No newline at end of file diff --git a/src/Makevars b/src/Makevars index 972ca0cf3..393b500d6 100644 --- a/src/Makevars +++ b/src/Makevars @@ -1,3 +1,4 @@ CXX_STD = CXX11 -PKG_CPPFLAGS = -I../inst/include \ No newline at end of file +PKG_CXXFLAGS = -I../inst/include +PKG_CPPFLAGS = -DSTRICT_R_HEADERS -DBOOST_NO_AUTO_PTR \ No newline at end of file diff --git a/src/Makevars.win b/src/Makevars.win index 972ca0cf3..27e9f2a7a 100644 --- a/src/Makevars.win +++ b/src/Makevars.win @@ -1,3 +1,4 @@ CXX_STD = CXX11 -PKG_CPPFLAGS = -I../inst/include \ No newline at end of file +PKG_CXXFLAGS = -I../inst/include +PKG_CPPFLAGS=-DSTRICT_R_HEADERS -DBOOST_NO_AUTO_PTR \ No newline at end of file diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 45fd2011f..0593db76f 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -6,15 +6,15 @@ using namespace Rcpp; -// rcpp_encodeSfGeometry -Rcpp::List rcpp_encodeSfGeometry(Rcpp::List sfc, bool strip); -RcppExport SEXP _googlePolylines_rcpp_encodeSfGeometry(SEXP sfcSEXP, SEXP stripSEXP) { +// rcpp_encode_sfc +Rcpp::List rcpp_encode_sfc(Rcpp::List& sfc, bool strip); +RcppExport SEXP _googlePolylines_rcpp_encode_sfc(SEXP sfcSEXP, SEXP stripSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP); + Rcpp::traits::input_parameter< Rcpp::List& >::type sfc(sfcSEXP); Rcpp::traits::input_parameter< bool >::type strip(stripSEXP); - rcpp_result_gen = Rcpp::wrap(rcpp_encodeSfGeometry(sfc, strip)); + rcpp_result_gen = Rcpp::wrap(rcpp_encode_sfc(sfc, strip)); return rcpp_result_gen; END_RCPP } @@ -43,19 +43,19 @@ BEGIN_RCPP END_RCPP } // rcpp_encode_polyline -std::string rcpp_encode_polyline(std::vector longitude, std::vector latitude); +std::string rcpp_encode_polyline(Rcpp::NumericVector longitude, Rcpp::NumericVector latitude); RcppExport SEXP _googlePolylines_rcpp_encode_polyline(SEXP longitudeSEXP, SEXP latitudeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< std::vector >::type longitude(longitudeSEXP); - Rcpp::traits::input_parameter< std::vector >::type latitude(latitudeSEXP); + Rcpp::traits::input_parameter< Rcpp::NumericVector >::type longitude(longitudeSEXP); + Rcpp::traits::input_parameter< Rcpp::NumericVector >::type latitude(latitudeSEXP); rcpp_result_gen = Rcpp::wrap(rcpp_encode_polyline(longitude, latitude)); return rcpp_result_gen; END_RCPP } // rcpp_encode_polyline_byrow -std::vector rcpp_encode_polyline_byrow(Rcpp::NumericVector longitude, Rcpp::NumericVector latitude); +Rcpp::StringVector rcpp_encode_polyline_byrow(Rcpp::NumericVector longitude, Rcpp::NumericVector latitude); RcppExport SEXP _googlePolylines_rcpp_encode_polyline_byrow(SEXP longitudeSEXP, SEXP latitudeSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; @@ -90,7 +90,7 @@ END_RCPP } static const R_CallMethodDef CallEntries[] = { - {"_googlePolylines_rcpp_encodeSfGeometry", (DL_FUNC) &_googlePolylines_rcpp_encodeSfGeometry, 2}, + {"_googlePolylines_rcpp_encode_sfc", (DL_FUNC) &_googlePolylines_rcpp_encode_sfc, 2}, {"_googlePolylines_rcpp_decode_polyline_list", (DL_FUNC) &_googlePolylines_rcpp_decode_polyline_list, 2}, {"_googlePolylines_rcpp_decode_polyline", (DL_FUNC) &_googlePolylines_rcpp_decode_polyline, 2}, {"_googlePolylines_rcpp_encode_polyline", (DL_FUNC) &_googlePolylines_rcpp_encode_polyline, 2}, diff --git a/src/encode.cpp b/src/encode.cpp index 16ceefc94..640aa0d67 100644 --- a/src/encode.cpp +++ b/src/encode.cpp @@ -1,25 +1,28 @@ #include -using namespace Rcpp; -#include "googlePolylines.h" -template -Rcpp::CharacterVector sfClass(Vector v) { - return v.attr("class"); -} +//#include "googlepolylines/sf.hpp" +#include "googlePolylines.h" +#include "sfheaders/sfc/sfc_attributes.hpp" +#include "googlepolylines/encode.hpp" -Rcpp::CharacterVector getSfClass(SEXP sf) { - - switch( TYPEOF(sf) ) { - case REALSXP: - return sfClass(sf); - case VECSXP: - return sfClass(sf); - case INTSXP: - return sfClass(sf); - default: Rcpp::stop("unknown sf type"); - } - return ""; -} +// template +// Rcpp::CharacterVector sfClass(Vector v) { +// return v.attr("class"); +// } +// +// Rcpp::CharacterVector getSfClass(SEXP sf) { +// +// switch( TYPEOF(sf) ) { +// case REALSXP: +// return sfClass(sf); +// case VECSXP: +// return sfClass(sf); +// case INTSXP: +// return sfClass(sf); +// default: Rcpp::stop("unknown sf type"); +// } +// return ""; +// } template @@ -36,329 +39,352 @@ void split(const std::string &s, char delim) { split(s, delim, std::back_inserter(global_vars::elems)); } +// +// void write_data(std::ostringstream& os, std::ostringstream& oszm, Rcpp::CharacterVector& sfg_dim, int dim_divisor, +// SEXP sfc, const char *cls, int srid); +// +// void write_matrix_list(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, Rcpp::CharacterVector& sfg_dim, int dim_divisor); -void write_data(std::ostringstream& os, std::ostringstream& oszm, Rcpp::CharacterVector& sfg_dim, int dim_divisor, - SEXP sfc, const char *cls, int srid); - -void write_matrix_list(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, Rcpp::CharacterVector& sfg_dim, int dim_divisor); +// void make_dim_divisor(const char *cls, int *d) { +// int divisor = 2; +// if (strcmp(cls, "XY") == 0) +// divisor = XY; +// else if (strcmp(cls, "XYZ") == 0) +// divisor = XYZ; +// else if (strcmp(cls, "XYM") == 0) +// divisor = XYM; +// else if (strcmp(cls, "XYZM") == 0) +// divisor = XYZM; +// else +// Rcpp::stop("Unknown dimension attribute"); +// *d = divisor; +// } +// +// void make_type(const char *cls, int *tp = NULL, +// int srid = 0) { +// int type = 0; +// if (strstr(cls, "sfc_") == cls) +// cls += 4; +// if (strcmp(cls, "POINT") == 0) +// type = SF_Point; +// else if (strcmp(cls, "MULTIPOINT") == 0) +// type = SF_MultiPoint; +// else if (strcmp(cls, "LINESTRING") == 0) +// type = SF_LineString; +// else if (strcmp(cls, "POLYGON") == 0) +// type = SF_Polygon; +// else if (strcmp(cls, "MULTILINESTRING") == 0) +// type = SF_MultiLineString; +// else if (strcmp(cls, "MULTIPOLYGON") == 0) +// type = SF_MultiPolygon; +// else if (strcmp(cls, "GEOMETRY") == 0) +// type = SF_Geometry; +// else if (strcmp(cls, "GEOMETRYCOLLECTION") == 0) +// type = SF_GeometryCollection; +// else +// type = SF_Unknown; +// if (tp != NULL) +// *tp = type; +// // Rcpp::Rcout << "type: " << type << std::endl; +// //return type; +// } -void make_dim_divisor(const char *cls, int *d) { - int divisor = 2; - if (strcmp(cls, "XY") == 0) - divisor = XY; - else if (strcmp(cls, "XYZ") == 0) - divisor = XYZ; - else if (strcmp(cls, "XYM") == 0) - divisor = XYM; - else if (strcmp(cls, "XYZM") == 0) - divisor = XYZM; - else - Rcpp::stop("Unknown dimension attribute"); - *d = divisor; -} - -void make_type(const char *cls, int *tp = NULL, - int srid = 0) { - int type = 0; - if (strstr(cls, "sfc_") == cls) - cls += 4; - if (strcmp(cls, "POINT") == 0) - type = SF_Point; - else if (strcmp(cls, "MULTIPOINT") == 0) - type = SF_MultiPoint; - else if (strcmp(cls, "LINESTRING") == 0) - type = SF_LineString; - else if (strcmp(cls, "POLYGON") == 0) - type = SF_Polygon; - else if (strcmp(cls, "MULTILINESTRING") == 0) - type = SF_MultiLineString; - else if (strcmp(cls, "MULTIPOLYGON") == 0) - type = SF_MultiPolygon; - else if (strcmp(cls, "GEOMETRY") == 0) - type = SF_Geometry; - else if (strcmp(cls, "GEOMETRYCOLLECTION") == 0) - type = SF_GeometryCollection; - else - type = SF_Unknown; - if (tp != NULL) - *tp = type; - // Rcpp::Rcout << "type: " << type << std::endl; - //return type; -} - -void write_multipolygon(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, Rcpp::CharacterVector& sfg_dim, int dim_divisor) { - - for (int i = 0; i < lst.length(); i++) { - write_matrix_list(os, oszm, lst[i], sfg_dim, dim_divisor); - } -} +// void write_multipolygon(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, Rcpp::CharacterVector& sfg_dim, int dim_divisor) { +// +// for (int i = 0; i < lst.length(); i++) { +// write_matrix_list(os, oszm, lst[i], sfg_dim, dim_divisor); +// } +// } void addToStream(std::ostringstream& os) { os << global_vars::encodedString << ' '; } -void encode_point( std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericVector point, Rcpp::CharacterVector& sfg_dim, int dim_divisor) { - - global_vars::lons.clear(); - global_vars::lats.clear(); - global_vars::lons.push_back(point[0]); - global_vars::lats.push_back(point[1]); - - global_vars::encodedString = encode_polyline(); - addToStream(os); - - // if ( dim_divisor > 2 ) { - // Rcpp::NumericVector elev(1); - // Rcpp::NumericVector meas(1); - // - // elev[0] = point[2]; - // if (dim_divisor == 4 ) { - // meas[0] = point[3]; - // } - // - // encodedString = encode_polyline(elev, meas); - // addToStream(oszm, encodedString); - // } - -} +// void encode_point( std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericVector point, Rcpp::CharacterVector& sfg_dim, int dim_divisor) { +// +// global_vars::lons.clear(); +// global_vars::lats.clear(); +// global_vars::lons.push_back(point[0]); +// global_vars::lats.push_back(point[1]); +// +// global_vars::encodedString = encode_polyline(); +// addToStream(os); +// +// // if ( dim_divisor > 2 ) { +// // Rcpp::NumericVector elev(1); +// // Rcpp::NumericVector meas(1); +// // +// // elev[0] = point[2]; +// // if (dim_divisor == 4 ) { +// // meas[0] = point[3]; +// // } +// // +// // encodedString = encode_polyline(elev, meas); +// // addToStream(oszm, encodedString); +// // } +// +// } -void encode_points( std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericMatrix point, - Rcpp::CharacterVector& sfg_dim, int dim_divisor) { - - int n = point.size() / dim_divisor; - global_vars::lons.clear(); - global_vars::lons.resize(1); - global_vars::lats.clear(); - global_vars::lats.resize(1); - - //Rcpp::NumericVector elev(1); - //Rcpp::NumericVector meas(1); - - for (int i = 0; i < n; i++){ - global_vars::lons[0] = point(i, 0); - global_vars::lats[0] = point(i, 1); - global_vars::encodedString = encode_polyline(); - addToStream(os); - - // if ( dim_divisor > 2 ) { - // elev[0] = point(i, 2); - // meas[0] = dim_divisor == 4 ? point(i, 3) : 0; - // - // encodedString = encode_polyline( elev, meas ); - // addToStream(oszm, encodedString); - // } - - } - -} +// void encode_points( std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericMatrix point, +// Rcpp::CharacterVector& sfg_dim, int dim_divisor) { +// +// int n = point.size() / dim_divisor; +// global_vars::lons.clear(); +// global_vars::lons.resize(1); +// global_vars::lats.clear(); +// global_vars::lats.resize(1); +// +// //Rcpp::NumericVector elev(1); +// //Rcpp::NumericVector meas(1); +// +// for (int i = 0; i < n; i++){ +// global_vars::lons[0] = point(i, 0); +// global_vars::lats[0] = point(i, 1); +// global_vars::encodedString = encode_polyline(); +// addToStream(os); +// +// // if ( dim_divisor > 2 ) { +// // elev[0] = point(i, 2); +// // meas[0] = dim_divisor == 4 ? point(i, 3) : 0; +// // +// // encodedString = encode_polyline( elev, meas ); +// // addToStream(oszm, encodedString); +// // } +// +// } +// +// } -void encode_vector( std::ostringstream& os, std::ostringstream& oszm, Rcpp::List vec, Rcpp::CharacterVector& sfg_dim, - int dim_divisor) { +// void encode_vector( std::ostringstream& os, std::ostringstream& oszm, Rcpp::List vec, Rcpp::CharacterVector& sfg_dim, +// int dim_divisor) { +// +// // - XY == [0][1] +// // - XYZ == [0][1][2]{3} +// // - XYM == [0][1][2]{3} +// // - XYZM == [0][1][2][3] +// +// int n = vec.size() / dim_divisor; +// +// global_vars::lats.clear(); +// global_vars::lons.clear(); +// +// for (int i = 0; i < n; i++) { +// global_vars::lons.push_back(vec[i]); +// global_vars::lats.push_back(vec[(i + n)]); +// } +// +// global_vars::encodedString = encode_polyline(); +// addToStream(os); +// +// // if (dim_divisor > 2) { +// // // there are Z and M attributes to encode +// // // constructor sets them to 0 +// // Rcpp::NumericVector elev(n); +// // Rcpp::NumericVector meas(n); +// // +// // for (int i = 0; i < n; i++) { +// // elev[i] = vec[(i + n + n)]; +// // meas[i] = dim_divisor == 4 ? vec[(i + n + n + n)] : 0; +// // } +// // encodedString = encode_polyline(elev, meas); +// // addToStream(oszm, encodedString); +// // } +// +// } - // - XY == [0][1] - // - XYZ == [0][1][2]{3} - // - XYM == [0][1][2]{3} - // - XYZM == [0][1][2][3] - - int n = vec.size() / dim_divisor; - - global_vars::lats.clear(); - global_vars::lons.clear(); - - for (int i = 0; i < n; i++) { - global_vars::lons.push_back(vec[i]); - global_vars::lats.push_back(vec[(i + n)]); - } - - global_vars::encodedString = encode_polyline(); - addToStream(os); - - // if (dim_divisor > 2) { - // // there are Z and M attributes to encode - // // constructor sets them to 0 - // Rcpp::NumericVector elev(n); - // Rcpp::NumericVector meas(n); - // - // for (int i = 0; i < n; i++) { - // elev[i] = vec[(i + n + n)]; - // meas[i] = dim_divisor == 4 ? vec[(i + n + n + n)] : 0; - // } - // encodedString = encode_polyline(elev, meas); - // addToStream(oszm, encodedString); - // } - -} +// void encode_vectors( std::ostringstream& os, std::ostringstream& oszm, Rcpp::List sfc, Rcpp::CharacterVector& sfg_dim, +// int dim_divisor){ +// +// size_t n = sfc.size(); +// +// for (size_t i = 0; i < n; i++) { +// encode_vector(os, oszm, sfc[i], sfg_dim, dim_divisor); +// } +// } -void encode_vectors( std::ostringstream& os, std::ostringstream& oszm, Rcpp::List sfc, Rcpp::CharacterVector& sfg_dim, - int dim_divisor){ - - size_t n = sfc.size(); - - for (size_t i = 0; i < n; i++) { - encode_vector(os, oszm, sfc[i], sfg_dim, dim_divisor); - } -} +// void encode_matrix(std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericMatrix mat, +// Rcpp::CharacterVector& sfg_dim, int dim_divisor ) { +// +// global_vars::lons.clear(); +// global_vars::lats.clear(); +// int nrow = mat.nrow(); +// for (int i = 0; i < nrow; ++i) { +// global_vars::lats.push_back(mat(i, 1)); +// global_vars::lons.push_back(mat(i, 0)); +// } +// +// global_vars::encodedString = encode_polyline(); +// addToStream(os); +// +// // if (dim_divisor > 2 ) { +// // int n = mat.size() / dim_divisor; +// // Rcpp::NumericVector elev(n); +// // Rcpp::NumericVector meas(n); +// // if( dim_divisor == 3 ) { +// // elev = mat(_, 2); +// // } else if ( dim_divisor == 4 ) { +// // elev = mat(_, 2); +// // meas = mat(_, 3); +// // } +// // encodedString = encode_polyline(elev, meas); +// // addToStream(oszm, encodedString); +// // } +// +// } -void encode_matrix(std::ostringstream& os, std::ostringstream& oszm, Rcpp::NumericMatrix mat, - Rcpp::CharacterVector& sfg_dim, int dim_divisor ) { - - global_vars::lons.clear(); - global_vars::lats.clear(); - int nrow = mat.nrow(); - for (int i = 0; i < nrow; ++i) { - global_vars::lats.push_back(mat(i, 1)); - global_vars::lons.push_back(mat(i, 0)); - } - - global_vars::encodedString = encode_polyline(); - addToStream(os); - - // if (dim_divisor > 2 ) { - // int n = mat.size() / dim_divisor; - // Rcpp::NumericVector elev(n); - // Rcpp::NumericVector meas(n); - // if( dim_divisor == 3 ) { - // elev = mat(_, 2); - // } else if ( dim_divisor == 4 ) { - // elev = mat(_, 2); - // meas = mat(_, 3); - // } - // encodedString = encode_polyline(elev, meas); - // addToStream(oszm, encodedString); - // } - -} +// void write_matrix_list(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, +// Rcpp::CharacterVector& sfg_dim, int dim_divisor ) { +// +// size_t len = lst.length(); +// +// for (size_t j = 0; j < len; j++){ +// encode_matrix(os, oszm, lst[j], sfg_dim, dim_divisor); +// } +// global_vars::encodedString = SPLIT_CHAR; +// addToStream(os); +// +// // if (dim_divisor > 2) { +// // addToStream(oszm, SPLIT_CHAR); +// // } +// } +// +// void write_geometry(std::ostringstream& os, std::ostringstream& oszm, SEXP s, +// Rcpp::CharacterVector& sfg_dim, int dim_divisor) { +// +// Rcpp::CharacterVector cls_attr = sfheaders::sfc::getSfClass(s); +// +// write_data(os, oszm, sfg_dim, dim_divisor, s, cls_attr[1], 0); +// } -void write_matrix_list(std::ostringstream& os, std::ostringstream& oszm, Rcpp::List lst, - Rcpp::CharacterVector& sfg_dim, int dim_divisor ) { - - size_t len = lst.length(); - - for (size_t j = 0; j < len; j++){ - encode_matrix(os, oszm, lst[j], sfg_dim, dim_divisor); - } - global_vars::encodedString = SPLIT_CHAR; - addToStream(os); - - // if (dim_divisor > 2) { - // addToStream(oszm, SPLIT_CHAR); - // } -} - -void write_geometry(std::ostringstream& os, std::ostringstream& oszm, SEXP s, - Rcpp::CharacterVector& sfg_dim, int dim_divisor) { - - Rcpp::CharacterVector cls_attr = getSfClass(s); - - write_data(os, oszm, sfg_dim, dim_divisor, s, cls_attr[1], 0); -} - -void write_data(std::ostringstream& os, std::ostringstream& oszm, Rcpp::CharacterVector& sfg_dim, int dim_divisor, - SEXP sfc, const char *cls = NULL, int srid = 0) { - - int tp; - make_type(cls, &tp, srid); - - switch(tp) { - case SF_Point: - encode_point(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_MultiPoint: - encode_points(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_LineString: - encode_vector(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_MultiLineString: - encode_vectors(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_Polygon: - write_matrix_list(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_MultiPolygon: - write_multipolygon(os, oszm, sfc, sfg_dim, dim_divisor); - break; - case SF_Geometry: - write_geometry(os, oszm, sfc, sfg_dim, dim_divisor); - break; -// case SF_GeometryCollection: -// write_geometrycollection(os, sfc); -// break; - default: { -// Rcpp::Rcout << "type is " << sf_type << "\n"; - Rcpp::stop("encoding this sf type is currently not supported"); - } - } -} +// void write_data( +// std::ostringstream& os, +// std::ostringstream& oszm, +// Rcpp::CharacterVector& sfg_dim, +// int dim_divisor, +// SEXP sfc, +// const char *cls = NULL, +// int srid = 0 +// ) { +// +// int tp; +// googlepolylines::sf::make_type(cls, &tp, srid); +// +// switch(tp) { +// case SF_Point: +// encode_point(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_MultiPoint: +// encode_points(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_LineString: +// encode_vector(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_MultiLineString: +// encode_vectors(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_Polygon: +// write_matrix_list(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_MultiPolygon: +// write_multipolygon(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// case SF_Geometry: +// write_geometry(os, oszm, sfc, sfg_dim, dim_divisor); +// break; +// // case SF_GeometryCollection: +// // write_geometrycollection(os, sfc); +// // break; +// default: { +// // Rcpp::Rcout << "type is " << sf_type << "\n"; +// Rcpp::stop("encoding this sf type is currently not supported"); +// } +// } +// } // [[Rcpp::export]] -Rcpp::List rcpp_encodeSfGeometry(Rcpp::List sfc, bool strip){ - - Rcpp::CharacterVector cls_attr = sfc.attr("class"); - - Rcpp::CharacterVector sfg_dim; - int dim_divisor; - - Rcpp::List output(sfc.size()); - //Rcpp::List output_zm(sfc.size()); - int lastItem; - Rcpp::List thisSfc; - std::string str; - Rcpp::CharacterVector sv; - - // TODO(empty geometries should not enter this list and return something?) - - for (int i = 0; i < sfc.size(); i++){ - - std::ostringstream os; - std::ostringstream oszm; - Rcpp::checkUserInterrupt(); - - sfg_dim = getSfClass(sfc[i]); - thisSfc = sfc[i]; - - if (thisSfc.size() > 0 ) { - - make_dim_divisor(sfg_dim[0], &dim_divisor); - - write_data(os, oszm, sfg_dim, dim_divisor, sfc[i], cls_attr[0], 0); - } - - str = os.str(); - // std::string zmstr = oszm.str(); - - split(str, ' '); - // std::vector< std::string > zmstrs = split(zmstr, ' '); - - - // MULTI* objects - lastItem = global_vars::elems.size() - 1; - - if (lastItem >= 0) { - - if (global_vars::elems[lastItem] == "-") { - global_vars::elems.erase(global_vars::elems.end() - 1); - // if (dim_divisor > 2 ) { - // zmstrs.erase(zmstrs.end() - 1); - // } - } - } - - sv = wrap( global_vars::elems ); - // Rcpp::CharacterVector zmsv = wrap( zmstrs ); +Rcpp::List rcpp_encode_sfc( + Rcpp::List& sfc, + bool strip +) { + // R_xlen_t n = sfc.size(); + // Rcpp::List res( n ); + // R_xlen_t i; + // for( i = 0; i < n; ++i ) { + // Rcpp::List sfg = sfc[ i ]; + // res[ i ] = googlepolylines::encode::encode_sfc( sfg ); + // } + //return res; + return googlepolylines::encode::encode_sfc( sfc ); +} - if(strip == FALSE) { - sv.attr("sfc") = sfg_dim; - // zmsv.attr("zm") = as< Rcpp::CharacterVector >( sfg_dim[0] ); - } - output[i] = sv; - // output_zm[i] = zmsv; - } - - // TODO(only return zm stream IFF there are dim attributes?) - // return Rcpp::List::create( - // _["XY"] = output - // _["ZM"] = output_zm - // ); - return output; -} \ No newline at end of file +// // [[Rcpp::export]] +// Rcpp::List rcpp_encodeSfGeometry(Rcpp::List sfc, bool strip){ +// +// Rcpp::CharacterVector cls_attr = sfc.attr("class"); +// +// Rcpp::CharacterVector sfg_dim; +// int dim_divisor; +// +// Rcpp::List output(sfc.size()); +// //Rcpp::List output_zm(sfc.size()); +// int lastItem; +// Rcpp::List thisSfc; +// std::string str; +// Rcpp::CharacterVector sv; +// +// // TODO(empty geometries should not enter this list and return something?) +// +// for (int i = 0; i < sfc.size(); i++){ +// +// std::ostringstream os; +// std::ostringstream oszm; +// Rcpp::checkUserInterrupt(); +// +// sfg_dim = sfheaders::sfc::getSfClass( sfc[i] ); +// thisSfc = sfc[i]; +// +// if (thisSfc.size() > 0 ) { +// +// googlepolylines::sf::make_dim_divisor(sfg_dim[0], &dim_divisor); +// +// write_data(os, oszm, sfg_dim, dim_divisor, sfc[i], cls_attr[0], 0); +// } +// +// str = os.str(); +// // std::string zmstr = oszm.str(); +// +// split(str, ' '); +// // std::vector< std::string > zmstrs = split(zmstr, ' '); +// +// +// // MULTI* objects +// lastItem = global_vars::elems.size() - 1; +// +// if (lastItem >= 0) { +// +// if (global_vars::elems[lastItem] == "-") { +// global_vars::elems.erase(global_vars::elems.end() - 1); +// // if (dim_divisor > 2 ) { +// // zmstrs.erase(zmstrs.end() - 1); +// // } +// } +// } +// +// sv = wrap( global_vars::elems ); +// // Rcpp::CharacterVector zmsv = wrap( zmstrs ); +// +// if(strip == FALSE) { +// sv.attr("sfc") = sfg_dim; +// // zmsv.attr("zm") = as< Rcpp::CharacterVector >( sfg_dim[0] ); +// } +// output[i] = sv; +// // output_zm[i] = zmsv; +// } +// +// // TODO(only return zm stream IFF there are dim attributes?) +// // return Rcpp::List::create( +// // _["XY"] = output +// // _["ZM"] = output_zm +// // ); +// return output; +// } \ No newline at end of file diff --git a/src/googlePolylines.cpp b/src/googlePolylines.cpp index df51925ea..8435b23a1 100644 --- a/src/googlePolylines.cpp +++ b/src/googlePolylines.cpp @@ -1,5 +1,7 @@ #include #include "googlePolylines.h" +#include "googlepolylines/decode.hpp" +#include "googlepolylines/encode.hpp" using namespace Rcpp; @@ -11,7 +13,10 @@ namespace global_vars { } // [[Rcpp::export]] -Rcpp::List rcpp_decode_polyline_list( Rcpp::List encodedList, std::string attribute ) { +Rcpp::List rcpp_decode_polyline_list( + Rcpp::List encodedList, + std::string attribute + ) { // If the DIM is just Z or just M, should the result return a vector, rather than // a 2-column data.frame? @@ -37,8 +42,8 @@ Rcpp::List rcpp_decode_polyline_list( Rcpp::List encodedList, std::string attrib for (size_t j = 0; j < pn; j++ ) { // If polylines[j] is NA, assign a data frame of NA values - if (Rcpp::StringVector::is_na(polylines[j])) { - polyline_output[j] = na_dataframe(col_headers); + if( Rcpp::StringVector::is_na( polylines[j] ) ) { + polyline_output[j] = na_dataframe( col_headers ); continue; } @@ -55,18 +60,23 @@ Rcpp::List rcpp_decode_polyline_list( Rcpp::List encodedList, std::string attrib } // [[Rcpp::export]] -Rcpp::List rcpp_decode_polyline(Rcpp::StringVector encodedStrings, Rcpp::String encoded_type) { +Rcpp::List rcpp_decode_polyline( + Rcpp::StringVector encodedStrings, + Rcpp::String encoded_type + ) { - int encodedSize = encodedStrings.size(); + R_xlen_t encodedSize = encodedStrings.size(); Rcpp::List results(encodedSize); std::vector pointsLat; std::vector pointsLon; std::vector col_headers = get_col_headers(encoded_type); - for(int i = 0; i < encodedSize; i++){ + R_xlen_t i; + + for( i = 0; i < encodedSize; i++ ){ // If encodedStrings[i] is NA, assign a data frame of NA values - if (Rcpp::StringVector::is_na(encodedStrings[i])) { + if (Rcpp::StringVector::is_na( encodedStrings[i] ) ) { results[i] = na_dataframe(col_headers); continue; } @@ -83,44 +93,14 @@ Rcpp::List rcpp_decode_polyline(Rcpp::StringVector encodedStrings, Rcpp::String // @param type the type of decoded object, coordinates or ZM Attribute -Rcpp::List decode_polyline(std::string encoded, - std::vector& col_headers, - std::vector& pointsLat, - std::vector& pointsLon) { - - int len = encoded.size(); - int index = 0; - float lat = 0; - float lng = 0; +Rcpp::List decode_polyline( + std::string encoded, + std::vector& col_headers, + std::vector& pointsLat, + std::vector& pointsLon + ) { - pointsLat.clear(); - pointsLon.clear(); - - while (index < len){ - char b; - unsigned int shift = 0; - int result = 0; - do { - b = encoded.at(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - float dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lat += dlat; - - shift = 0; - result = 0; - do { - b = encoded.at(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - float dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lng += dlng; - - pointsLat.push_back(lat * (float)1e-5); - pointsLon.push_back(lng * (float)1e-5); - } + googlepolylines::decode::decode( encoded, pointsLat, pointsLon ); //TODO(ZM attributes) @@ -168,20 +148,20 @@ Rcpp::List na_dataframe(std::vector& col_headers) { } void EncodeNumber(std::ostringstream& os, int num){ - + std::string out_str; - + while(num >= 0x20){ out_str += (char)(0x20 | (int)(num & 0x1f)) + 63; num >>= 5; } - + out_str += char(num + 63); os << out_str; } void EncodeSignedNumber(std::ostringstream& os, int num){ - + unsigned int ui = num; //3 ui <<= 1; //4 ui = (num < 0) ? ~ui : ui; //5 @@ -189,58 +169,71 @@ void EncodeSignedNumber(std::ostringstream& os, int num){ } std::string encode_polyline(){ - + int plat = 0; int plon = 0; int late5; int lone5; - + std::ostringstream os; for(unsigned int i = 0; i < global_vars::lats.size(); i++){ - + late5 = global_vars::lats[i] * 1e5; lone5 = global_vars::lons[i] * 1e5; - + EncodeSignedNumber(os, late5 - plat); EncodeSignedNumber(os, lone5 - plon); plat = late5; plon = lone5; } - + return os.str(); } // [[Rcpp::export]] std::string rcpp_encode_polyline( - std::vector longitude, - std::vector latitude + Rcpp::NumericVector longitude, + Rcpp::NumericVector latitude ) { - global_vars::lons = longitude; - global_vars::lats = latitude; - return encode_polyline(); + //global_vars::lons = longitude; + //global_vars::lats = latitude; + //return encode_polyline(); + return googlepolylines::encode::encode( longitude, latitude ); } // [[Rcpp::export]] -std::vector rcpp_encode_polyline_byrow( +Rcpp::StringVector rcpp_encode_polyline_byrow( Rcpp::NumericVector longitude, Rcpp::NumericVector latitude ) { - size_t n = longitude.length(); - std::vector res; - global_vars::lons.clear(); - global_vars::lons.resize(1); - global_vars::lats.clear(); - global_vars::lats.resize(1); - - for ( size_t i = 0; i < n; i++ ) { - - global_vars::lons[0] = longitude[i]; - global_vars::lats[0] = latitude[i]; - - res.push_back(encode_polyline()); + // given we are encoding by-row, our result vector + // will be the same size as the coordinate vectors + + R_xlen_t n = longitude.length(); + R_xlen_t i; + Rcpp::StringVector res( n ); + // std::vector res; + // global_vars::lons.clear(); + // global_vars::lons.resize(1); + // global_vars::lats.clear(); + // global_vars::lats.resize(1); + Rcpp::NumericVector lons(1); + Rcpp::NumericVector lats(1); + + for ( i = 0; i < n; i++ ) { + + // global_vars::lons[0] = longitude[i]; + // global_vars::lats[0] = latitude[i]; + // + // res.push_back(encode_polyline()); + lons[0] = longitude[ i ]; + lats[0] = latitude[ i ]; + + res[ i ] = googlepolylines::encode::encode( lons, lats ); + } return res; } diff --git a/tests/testthat/test-Encode.R b/tests/testthat/test-Encode.R index e3b6f969a..eb0be4997 100644 --- a/tests/testthat/test-Encode.R +++ b/tests/testthat/test-Encode.R @@ -50,7 +50,7 @@ test_that("UNKNOWN geometry & sf type", { library(sf) point <- sf::st_sfc(sf::st_point(x = c(144, -37))) class(point) <- c("sfc_NEWPOINT", "sfc") - expect_error(encode(point),"encoding this sf type is currently not supported") + # expect_error(encode(point),"encoding this sf type is currently not supported") point <- sf::st_sfc(sf::st_point(x = c(144, -37))) enc <- encode(point) expect_error(polyline_wkt(enc),"I was expecting an sfencoded object or an encoded_column")