From e4d5eb8801084727d86bba87f62e504084c833a9 Mon Sep 17 00:00:00 2001 From: rhijmans Date: Wed, 25 Dec 2024 11:27:56 -0800 Subject: [PATCH] u --- NEWS.md | 2 +- R/RcppExports.R | 20 ++++++------- R/panel.R | 16 +++++++--- R/plot_raster.R | 7 +---- src/RcppExports.cpp | 45 +++++++++++++++------------- src/RcppModule.cpp | 1 + src/distRaster.cpp | 6 ++-- src/geosphere.cpp | 66 ++++++++++++++++++------------------------ src/raster_methods.cpp | 12 ++++++++ src/spatVector.h | 4 ++- 10 files changed, 96 insertions(+), 83 deletions(-) diff --git a/NEWS.md b/NEWS.md index 59e85db7f..e5e721c64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,7 +11,6 @@ - `autocor` improved handling of NA cells for global Moran computation [#1992](https://github.com/rspatial/terra/issues/1592) by Nicholas Berryman - `shade` is more memory-safe. [#1452](https://github.com/rspatial/terra/issues/1452) by Francis van Oordt and Chris English - ## enhancements - `plot` now uses the same default viridis color palette as `plot` [#1670](https://github.com/rspatial/terra/issues/1670) by Márcia Barbosa @@ -19,6 +18,7 @@ - `init` accepts additional arguments for function "fun" - better handling of the 32 connection limiations set by the HDF4 library [#1481](https://github.com/rspatial/terra/issues/1481) by Dimitri Falk - When using RStudio a once per session warning is given when using draw, sel or click [#1063](https://github.com/rspatial/terra/issues/1063) by Sergei Kharchenko +- `distance` from lon and lat lines/polygons computes distance to the edges instead of the nodes [#1462](https://github.com/rspatial/terra/issues/1462) by Derek Friend ## new diff --git a/R/RcppExports.R b/R/RcppExports.R index d423cf524..4192394de 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -141,28 +141,28 @@ dir_rad <- function(lon1, lat1, lon2, lat2) { .Call(`_terra_dir_rad`, lon1, lat1, lon2, lat2) } -dist2track <- function(lon1, lat1, lon2, lat2, plon, plat, sign) { - .Call(`_terra_dist2track`, lon1, lat1, lon2, lat2, plon, plat, sign) +dist2track <- function(lon1, lat1, lon2, lat2, plon, plat, sign, r = 6378137) { + .Call(`_terra_dist2track`, lon1, lat1, lon2, lat2, plon, plat, sign, r) } -dist2track_cosine_rad <- function(lon1, lat1, lon2, lat2, plon, plat, sign) { - .Call(`_terra_dist2track_cosine_rad`, lon1, lat1, lon2, lat2, plon, plat, sign) +dist2track_cosine_rad <- function(lon1, lat1, lon2, lat2, plon, plat, sign, r = 6378137) { + .Call(`_terra_dist2track_cosine_rad`, lon1, lat1, lon2, lat2, plon, plat, sign, r) } -alongTrackDistance <- function(lon1, lat1, lon2, lat2, plon, plat) { - .Call(`_terra_alongTrackDistance`, lon1, lat1, lon2, lat2, plon, plat) +alongTrackDistance <- function(lon1, lat1, lon2, lat2, plon, plat, r = 6378137) { + .Call(`_terra_alongTrackDistance`, lon1, lat1, lon2, lat2, plon, plat, r) } -alongTrackDistance_rad <- function(lon1, lat1, lon2, lat2, plon, plat) { - .Call(`_terra_alongTrackDistance_rad`, lon1, lat1, lon2, lat2, plon, plat) +alongTrackDistance_rad <- function(lon1, lat1, lon2, lat2, plon, plat, r = 6378137) { + .Call(`_terra_alongTrackDistance_rad`, lon1, lat1, lon2, lat2, plon, plat, r) } dist2segment <- function(plon, plat, lon1, lat1, lon2, lat2) { .Call(`_terra_dist2segment`, plon, plat, lon1, lat1, lon2, lat2) } -dist2segment_cosine_rad <- function(plon, plat, lon1, lat1, lon2, lat2) { - .Call(`_terra_dist2segment_cosine_rad`, plon, plat, lon1, lat1, lon2, lat2) +dist2segment_cosine_rad <- function(plon, plat, lon1, lat1, lon2, lat2, r = 6378137) { + .Call(`_terra_dist2segment_cosine_rad`, plon, plat, lon1, lat1, lon2, lat2, r) } dist2segmentPoint <- function(plon, plat, lon1, lat1, lon2, lat2, ilon, ilat) { diff --git a/R/panel.R b/R/panel.R index fb9b76375..eee3484b1 100644 --- a/R/panel.R +++ b/R/panel.R @@ -70,9 +70,15 @@ setMethod("panel", signature(x="SpatRaster"), if (is.null(range)) { if (all(hasMinMax(x))) { range <- range(minmax(x, FALSE)) + if (any(is.nan(range) | is.infinite(range))) { + r <- as.matrix(spatSample(x, maxcell, method="regular", as.raster=FALSE, warn=FALSE)) + r[is.infinite(r)] <- NA + range <- range(r, na.rm=TRUE) + } } else { - x <- spatSample(x, maxcell, method="regular", as.raster=TRUE, warn=FALSE) - range <- range(minmax(x, TRUE)) + r <- as.matrix(spatSample(x, maxcell, method="regular", as.raster=FALSE, warn=FALSE)) + r[is.infinite(r)] <- NA + range <- range(r, na.rm=TRUE) } } if (diff(range) > 0) { @@ -84,17 +90,19 @@ setMethod("panel", signature(x="SpatRaster"), if (is.null(plg$size)) plg$size <- max(1, nrnc[1] * 0.66) if (is.null(plg$cex)) plg$cex <- 1.25 plg$yshift <- (nrnc[1] %% 2 == 0) + for (i in 1:nl) { pax$side <- c(bottom[i], left[i]) if (categorical) { y <- x[[i]] levels(y) <- lv plot(y, 1, main=main[i], mar=mar, legend=legend[i], pax=pax, box=box, - loc.main=loc.main, plg=plg, type="classes", ...) + loc.main=loc.main, halo=TRUE, plg=plg, type="classes", ...) } else { plot(x, i, main=main[i], mar=mar, legend=legend[i], range=range, pax=pax, box=box, - loc.main=loc.main, plg=plg, type=ptype, ...) + loc.main=loc.main, halo=TRUE, plg=plg, type=ptype, ...) } } } ) + diff --git a/R/plot_raster.R b/R/plot_raster.R index de667f00e..4b869d429 100644 --- a/R/plot_raster.R +++ b/R/plot_raster.R @@ -106,12 +106,7 @@ hexcols <- function(out) { } -.as.raster.continuous <- function(out, x, type, Z=NULL) { - - if (is.null(Z)) { - Z <- as.matrix(x, wide=TRUE) - Z[is.nan(Z) | is.infinite(Z)] <- NA - } +.as.raster.continuous <- function(out, x, type) { Z <- as.matrix(x, wide=TRUE) Z[is.nan(Z) | is.infinite(Z)] <- NA diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 94937bedb..1455ae19f 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -425,8 +425,8 @@ BEGIN_RCPP END_RCPP } // dist2track -double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign); -RcppExport SEXP _terra_dist2track(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP signSEXP) { +double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign, double r); +RcppExport SEXP _terra_dist2track(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP signSEXP, SEXP rSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -437,13 +437,14 @@ BEGIN_RCPP Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); Rcpp::traits::input_parameter< bool >::type sign(signSEXP); - rcpp_result_gen = Rcpp::wrap(dist2track(lon1, lat1, lon2, lat2, plon, plat, sign)); + Rcpp::traits::input_parameter< double >::type r(rSEXP); + rcpp_result_gen = Rcpp::wrap(dist2track(lon1, lat1, lon2, lat2, plon, plat, sign, r)); return rcpp_result_gen; END_RCPP } // dist2track_cosine_rad -double dist2track_cosine_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign); -RcppExport SEXP _terra_dist2track_cosine_rad(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP signSEXP) { +double dist2track_cosine_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign, double r); +RcppExport SEXP _terra_dist2track_cosine_rad(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP signSEXP, SEXP rSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -454,13 +455,14 @@ BEGIN_RCPP Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); Rcpp::traits::input_parameter< bool >::type sign(signSEXP); - rcpp_result_gen = Rcpp::wrap(dist2track_cosine_rad(lon1, lat1, lon2, lat2, plon, plat, sign)); + Rcpp::traits::input_parameter< double >::type r(rSEXP); + rcpp_result_gen = Rcpp::wrap(dist2track_cosine_rad(lon1, lat1, lon2, lat2, plon, plat, sign, r)); return rcpp_result_gen; END_RCPP } // alongTrackDistance -double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat); -RcppExport SEXP _terra_alongTrackDistance(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP) { +double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat, double r); +RcppExport SEXP _terra_alongTrackDistance(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP rSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -470,13 +472,14 @@ BEGIN_RCPP Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); - rcpp_result_gen = Rcpp::wrap(alongTrackDistance(lon1, lat1, lon2, lat2, plon, plat)); + Rcpp::traits::input_parameter< double >::type r(rSEXP); + rcpp_result_gen = Rcpp::wrap(alongTrackDistance(lon1, lat1, lon2, lat2, plon, plat, r)); return rcpp_result_gen; END_RCPP } // alongTrackDistance_rad -double alongTrackDistance_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat); -RcppExport SEXP _terra_alongTrackDistance_rad(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP) { +double alongTrackDistance_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, double r); +RcppExport SEXP _terra_alongTrackDistance_rad(SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP plonSEXP, SEXP platSEXP, SEXP rSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -486,7 +489,8 @@ BEGIN_RCPP Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); Rcpp::traits::input_parameter< double >::type plon(plonSEXP); Rcpp::traits::input_parameter< double >::type plat(platSEXP); - rcpp_result_gen = Rcpp::wrap(alongTrackDistance_rad(lon1, lat1, lon2, lat2, plon, plat)); + Rcpp::traits::input_parameter< double >::type r(rSEXP); + rcpp_result_gen = Rcpp::wrap(alongTrackDistance_rad(lon1, lat1, lon2, lat2, plon, plat, r)); return rcpp_result_gen; END_RCPP } @@ -507,8 +511,8 @@ BEGIN_RCPP END_RCPP } // dist2segment_cosine_rad -double dist2segment_cosine_rad(double plon, double plat, double lon1, double lat1, double lon2, double lat2); -RcppExport SEXP _terra_dist2segment_cosine_rad(SEXP plonSEXP, SEXP platSEXP, SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP) { +double dist2segment_cosine_rad(double plon, double plat, double lon1, double lat1, double lon2, double lat2, double r); +RcppExport SEXP _terra_dist2segment_cosine_rad(SEXP plonSEXP, SEXP platSEXP, SEXP lon1SEXP, SEXP lat1SEXP, SEXP lon2SEXP, SEXP lat2SEXP, SEXP rSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -518,7 +522,8 @@ BEGIN_RCPP Rcpp::traits::input_parameter< double >::type lat1(lat1SEXP); Rcpp::traits::input_parameter< double >::type lon2(lon2SEXP); Rcpp::traits::input_parameter< double >::type lat2(lat2SEXP); - rcpp_result_gen = Rcpp::wrap(dist2segment_cosine_rad(plon, plat, lon1, lat1, lon2, lat2)); + Rcpp::traits::input_parameter< double >::type r(rSEXP); + rcpp_result_gen = Rcpp::wrap(dist2segment_cosine_rad(plon, plat, lon1, lat1, lon2, lat2, r)); return rcpp_result_gen; END_RCPP } @@ -595,12 +600,12 @@ static const R_CallMethodDef CallEntries[] = { {"_terra_dest_lonlat", (DL_FUNC) &_terra_dest_lonlat, 7}, {"_terra_dir_lonlat", (DL_FUNC) &_terra_dir_lonlat, 4}, {"_terra_dir_rad", (DL_FUNC) &_terra_dir_rad, 4}, - {"_terra_dist2track", (DL_FUNC) &_terra_dist2track, 7}, - {"_terra_dist2track_cosine_rad", (DL_FUNC) &_terra_dist2track_cosine_rad, 7}, - {"_terra_alongTrackDistance", (DL_FUNC) &_terra_alongTrackDistance, 6}, - {"_terra_alongTrackDistance_rad", (DL_FUNC) &_terra_alongTrackDistance_rad, 6}, + {"_terra_dist2track", (DL_FUNC) &_terra_dist2track, 8}, + {"_terra_dist2track_cosine_rad", (DL_FUNC) &_terra_dist2track_cosine_rad, 8}, + {"_terra_alongTrackDistance", (DL_FUNC) &_terra_alongTrackDistance, 7}, + {"_terra_alongTrackDistance_rad", (DL_FUNC) &_terra_alongTrackDistance_rad, 7}, {"_terra_dist2segment", (DL_FUNC) &_terra_dist2segment, 6}, - {"_terra_dist2segment_cosine_rad", (DL_FUNC) &_terra_dist2segment_cosine_rad, 6}, + {"_terra_dist2segment_cosine_rad", (DL_FUNC) &_terra_dist2segment_cosine_rad, 7}, {"_terra_dist2segmentPoint", (DL_FUNC) &_terra_dist2segmentPoint, 8}, {"_terra_intermediate", (DL_FUNC) &_terra_intermediate, 6}, {"_rcpp_module_boot_spat", (DL_FUNC) &_rcpp_module_boot_spat, 0}, diff --git a/src/RcppModule.cpp b/src/RcppModule.cpp index 6fe0bd2c9..9fe3402a6 100644 --- a/src/RcppModule.cpp +++ b/src/RcppModule.cpp @@ -563,6 +563,7 @@ RCPP_MODULE(spat){ .method("intersect", &SpatVector::intersect) .method("delaunay", &SpatVector::delaunay) .method("voronoi", &SpatVector::voronoi) + .method("voronoi_sphere", &SpatVector::voronoi_sphere) .method("hull", &SpatVector::hull) .method("width", &SpatVector::width) diff --git a/src/distRaster.cpp b/src/distRaster.cpp index 4178e4f40..d5603123f 100644 --- a/src/distRaster.cpp +++ b/src/distRaster.cpp @@ -1013,14 +1013,14 @@ std::vector SpatVector::distance(SpatVector x, bool pairwise, std::strin if (lonlat) { if (xtype == "points") { - return linedistLonLat(x); + return linedistLonLat(x, unit); } else if (gtype == "points") { - return x.linedistLonLat(*this); + return x.linedistLonLat(*this, unit); } else { // not good enough // need fixing SpatVector tmp = x.as_points(false, true); - return x.linedistLonLat(tmp); + return x.linedistLonLat(tmp, unit); } } diff --git a/src/geosphere.cpp b/src/geosphere.cpp index 7646decdf..579187c4a 100644 --- a/src/geosphere.cpp +++ b/src/geosphere.cpp @@ -134,12 +134,12 @@ double dir_rad(double lon1, double lat1, double lon2, double lat2) { // [[Rcpp::export]] -double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign) { +double dist2track(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign, double r=6378137) { double a = 1; double f = 0; struct geod_geodesic geod; geod_init(&geod, a, f); - const double r = 6378137.0; + double d, b2, b3, azi; geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &b2, &azi); @@ -153,12 +153,11 @@ double dist2track(double lon1, double lat1, double lon2, double lat2, double plo // [[Rcpp::export]] -double dist2track_cosine_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign) { +double dist2track_cosine_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, bool sign, double r=6378137) { // same results as above but probably much faster - const double r = 6378137.0; double b2 = dir_rad(lon1, lat1, lon2, lat2); double b3 = dir_rad(lon1, lat1, plon, plat); - double d = dist_cosine_rad(lon1, lat1, plon, plat) / r; + double d = dist_cosine_rad(lon1, lat1, plon, plat, 1); double xtr = asin(sin(b3-b2) * sin(d)) * r; return sign ? xtr : fabs(xtr); } @@ -167,13 +166,11 @@ double dist2track_cosine_rad(double lon1, double lat1, double lon2, double lat2, // [[Rcpp::export]] -double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat) { +double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, double plon, double plat, double r=6378137) { double a = 1; double f = 0; struct geod_geodesic geod; geod_init(&geod, a, f); - double r = 6378137.0; - double d, b2, b3, azi; geod_inverse(&geod, lat1, lon1, lat2, lon2, &d, &b2, &azi); geod_inverse(&geod, lat1, lon1, plat, plon, &d, &b3, &azi); @@ -189,9 +186,7 @@ double alongTrackDistance(double lon1, double lat1, double lon2, double lat2, do // [[Rcpp::export]] -double alongTrackDistance_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat) { - - const double r = 6378137; +double alongTrackDistance_rad(double lon1, double lat1, double lon2, double lat2, double plon, double plat, double r=6378137) { double tc = dir_rad(lon1, lat1, lon2, lat2); // * toRad double tcp = dir_rad(lon1, lat1, plon, plat); // * toRad @@ -229,19 +224,19 @@ double dist2segment(double plon, double plat, double lon1, double lat1, double l // [[Rcpp::export]] -double dist2segment_cosine_rad(double plon, double plat, double lon1, double lat1, double lon2, double lat2) { +double dist2segment_cosine_rad(double plon, double plat, double lon1, double lat1, double lon2, double lat2, double r=6378137) { // the alongTrackDistance is the length of the path along the great circle to the point of intersection // there are two, depending on which node you start // we want to use the min, but the max needs to be < segment length - double seglength = dist_cosine_rad(lon1, lat1, lon2, lat2); - double trackdist1 = alongTrackDistance_rad(lon1, lat1, lon2, lat2, plon, plat); - double trackdist2 = alongTrackDistance_rad(lon2, lat2, lon1, lat1, plon, plat); + double seglength = dist_cosine_rad(lon1, lat1, lon2, lat2, r); + double trackdist1 = alongTrackDistance_rad(lon1, lat1, lon2, lat2, plon, plat, r); + double trackdist2 = alongTrackDistance_rad(lon2, lat2, lon1, lat1, plon, plat, r); if ((trackdist1 >= seglength) || (trackdist2 >= seglength)) { - double d1 = dist_cosine_rad(lon1, lat1, plon, plat); - double d2 = dist_cosine_rad(lon2, lat2, plon, plat); + double d1 = dist_cosine_rad(lon1, lat1, plon, plat, r); + double d2 = dist_cosine_rad(lon2, lat2, plon, plat, r); return d1 < d2 ? d1 : d2; } - return dist2track_cosine_rad(lon1, lat1, lon2, lat2, plon, plat, false); + return dist2track_cosine_rad(lon1, lat1, lon2, lat2, plon, plat, false, r); } // [[Rcpp::export]] @@ -276,7 +271,7 @@ double dist2segmentPoint(double plon, double plat, double lon1, double lat1, dou } -std::vector SpatVector::linedistLonLat(SpatVector x) { +std::vector SpatVector::linedistLonLat(SpatVector x, std::string unit) { std::vector d; @@ -286,6 +281,13 @@ std::vector SpatVector::linedistLonLat(SpatVector x) { return d; } + double r = 6378137; + if (unit == "km") { + r = 6378.137; + } else if (unit == "ha") { + r = 63781.37; + } + std::vector> pxy = x.coordinates(); deg2rad(pxy[0]); deg2rad(pxy[1]); @@ -301,10 +303,6 @@ std::vector SpatVector::linedistLonLat(SpatVector x) { if (type() == "polygons") { std::vector insect = relate(x, "intersects", true, true); for (size_t g=0; g> xy = geoms[g].coordinates(true); -// deg2rad(xy[0]); -// deg2rad(xy[1]); -// size_t nseg = xy[0].size() - 1; size_t nparts = geoms[g].size(); for (size_t h=0; h SpatVector::linedistLonLat(SpatVector x) { deg2rad(py); size_t nseg = px.size() - 1; for (size_t i=0; i SpatVector::linedistLonLat(SpatVector x) { if ((d[i] != 0) && (insect[i] == 0)) { for (size_t j=0; j SpatVector::linedistLonLat(SpatVector x) { for (size_t i=0; i fact, std::string fun, bool //size_t outnc = out.ncol(); if (fun == "table") { + + /* + std::vector> ud = unique(false, 0, ops); + std::vector uvals; + uvals.reserve(ud.size()); + for (size_t i=0; i counts; + for (sizt_t =0; i vin, v; readValues(vin, bs.row[i], bs.nrows[i], 0, nc); diff --git a/src/spatVector.h b/src/spatVector.h index dff040ca0..9a77a607f 100644 --- a/src/spatVector.h +++ b/src/spatVector.h @@ -203,7 +203,7 @@ class SpatVector { // std::vector pointdistance_seq(const std::vector& px, const std::vector& py, double m, bool lonlat); - std::vector linedistLonLat(SpatVector x); + std::vector linedistLonLat(SpatVector x, std::string unit); std::vector> knearest(size_t k); @@ -352,6 +352,8 @@ class SpatVector { SpatVector crop(SpatExtent e, bool wrap); SpatVector crop(SpatVector e); SpatVector voronoi(SpatVector bnd, double tolerance, int onlyEdges); + SpatVector voronoi_sphere(SpatVector bnd, double tolerance, int onlyEdges); + SpatVector delaunay(double tolerance, int onlyEdges); SpatVector hull(std::string htype, std::string by=""); SpatVector intersect(SpatVector v, bool values);