rspatial / terra

R package for spatial data handling https://rspatial.github.io/terra/reference/terra-package.html
GNU General Public License v3.0
535 stars 88 forks source link

return raw wkb? #1609

Open mdsumner opened 3 days ago

mdsumner commented 3 days ago

Here raw binary wkb is obtained but then converted to string:

https://github.com/rspatial/terra/blob/e62c73372b008d0ef58957319a1a5a7286d7e338/src/geos_methods.cpp#L107

I'd like to request returning it as a list of raw vectors, I don't think that's otherwise possible in terra atm? We can get wkt string or hex string, but not the raw vector in a list.

I'm interested to have general interop via {wk} with this (SpatVector is really the only major missing type for wk), and not go through character vectors or file or other expanded in-memory form. Thank you. I can probably manage a PR if it's not unwelcome. Not sure what to call the method ... "wkb_raw()" ?

mdsumner commented 2 days ago

I got this to work by adding this to 'geos_methods.cpp'

Rcpp::List SpatVector::wkb_raw() {
    GEOSContextHandle_t hGEOSCtxt = geos_init();
    std::vector<GeomPtr> g = geos_geoms(this, hGEOSCtxt);
    Rcpp::List out; 
    size_t len = 0;
    for (size_t i = 0; i < g.size(); i++) {
     unsigned char *hex = GEOSGeomToWKB_buf_r(hGEOSCtxt, g[i].get(), &len);
         Rcpp::RawVector raw(len);
         memcpy(&(raw[0]), hex, len);
         out.push_back(raw);
         free(hex);
    }
    geos_finish(hGEOSCtxt);
    return out;
}

and the required

Rcpp::List wkb_raw(); to 'SpatVector.h'

.method("wkb_raw", &SpatVector::wkb_raw) in 'RcppModule'

That means Rcpp.h added as well which is probably not welcome? I'll keep exploring how to structure this.

Example:

wk::wkb(vect(cbind(1:10, rnorm(10)), "line")@ptr$wkb_raw())
<wk_wkb[1]>
[1] <LINESTRING (1 0.5928676, 2 0.9755936, 3 -1.12088, 4 0.08522013, 5 0.4874861, 6 0.2880466...>