suppressPackageStartupMessages(library(sf))

p = st_point(c(1/3,1/6))
st_sfc(p, precision = 1000)
st_as_sfc(st_as_binary(st_sfc(p, precision = 0L)))
st_as_sfc(st_as_binary(st_sfc(p, precision = 1000)))
st_as_sfc(st_as_binary(st_sfc(p, precision = 1000000)))
st_as_sfc(st_as_binary(st_sfc(p, precision = 10L)))
st_as_sfc(st_as_binary(st_sfc(p, precision = -1)))

d = data.frame(a = 1:2)
d$geom = c("POINT(0 0)", "POINT(1 1)")

st_as_sf(d, wkt = "geom")
st_as_sf(d, wkt = 2)
st_as_sf(d, wkt = "geom", remove = FALSE)

st_as_sfc(c("POINT(0 0)", "POINT(1 1)"))
st_as_sfc(c("POINT(0 0)", "POINT(1 1)", "POLYGON((0 0,1 1,0 1,0 0))"))
st_as_sfc(character(0))
x = st_as_sfc(character(0), 4326)
y = st_as_sfc(character(0), crs = 4326)
all.equal(x, y)
st_as_sfc(c("POINT(0 0)", "POINT(1 1)", "POLYGON((0 0,1 1,0 1,0 0))"),
	"+proj=longlat +datum=WGS84")
dg = st_as_sf(d, wkt = "geom")
print(dg, n = 1)
head(st_as_sf(d, wkt = "geom"), 1)

d$geom = st_as_sfc(d$geom)
d1 = d
attr(d1, "sf_col") = "geom"
st_geometry(d1) = d$geom

d$geometry = d$geom # second geometry list-column
if (require(testthat, quietly = TRUE)) {
 expect_warning(st_geometry(d) <- d$geom)
}
d

x = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326)
# don't warn when replacing crs with identical value:
st_sfc(x, crs = 4326)
y = st_sfc(x, crs = "+proj=longlat +datum=WGS84 +no_defs")
# but do when it changes:
y = st_sfc(x, crs = 3857)

p = st_point(0:1)
st_cast(p, "MULTIPOINT")
mp = st_multipoint(rbind(c(0,1), c(2,2)))
st_cast(mp, "POINT")
st_cast(mp, "MULTIPOINT")

# geometry collection to its elements:
st_cast(st_geometrycollection(list(mp)), "POINT")
st_cast(st_geometrycollection(list(mp)), "MULTIPOINT")
st_cast(st_geometrycollection(list(p,mp)), "MULTIPOINT")

mp = st_multipoint(rbind(c(0,1)))
x = st_sfc(p, mp)
st_cast(x, "POINT")

sf = st_sf(a = 3:2, geom = x)
st_cast(sf, "POINT")


x |> st_cast("POINT")

# points:
mp = st_multipoint(rbind(c(0,1))) # single-point multipoint
st_sfc(p,mp) |> st_cast("POINT")
st_sfc(p,mp) |> st_cast("MULTIPOINT")

# lines:
pts = rbind(c(0,0), c(1,1), c(2,1))
st_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast("LINESTRING")
st_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast("MULTILINESTRING")

# polygons:
pts = rbind(c(0,0), c(1,1), c(0,1), c(0,0))
st_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast("POLYGON")
st_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast("MULTIPOLYGON")


st_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |> st_cast()
st_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |>
	st_cast() |>
	st_cast("POINT")

p = rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))
pol = st_polygon(list(p))
# plot(pol)
try(plot(st_polygonize(pol))) # --> breaks
st_length(st_sfc(st_point(c(0,0))))

try(as(st_sfc(st_linestring(matrix(1:9,3))), "Spatial"))

# check conus is present:
x = st_sfc(st_point(c(-90,35)), st_point(c(-80,36)),
	crs = "+proj=longlat +datum=NAD27")
y = st_transform(x, 3857)

## IGNORE_RDIFF_BEGIN
sf_extSoftVersion()[1:3]
## IGNORE_RDIFF_END

# Ops.sfc:
ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))))
ls * 2
ls - 2
(ls + 2) %% 3
ls / ls
p_ = st_point(0:1)
ll = st_sfc(ls[[1]], p_)
ll & st_sfc(p_)
ll | st_sfc(p_)
ll %/% st_sfc(p_)
ll == st_sfc(p_)
ll != st_sfc(p_)


str(x)
nc = st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
str(nc)
bb = st_as_sfc(st_bbox(nc))
format(st_bbox(nc))

st_agr("constant")
st_agr()
x <- st_sf(a = 1:2, b = 3:4, geom = x, agr = c("constant", "aggregate"))
y <- x |> st_set_agr("constant")
y

sf1 <- st_sf(a = c("x", "y"), geom = st_sfc(st_point(3:4), st_point(3:4)))
sf1[names(sf1)]

