Skip to content

Commit 4fde3e0

Browse files
committed
fixes #1738
1 parent ad5f658 commit 4fde3e0

File tree

11 files changed

+171
-11
lines changed

11 files changed

+171
-11
lines changed

NAMESPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
useDynLib(terra, .registration=TRUE)
22
import(methods, Rcpp)
33
exportClasses(SpatExtent, SpatRaster, SpatRasterDataset, SpatRasterCollection, SpatVector, SpatVectorProxy, SpatVectorCollection)
4-
exportMethods("[", "[[", "!", "%in%", activeCat, "activeCat<-", "add<-", addCats, adjacent, agitate, all.equal, aggregate, allNA, align, animate, anyNA, app, Arith, approximate, as.bool, as.int, as.contour, as.lines, as.points, as.polygons, as.raster, as.array, as.data.frame, as.factor, as.list, as.logical, as.matrix, as.numeric, atan2, atan_2, autocor, barplot, blocks, boundaries, boxplot, buffer, cartogram, categories, cats, catalyze, chunk, clamp, clamp_ts, classify, clearance, cellSize, cells, cellFromXY, cellFromRowCol, cellFromRowColCombine, centroids, click, bestMatch, colFromX, colFromCell, colorize, coltab, "coltab<-", combineGeoms, compare, concats, Compare, compareGeom, contour, convHull, countNA, costDist, crds, cover, crop, crosstab, crs, "crs<-", datatype, deepcopy, delaunay, densify, density, depth, "depth<-", depthName, "depthName<-", depthUnit, "depthUnit<-", describe, diff, disagg, direction, distance, divide, dots, draw, droplevels, elongate, emptyGeoms, erase, extend, ext, "ext<-", extract, extractRange, expanse, fillHoles, fillTime, flip, focal, focal3D, focalPairs, focalReg, focalCpp, focalValues, forceCCW, freq, gaps, geom, geomtype, getTileExtents, global, gridDistance, gridDist, has.colors, has.RGB, has.time, hull, hasMinMax, hasValues, hist, head, identical, ifel, impose, init, image, inext, interpIDW, interpNear, inMemory, inset, interpolate, intersect, is.bool, is.int, is.num, is.lonlat, is.rotated, isTRUE, isFALSE, is.empty, is.factor, is.flipped, is.lines, is.points, is.polygons, is.related, is.valid, k_means, lapp, layerCor, levels, "levels<-", linearUnits, lines, Logic, varnames, "varnames<-", logic, longnames, "longnames<-", simplifyLevels, makeValid, mask, match, math, Math, Math2, mean, median, meta, merge, mergeLines, mergeTime, minmax, modal, mosaic, na.omit, nany, not.na, NAflag, "NAflag<-", nearby, nearest, ncell, ncol, "ncol<-", nlyr, "nlyr<-", noNA, normalize.longitude, nrow, "nrow<-", nseg, nsrc, origin, "origin<-", pairs, panel, patches, perim, persp, plot, plotRGB, plet, prcomp, princomp, RGB, "RGB<-", polys, points, predict, project, quantile, query, rangeFill, rapp, rast, rasterize, rasterizeGeom, rasterizeWin, readStart, readStop, readValues, rectify, regress, relate, removeDupNodes, res, "res<-", resample, rescale, rev, rcl, roll, rotate, rowFromY, rowColCombine, rowColFromCell, rowFromCell, sapp, scale, scale_linear, scoff, "scoff<-", sds, sort, sprc, sel, selectRange, setMinMax, setValues, segregate, selectHighest, set.cats, set.crs, set.ext, set.names, set.RGB, set.values, set.window, size, sharedPaths, shift, sieve, simplifyGeom, snap, sources, spatSample, split, spin, stdev, stretch, subset, subst, summary, Summary, surfArea, svc, symdif, t, metags, "metags<-", tail, tapp, terrain, thresh, tighten, makeNodes, makeTiles, time, timeInfo, "time<-", text, toMemory, trans, trim, units, union, "units<-", unique, unwrap, update, vect, values, "values<-", viewshed, voronoi, vrt, weighted.mean, where.min, where.max, which.lyr, which.min, which.max, which.lyr, width, window, "window<-", writeCDF, writeRaster, wrap, wrapCache, writeStart, writeStop, writeVector, writeValues, xmin, xmax, "xmin<-", "xmax<-", xres, xFromCol, xyFromCell, xFromCell, ymin, ymax, "ymin<-", "ymax<-", yres, yFromCell, yFromRow, zonal, zoom, cbind2, readRDS, saveRDS, unserialize, serialize, xapp, area, colSums, rowSums, colMeans, rowMeans)
4+
exportMethods("[", "[[", "!", "%in%", activeCat, "activeCat<-", "add<-", addCats, adjacent, agitate, all.equal, aggregate, allNA, align, animate, anyNA, app, Arith, approximate, as.bool, as.int, as.contour, as.lines, as.points, as.polygons, as.raster, as.array, as.data.frame, as.factor, as.list, as.logical, as.matrix, as.numeric, atan2, atan_2, autocor, barplot, blocks, boundaries, boxplot, buffer, cartogram, categories, cats, catalyze, chunk, clamp, clamp_ts, classify, clearance, cellSize, cells, cellFromXY, cellFromRowCol, cellFromRowColCombine, centroids, click, bestMatch, colFromX, colFromCell, colorize, coltab, "coltab<-", combineGeoms, compare, concats, Compare, compareGeom, contour, convHull, countNA, costDist, crds, cover, crop, crosstab, crs, "crs<-", datatype, deepcopy, delaunay, densify, density, depth, "depth<-", depthName, "depthName<-", depthUnit, "depthUnit<-", describe, diff, disagg, direction, distance, divide, dots, draw, droplevels, elongate, emptyGeoms, erase, extend, ext, "ext<-", extract, extractRange, expanse, fillHoles, fillTime, flip, focal, focal3D, focalPairs, focalReg, focalCpp, focalValues, forceCCW, freq, gaps, geom, geomtype, getTileExtents, global, gridDistance, gridDist, has.colors, has.RGB, has.time, hull, hasMinMax, hasValues, hist, head, identical, ifel, impose, init, image, inext, interpIDW, interpNear, inMemory, inset, interpolate, intersect, is.bool, is.int, is.num, is.lonlat, is.rotated, isTRUE, isFALSE, is.empty, is.factor, is.flipped, is.lines, is.points, is.polygons, is.related, is.valid, k_means, lapp, layerCor, levels, "levels<-", linearUnits, lines, Logic, varnames, "varnames<-", logic, longnames, "longnames<-", simplifyLevels, makeValid, mask, match, math, Math, Math2, mean, median, meta, merge, mergeLines, mergeTime, minmax, modal, mosaic, na.omit, nany, not.na, NAflag, "NAflag<-", nearby, nearest, ncell, ncol, "ncol<-", nlyr, "nlyr<-", noNA, normalize.longitude, nrow, "nrow<-", nseg, nsrc, origin, "origin<-", pairs, panel, patches, perim, persp, plot, plotRGB, plet, prcomp, princomp, RGB, "RGB<-", polys, points, predict, project, quantile, query, rangeFill, rapp, rast, rasterize, rasterizeGeom, rasterizeWin, readStart, readStop, readValues, rectify, regress, relate, removeDupNodes, res, "res<-", resample, rescale, rev, rcl, roll, rotate, rowFromY, rowColCombine, rowColFromCell, rowFromCell, sapp, scale, scale_linear, scoff, "scoff<-", sds, sort, sprc, sel, selectRange, setMinMax, setValues, segregate, selectHighest, set.cats, set.crs, set.ext, set.names, set.RGB, set.values, set.window, size, sharedPaths, shift, sieve, simplifyGeom, snap, sources, spatSample, split, spin, stdev, stretch, subset, subst, summary, Summary, surfArea, svc, symdif, t, thin, thinNodes, metags, "metags<-", tail, tapp, terrain, thresh, tighten, makeNodes, makeTiles, time, timeInfo, "time<-", text, toMemory, trans, trim, units, union, "units<-", unique, unwrap, update, vect, values, "values<-", viewshed, voronoi, vrt, weighted.mean, where.min, where.max, which.lyr, which.min, which.max, which.lyr, width, window, "window<-", writeCDF, writeRaster, wrap, wrapCache, writeStart, writeStop, writeVector, writeValues, xmin, xmax, "xmin<-", "xmax<-", xres, xFromCol, xyFromCell, xFromCell, ymin, ymax, "ymin<-", "ymax<-", yres, yFromCell, yFromRow, zonal, zoom, cbind2, readRDS, saveRDS, unserialize, serialize, xapp, area, colSums, rowSums, colMeans, rowMeans)
55

