Skip to content

Commit 5cdd168

Browse files
committed
fixes #2406
1 parent afbb1e8 commit 5cdd168

File tree

6 files changed

+102
-3
lines changed

6 files changed

+102
-3
lines changed

NAMESPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ S3method(st_difference,sfc)
217217
S3method(st_difference,sfg)
218218
S3method(st_drop_geometry,default)
219219
S3method(st_drop_geometry,sf)
220+
S3method(st_exterior_ring,sf)
221+
S3method(st_exterior_ring,sfc)
222+
S3method(st_exterior_ring,sfg)
220223
S3method(st_filter,sf)
221224
S3method(st_geometry,sf)
222225
S3method(st_geometry,sfc)
@@ -447,6 +450,7 @@ export(st_drivers)
447450
export(st_drop_geometry)
448451
export(st_equals)
449452
export(st_equals_exact)
453+
export(st_exterior_ring)
450454
export(st_filter)
451455
export(st_geometry)
452456
export(st_geometry_type)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# version 1.0-17
22

3+
* add `st_exterior_ring()` to extract exterior rings (remove holes); #2406
4+
35
* add `text.sf()`, `text.sfc()`, `points.sf()`, `points.sfc()` to annotate base plots at geometry centroids; #2399
46

57
* `st_sf()` no longer strips `tbl` or `tbl_df` class labels; #2378

R/geom-transformers.R

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,3 +1149,29 @@ st_line_interpolate = function(line, dist, normalized = FALSE) {
11491149
st_sfc(CPL_line_interpolate(recycled[[1]], recycled[[2]], normalized),
11501150
crs = st_crs(line))
11511151
}
1152+
1153+
#' @export
1154+
#' @name geos_unary
1155+
st_exterior_ring = function(x, ...) UseMethod("st_exterior_ring")
1156+
1157+
#' @export
1158+
st_exterior_ring.sf = function(x, ...)
1159+
st_set_geometry(x, st_exterior_ring(st_geometry(x)))
1160+
1161+
#' @export
1162+
st_exterior_ring.sfg = function(x, ...)
1163+
st_exterior_ring(st_sfc(x))[[1]]
1164+
1165+
#' @export
1166+
st_exterior_ring.sfc = function(x, ...) {
1167+
stopifnot(all(st_dimension(x, NA_if_empty = FALSE) == 2))
1168+
exterior_sfg = function(x) {
1169+
if (inherits(x, "MULTIPOLYGON"))
1170+
st_multipolygon(lapply(st_cast(st_sfc(x), "POLYGON"), exterior_sfg))
1171+
else if (inherits(x, "POLYGON"))
1172+
st_polygon(x[1])
1173+
else
1174+
stop(paste("no exterior_ring method for objects of class", class(x)[1]))
1175+
}
1176+
st_as_sfc(lapply(x, exterior_sfg), crs = st_crs(x))
1177+
}

man/geos_unary.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/sfc.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,21 @@ out = merge(x, y, all.x=TRUE)
340340
class(out)
341341

342342
st_as_sf(st_sfc(st_point(0:1)))
343+
344+
# st_exterior_ring():
345+
outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)
346+
hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)
347+
hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)
348+
pts = list(outer, hole1, hole2)
349+
pl1 = st_polygon(pts)
350+
mpl1 = st_multipolygon(list(pl1,pl1+20))
351+
352+
spl1 = st_as_sfc(list(pl1),crs=4326)
353+
smpl1 = st_as_sfc(list(mpl1),crs=4326)
354+
355+
st_exterior_ring(spl1[[1]])
356+
st_exterior_ring(spl1)
357+
st_exterior_ring(st_sf(a = 1, geom = spl1))
358+
st_exterior_ring(smpl1[[1]])
359+
st_exterior_ring(st_sfc(smpl1))
360+
st_exterior_ring(st_sf(a = 1, geom = st_sfc(smpl1)))

tests/sfc.Rout.save

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
R version 4.3.3 (2024-02-29) -- "Angel Food Cake"
2+
R version 4.4.0 (2024-04-24) -- "Puppy Cup"
33
Copyright (C) 2024 The R Foundation for Statistical Computing
4-
Platform: x86_64-pc-linux-gnu (64-bit)
4+
Platform: x86_64-pc-linux-gnu
55

66
R is free software and comes with ABSOLUTELY NO WARRANTY.
77
You are welcome to redistribute it under certain conditions.
@@ -1086,6 +1086,52 @@ CRS: NA
10861086
x
10871087
1 POINT (0 1)
10881088
>
1089+
> # st_exterior_ring():
1090+
> outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)
1091+
> hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)
1092+
> hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)
1093+
> pts = list(outer, hole1, hole2)
1094+
> pl1 = st_polygon(pts)
1095+
> mpl1 = st_multipolygon(list(pl1,pl1+20))
1096+
>
1097+
> spl1 = st_as_sfc(list(pl1),crs=4326)
1098+
> smpl1 = st_as_sfc(list(mpl1),crs=4326)
1099+
>
1100+
> st_exterior_ring(spl1[[1]])
1101+
POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
1102+
> st_exterior_ring(spl1)
1103+
Geometry set for 1 feature
1104+
Geometry type: POLYGON
1105+
Dimension: XY
1106+
Bounding box: xmin: 0 ymin: 0 xmax: 10 ymax: 10
1107+
Geodetic CRS: WGS 84
1108+
POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
1109+
> st_exterior_ring(st_sf(a = 1, geom = spl1))
1110+
Simple feature collection with 1 feature and 1 field
1111+
Geometry type: POLYGON
1112+
Dimension: XY
1113+
Bounding box: xmin: 0 ymin: 0 xmax: 10 ymax: 10
1114+
Geodetic CRS: WGS 84
1115+
a geom
1116+
1 1 POLYGON ((0 0, 10 0, 10 10,...
1117+
> st_exterior_ring(smpl1[[1]])
1118+
MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 20)))
1119+
> st_exterior_ring(st_sfc(smpl1))
1120+
Geometry set for 1 feature
1121+
Geometry type: MULTIPOLYGON
1122+
Dimension: XY
1123+
Bounding box: xmin: 0 ymin: 0 xmax: 30 ymax: 30
1124+
Geodetic CRS: WGS 84
1125+
MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ...
1126+
> st_exterior_ring(st_sf(a = 1, geom = st_sfc(smpl1)))
1127+
Simple feature collection with 1 feature and 1 field
1128+
Geometry type: MULTIPOLYGON
1129+
Dimension: XY
1130+
Bounding box: xmin: 0 ymin: 0 xmax: 30 ymax: 30
1131+
Geodetic CRS: WGS 84
1132+
a geom
1133+
1 1 MULTIPOLYGON (((0 0, 10 0, ...
1134+
>
10891135
> proc.time()
10901136
user system elapsed
1091-
5.156 1.454 5.144
1137+
5.477 1.381 5.407

0 commit comments

Comments
 (0)