st_bbox(sf1)
bb = st_bbox(nc)
bb
st_crs(bb)
st_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = st_crs(4326))
st_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = 4326)

bb$xrange
bb$yrange
bb$xmin
bb$ymin
bb$xmax
bb$ymax
try(bb$foo)

# merge:
a = data.frame(a = 1:3, b = 5:7)
st_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))
b = data.frame(x = c("a", "b", "c"), b = c(2,5,6))
merge(a, b)
merge(a, b, all = TRUE)

if (require(dplyr, quietly = TRUE)) {
# joins:
inner_join(a, b)
left_join(a, b)
right_join(a, b)
full_join(a, b)
semi_join(a, b)
anti_join(a, b)
left_join(a, data.frame(b, geometry = 1), by = "b")
}

# st_joins:
a = st_sf(a = 1:3,
 geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))
b = st_sf(a = 11:14,
 geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))
st_join(a, b)
st_join(a, b, left = FALSE)
# st_join, largest = TRUE:
nc <- st_transform(st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE), 2264)
gr = st_sf(
    label = apply(expand.grid(1:10, LETTERS[10:1])[,2:1], 1, paste0, collapse = " "),
	geom = st_make_grid(st_as_sfc(st_bbox(nc))))
gr$col = sf.colors(10, categorical = TRUE, alpha = .3)
# cut, to check, NA's work out:
gr = gr[-(1:30),]
st_join(nc, gr, largest = TRUE)

# rbind:
x = st_sf(a = 1:2, geom = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326))
rbind(x, x, x)
nc2 = rbind(nc[1:50, ], nc[51:100, ])
all.equal(nc, nc2)

# st_sample:
suppressWarnings(RNGversion("3.5.3"))
set.seed(131)
options(digits=6)
x = st_sfc(st_polygon(list(rbind(c(0,1),c(90,1),c(90,90),c(0,90),c(0,1)))), crs = st_crs(4326))
  (p <- st_sample(x, 10))
  p <- st_sample(x[[1]], 10) # sfg method
x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:
p <- st_sample(x, 10)
x = st_sfc(st_polygon(list(rbind(c(-180,-90),c(180,-90),c(180,90),c(-180,90),c(-180,-90)))),
 crs=st_crs(4326))
#FIXME:
# if (sf_extSoftVersion()[["proj.4"]] >= "4.9.0") # lwgeom breaks on this
#   (p <- st_sample(x, 10))
pt = st_multipoint(matrix(1:20,,2))
st_sample(p, 3)
try(st_sample(p, 3.3))
ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),
 st_linestring(rbind(c(0,0),c(.1,0))),
 st_linestring(rbind(c(0,1),c(.1,1))),
 st_linestring(rbind(c(2,2),c(2,2.00001))))
st_sample(ls, 80)
st_sample(nc[1:2,], size = c(10,20))
# try with LINES, LongLat, should generate a warning:
nc[1:2,] |> st_transform(4326) |> st_cast("MULTILINESTRING") |> st_sample(size = c(10,20))
st_sample(ls, 80, type = "regular")
p_sample = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = FALSE))
lengths(p_sample)
p_sample_exact = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = TRUE))
lengths(p_sample_exact)
#plot(nc$geometry[1])
#plot(p_sample[[1]], add = TRUE)
#plot(p_sample_exact[[1]], add = TRUE)

if (require(dplyr, quietly = TRUE)) {
 #class(st_bind_cols(nc, as.data.frame(nc)[1:3]))
 print(class(dplyr::bind_cols(nc, as.data.frame(nc)[1:3])))
}
class(rbind(nc, nc))
class(cbind(nc, nc))

x = st_sfc(st_point(0:1), st_point(2:3))
x[c(NA,1,NA,2,NA)]

# jitter
pts = st_centroid(st_geometry(nc))
plot(pts)
plot(st_jitter(pts, .05), add = TRUE, col = 'red')
plot(st_geometry(nc))
plot(st_jitter(st_geometry(nc), factor = .01), add = TRUE, col = '#ff8888')
st_jitter(st_sfc(st_point(0:1)), amount = .1)

# st_bbox:
if (suppressPackageStartupMessages(require(sp, quietly = TRUE)) && require(raster, quietly = TRUE)) {
demo(meuse, ask = FALSE, echo = FALSE)
suppressWarnings(st_bbox(meuse))
crs = suppressWarnings(st_crs(meuse))
suppressWarnings(st_bbox(raster(meuse.grid)))
st_bbox(extent(raster()))
}

# st_to_s2
if (FALSE) { # stops working with GDAL 2.3.0 / PROJ 5.0.1:
 x = sf:::st_to_s2(nc)
 x1 = st_geometry(x)
 cc = st_coordinates(x1)
 summary(sqrt(cc[,1]^2+cc[,2]^2+cc[,3]^2))
}