66
exportMethods(watershed, pitfinder, NIDP, flowAccumulation)
77

NEWS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## bug fixes
44

5-
- `spatSample<SpatRaster>(method="stratified")` could cause an out of bounds error [#1858](https://github.com/rspatial/terra/issues/1858) by Felipe
5+
- `spatSample<SpatRaster>(method="stratified")` could cause an out of bounds error [#1858](https://gi[#1848]thub.com/rspatial/terra/issues/1858) by Felipe)
6+
- `vrt` on OSX had trouble with options [#1410](https://github.com/rspatial/terra/issues/1410) by Andrea Manica. And occaisionaly on Windows [#1848](https://github.com/rspatial/terra/issues/1848) by Monika Anna Tomaszewska; due to passing them as a dangling pointer.
67

78
## enhancements
89

@@ -17,6 +18,7 @@ https://github.com/rspatial/terra/issues/1993) by Enrico Mattea
1718

1819
- `mosaic( , fun="blend")` method to combine rasters with smooth gradients in overlapping zones [#2011](https://github.com/rspatial/terra/issues/2011) by Greg Schmidt
1920
- `animate<SpatVectorCollection>` method. [#2065](https://github.com/rspatial/terra/pull/2065) by Márcia Barbosa
21+
- `thin<SpatVector>` method. [#1738](https://github.com/rspatial/terra/issues/1738) by Andrés
2022

2123

2224
# version 1.9-11

R/Agenerics.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ if (!isGeneric("focalPairs")) { setGeneric("focalPairs", function(x, ...) standa
111111
if (!isGeneric("clearance")) {setGeneric("clearance", function(x, ...) standardGeneric("clearance"))}
112112
if (!isGeneric("width")) {setGeneric("width", function(x, ...) standardGeneric("width"))}
113113
if (!isGeneric("simplifyGeom")) {setGeneric("simplifyGeom", function(x, ...) standardGeneric("simplifyGeom"))}
114-
if (!isGeneric("thinGeom")) {setGeneric("thinGeom", function(x, ...) standardGeneric("thinGeom"))}
114+
if (!isGeneric("thinNodes")) {setGeneric("thinNodes", function(x, ...) standardGeneric("thinNodes"))}
115115
if (!isGeneric("mergeLines")) {setGeneric("mergeLines", function(x, ...) standardGeneric("mergeLines"))}
116116
if (!isGeneric("mergeTime")) {setGeneric("mergeTime", function(x, ...) standardGeneric("mergeTime"))}
117117
if (!isGeneric("fillTime")) {setGeneric("fillTime", function(x, ...) standardGeneric("fillTime"))}
@@ -256,6 +256,7 @@ if (!isGeneric("inMemory")) {setGeneric("inMemory", function(x, ...) standardGen
256256
if (!isGeneric("sources")) {setGeneric("sources", function(x, ...) standardGeneric("sources"))}
257257
if (!isGeneric("spatSample")) { setGeneric("spatSample", function(x, ...) standardGeneric("spatSample"))}
258258
if (!isGeneric("terrain")) {setGeneric("terrain", function(x, ...) standardGeneric("terrain"))}
259+
if (!isGeneric("thin")) {setGeneric("thin", function(x, ...) standardGeneric("thin"))}
259260
if (!isGeneric("has.time")) {setGeneric("has.time", function(x,...) standardGeneric("has.time"))}
260261
if (!isGeneric("time")) {setGeneric("time", function(x,...) standardGeneric("time"))}
261262
if (!isGeneric("time<-")) {setGeneric("time<-", function(x, ..., value) standardGeneric("time<-"))}

R/distance.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ setMethod("distance", signature(x="data.frame", y="missing"),
239239
)
240240

241241

242+
setMethod("thin", signature(x="SpatVector"),
243+
function(x, d, unit="m") {
244+
opt <- spatOptions()
245+
x@pntr <- x@pntr$thin_geoms(d, unit, opt)
246+
messages(x, "thin")
247+
}
248+
)
249+
250+
242251
setMethod("direction", signature(x="SpatRaster"),
243252
function(x, from=FALSE, degrees=FALSE, method="cosine", filename="", ...) {
244253
opt <- spatOptions(filename, ...)

R/geom.R

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,10 +539,12 @@ setMethod("simplifyGeom", signature(x="SpatVector"),
539539
}
540540
)
541541

542-
setMethod("thinGeom", signature(x="SpatVector"),
543-
function(x, threshold=1e-6, makeValid=TRUE) {
544-
x@pntr <- x@pntr$thin(threshold)
545-
x <- messages(x, "thinGeom")
542+
setMethod("thinNodes", signature(x="SpatVector"),
543+
function(x, d=1e-6, unit="m", makeValid=TRUE) {
544+
stopifnot(unit[1] %in% c("m", "km"))
545+
if (unit[1] == "km") d <- d * 1000
546+
x@pntr <- x@pntr$thin_nodes(d)
547+
x <- messages(x, "thinNodes")
546548
if (makeValid) {
547549
x <- makeValid(x)
548550
}

man/densify.Rd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Add additional nodes to lines or polygons. This can be useful to do prior to usi
2828
SpatVector
2929
}
3030
31-
\seealso{\code{\link{simplifyGeom}}}
31+
\seealso{\code{\link{simplifyGeom}}, \code{\link{thinNodes}}}
3232
3333
\examples{
3434
v <- vect(rbind(c(-120,-20), c(-80,5), c(-40,-60), c(-120,-20)),

man/thin.Rd

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
\name{thin}
2+
3+
\docType{methods}
4+
5+
\alias{thin}
6+
\alias{thin,SpatVector-method}
7+
8+
\alias{thinNodes}
9+
\alias{thinNodes,SpatVector-method}
10+
11+
\title{Subset geometries by minimum distance}
12+
13+
\description{
14+
\code{thin} return a subset of geometries such that all remaining geometries are at least \code{d} apart from each other. This uses greedy spatial thinning: the first geometry is always kept, and subsequent geometries are only kept if they are at least \code{d} away from all previously kept geometries.
15+
16+
\code{thinNodes} reduces the number of nodes to represent line or polygon geometries
17+
}
18+
19+
\usage{
20+
\S4method{thin}{SpatVector}(x, d, unit="m")
21+
22+
\S4method{thinNodes}{SpatVector}(x, d, unit="m", makeValid=TRUE)
23+
}
24+
25+
\arguments{
26+
\item{x}{SpatVector}
27+
\item{d}{positive numeric. The minimum distance between geometries or nodes}
28+
\item{unit}{character. \code{"m"} (meter, the default) or \code{"km"} (kilometer)}
29+
\item{makeValid}{logical. If \code{TRUE} an attempt is made to assure that thinned polygon geometries are valid (e.g., not self intersecting)}
30+
}
31+
32+
\value{
33+
SpatVector
34+
}
35+
36+
\seealso{\code{\link{densify}}, \code{\link{distance}}, \code{\link{nearby}}, \code{\link{nearest}}}
37+
38+
\examples{
39+
p <- vect(rbind(c(0,0), c(0.5,0.5), c(0.6, 0.6), c(5,5), c(5.5, 5.5), c(50, 50)), crs="+proj=longlat +datum=WGS84")
40+
values(p) <- data.frame(id=1:6)
41+
nrow(p)
42+
43+
# points that are at least 200 km apart
44+
p2 <- thin(p, 200000)
45+
nrow(p2)
46+
47+
# same, using km
48+
p3 <- thin(p, 200, unit="km")
49+
nrow(p3)
50+
}
51+
52+
\keyword{spatial}

src/RcppModule.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ RCPP_MODULE(spat){
472472
.method("rotate_longitude", &SpatVector::rotate_longitude)
473473
.method("line_merge", &SpatVector::line_merge)
474474
.method("simplify", &SpatVector::simplify)
475-
.method("thin", &SpatVector::thin)
475+
.method("thin_geoms", &SpatVector::thin_geoms)
476+
.method("thin_nodes", &SpatVector::thin_nodes)
476477
//.method("shared_paths", &SpatVector::shared_paths)
477478
.method("shared_paths", (SpatVector (SpatVector::*)(bool))( &SpatVector::shared_paths))
478479
.method("shared_paths2", (SpatVector (SpatVector::*)(SpatVector, bool))( &SpatVector::shared_paths))

src/distVector.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,3 +1792,95 @@ void SpatVector::fix_lonlat_overflow() {
17921792
}
17931793
return;
17941794
}
1795+
1796+
1797+
SpatVector SpatVector::thin_geoms(double d, std::string unit, SpatOptions &opt) {
1798+
1799+
SpatVector out;
1800+
size_t n = size();
1801+
if (n == 0) {
1802+
out.setError("empty SpatVector");
1803+
return out;
1804+
}
1805+
if (d <= 0) {
1806+
out.setError("d must be > 0");
1807+
return out;
1808+
}
1809+
1810+
bool lonlat = is_lonlat();
1811+
double m = 1;
1812+
if (!srs.m_dist(m, lonlat, unit)) {
1813+
setError("invalid unit");
1814+
return out;
1815+
}
1816+
// d_internal is in the native distance unit (meters for lonlat, CRS units for planar)
1817+
double d_internal = d / m;
1818+
1819+
out.srs = srs;
1820+
out.reserve(n);
1821+
1822+
std::string gtype = type();
1823+
1824+
if (gtype == "points") {
1825+
std::vector<std::vector<double>> pts = coordinates();
1826+
std::vector<double> &px = pts[0];
1827+
std::vector<double> &py = pts[1];
1828+
1829+
std::vector<size_t> keep;
1830+
keep.push_back(0);
1831+
1832+
if (lonlat) {
1833+
for (size_t i = 1; i < n; i++) {
1834+
bool far_enough = true;
1835+
for (size_t j = 0; j < keep.size(); j++) {
1836+
size_t k = keep[j];
1837+
if (distLonlat(px[i], py[i], px[k], py[k]) < d_internal) {
1838+
far_enough = false;
1839+
break;
1840+
}
1841+
}
1842+
if (far_enough) {
1843+
keep.push_back(i);
1844+
}
1845+
}
1846+
} else {
1847+
for (size_t i = 1; i < n; i++) {
1848+
bool far_enough = true;
1849+
for (size_t j = 0; j < keep.size(); j++) {
1850+
size_t k = keep[j];
1851+
if (distance_plane(px[i], py[i], px[k], py[k]) < d_internal) {
1852+
far_enough = false;
1853+
break;
1854+
}
1855+
}
1856+
if (far_enough) {
1857+
keep.push_back(i);
1858+
}
1859+
}
1860+
}
1861+
out = subset_rows(keep);
1862+
} else {
1863+
// lines and polygons: distance() returns in the user's unit
1864+
std::vector<size_t> keep;
1865+
keep.push_back(0);
1866+
for (size_t i = 1; i < n; i++) {
1867+
SpatVector vi = subset_rows((long)i);
1868+
bool far_enough = true;
1869+
for (size_t j = 0; j < keep.size(); j++) {
1870+
SpatVector vk = subset_rows((long)keep[j]);
1871+
std::vector<double> dd = vi.distance(vk, true, unit, "geo", false, opt);
1872+
if (dd.size() > 0 && dd[0] < d) {
1873+
far_enough = false;
1874+
break;
1875+
}
1876+
}
1877+
if (far_enough) {
1878+
keep.push_back(i);
1879+
}
1880+
}
1881+
out = subset_rows(keep);
1882+
}
1883+
return out;
1884+
}
1885+
1886+

src/spatVector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class SpatVector {
204204

205205
std::vector<double> distance(bool sequential, std::string unit, const std::string method, bool by_node, SpatOptions &opt);
206206
std::vector<double> distance(SpatVector x, bool pairwise, std::string unit, const std::string method, bool by_node, SpatOptions &opt);
207+
SpatVector thin_geoms(double d, std::string unit, SpatOptions &opt);
207208
std::vector<double> pointdistance(const std::vector<double>& px, const std::vector<double>& py, const std::vector<double>& sx, const std::vector<double>& sy, bool pairwise, double m, bool lonlat, std::string method);
208209

209210
// std::vector<double> pointdistance_seq(const std::vector<double>& px, const std::vector<double>& py, double m, bool lonlat);
@@ -336,7 +337,7 @@ class SpatVector {
336337
SpatVector shared_paths(SpatVector x, bool index);
337338
SpatVector snap(double tolerance);
338339
SpatVector snapto(SpatVector y, double tolerance);
339-
SpatVector thin(double threshold);
340+
SpatVector thin_nodes(double threshold);
340341
SpatVector split_lines(SpatVector v);
341342
SpatVector allerretour();
342343
SpatVectorCollection bienvenue();

0 commit comments

Comments
 (0)