# check_ring_dir
m = rbind(c(0,0), c(0,1), c(1,1), c(1,0), c(0,0))
mi = m[nrow(m):1,]
pol = st_polygon(list(m * 10, m + .5, mi + 1.5, mi + 3.5, m + 5, mi + 6.5))
st_sfc(pol)
x = st_sfc(pol, check_ring_dir=TRUE)
y = st_sf(a = 1, geom = st_sfc(pol), check_ring_dir=TRUE)
str(x)
x = st_sfc(st_polygon(), st_polygon(), check_ring_dir=TRUE)
str(x)
# empty ring/zero area:
x = st_sfc(st_polygon(list(m[c(1,3,1),])), check_ring_dir=TRUE)

mp = st_multipolygon(list(pol, pol))
try(x <- st_sfc(mp, st_polygon(), check_ring_dir=TRUE))
x <- st_sfc(mp, pol) |> st_cast("MULTIPOLYGON") |> st_sfc(check_ring_dir=TRUE)
x
str(x)

x = st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326)
st_wrap_dateline(st_sf(a = 1, geometry = x))
st_wrap_dateline(x)
st_wrap_dateline(x[[1]])

geo <- c("{\"geodesic\":true,\"type\":\"Point\",\"coordinates\":[-118.68152563269095,36.43764870908927]}",
         "{\"geodesic\":true,\"type\":\"Point\",\"coordinates\":[-118.67408758213843,36.43366018922779]}",
         "{\"geodesic\":true,\"type\":\"Point\",\"coordinates\":[-118.67708346361097,36.44208638659282]}",
         "{\"geodesic\":true,\"type\":\"Point\",\"coordinates\":[-118.67886661944996,36.44110273135671]}",
         "{\"geodesic\":true,\"type\":\"Point\",\"coordinates\":[-118.68089232041565,36.44173155205561]}")
st_as_sfc(geo, GeoJSON = TRUE)
st_as_sfc(geo, GeoJSON = TRUE, crs = 4326)

st_as_sfc(st_as_binary(st_sfc(st_point(0:1)))[[1]], crs = 4326)

x = nc
x$geom = NULL
class(x)

st_as_sfc(list(st_point(0:1)), crs = 4326)

# crop:
box = c(xmin = 0, ymin = 0, xmax = 1, ymax = 1)

pol = st_sfc(st_buffer(st_point(c(.5, .5)), .65))
pol_sf = st_sf(a=1, geom=pol)

st_crop(pol, box)
st_crop(pol, st_bbox(box))
st_crop(pol_sf, box)
st_crop(pol_sf, st_bbox(box))

# new sample methods:
x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:
p <- st_sample(x, 10, type = "regular")
p <- st_sample(x, 10, type = "hexagonal")

all.equal(st_drop_geometry(pol_sf), st_set_geometry(pol_sf, NULL))

# https://github.com/r-spatial/sf/issues/1024
shape1 <-st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0)))))
shape2 <- st_sfc(st_polygon())
shape3 <- st_sfc(st_polygon())

shape4 = st_intersection(shape2, shape3) # has zero features

st_difference(shape1, shape4)
st_difference(shape4, shape1)
st_sym_difference(shape1, shape4)
st_union(shape1, shape4)
st_union(shape4, shape1)

# transform empty:
tr = st_sf(geom=st_sfc()) |> st_set_crs(3587) |> st_transform(4326)

# NA values are converted to empty; #1114:
x <- data.frame(name=LETTERS)
y <- data.frame(name=LETTERS[1:13], letters[14:26])
y$geometry <- st_sfc(st_point(c(0,0)))
y <- st_sf(y)
out = merge(x, y, all.x=TRUE)
class(out)

st_as_sf(st_sfc(st_point(0:1)))

# st_exterior_ring():
outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)
hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)
hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)
pts = list(outer, hole1, hole2)
pl1 = st_polygon(pts)
mpl1 = st_multipolygon(list(pl1,pl1+20))

spl1 = st_as_sfc(list(pl1),crs=4326)
smpl1 = st_as_sfc(list(mpl1),crs=4326)

st_exterior_ring(spl1[[1]])
st_exterior_ring(spl1)
st_exterior_ring(st_sf(a = 1, geom = spl1))
st_exterior_ring(smpl1[[1]])
st_exterior_ring(st_sfc(smpl1))
st_exterior_ring(st_sf(a = 1, geom = st_sfc(smpl1)))

'{"type":"Polygon","coordinates":[[]]}' |> read_sf() |> st_is_empty()
# '{"type":"Polygon","coordinates":[]}' |> read_sf() |> st_is_empty() # breaks on GDAL < 3.9 or so
'{"type":"MultiPolygon","coordinates":[[[]]]}' |> read_sf() |> st_is_empty()
'{"type":"MultiPolygon","coordinates":[[]]}' |> read_sf() |> st_is_empty()
