Skip to content

Commit 6ed2da5

Browse files
committed
seemingly working intersection
1 parent 2b0a8e9 commit 6ed2da5

16 files changed

+455
-0
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Generated by roxygen2: do not edit by hand
22

33
export(dst_interpolate_aw)
4+
export(dst_intersection)
45
export(sf_use_ducksf)
56
export(st_interpolate_aw_ducksf)

R/dst_intersection.R

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#' Intersect geometries (DuckDB-backed, sf-compatible)
2+
#' @export
3+
dst_intersection <- function(
4+
x,
5+
y,
6+
duckdb_threads = getOption("ducksf.intersection.threads", NULL),
7+
compute_geometry = TRUE, # FALSE → just (xid,yid)
8+
join = c("intersects", "dwithin0") # "intersects" = sf-exact, "dwithin0" = fast path
9+
) {
10+
join <- match.arg(join)
11+
12+
# Unary/n-ary case: defer to sf for exact semantics (origins, n.overlaps, etc.)
13+
if (missing(y)) {
14+
return(sf::st_intersection(x))
15+
}
16+
17+
# sfg → sfc
18+
x_is_sfg <- inherits(x, "sfg")
19+
if (x_is_sfg) {
20+
x <- sf::st_sfc(x, crs = sf::st_crs(x))
21+
}
22+
if (inherits(y, "sfg")) {
23+
y <- sf::st_sfc(y, crs = sf::st_crs(y))
24+
}
25+
26+
# CRS must match (sf semantics)
27+
if (!isTRUE(sf::st_crs(x) == sf::st_crs(y))) {
28+
stop("st_crs(x) and st_crs(y) must be identical; transform first.")
29+
}
30+
out_crs <- sf::st_crs(x)
31+
32+
# Wrap as sf for registration/attrs
33+
x_sf <- if (inherits(x, "sf")) x else sf::st_sf(geometry = x)
34+
y_sf <- if (inherits(y, "sf")) y else sf::st_sf(geometry = y)
35+
36+
con <- ducksf_duck_connect(threads = duckdb_threads)
37+
on.exit(ducksf_duck_disconnect(con), add = TRUE)
38+
.ducksf_register_sf(con, x_sf, "x_tbl", overwrite = TRUE)
39+
.ducksf_register_sf(con, y_sf, "y_tbl", overwrite = TRUE)
40+
41+
on_pred <- if (join == "dwithin0") {
42+
"ST_DWithin(x.geometry, y.geometry, 0)"
43+
} else {
44+
"ST_Intersects(x.geometry, y.geometry)"
45+
}
46+
select_geom <- if (isTRUE(compute_geometry)) {
47+
"ST_Intersection(x.geometry, y.geometry) AS geometry"
48+
} else {
49+
"NULL::GEOMETRY AS geometry"
50+
}
51+
52+
DBI::dbExecute(
53+
con,
54+
glue::glue(
55+
"
56+
CREATE OR REPLACE VIEW _ducksf_pairs AS
57+
WITH
58+
x AS (SELECT ROW_NUMBER() OVER () AS xid, geometry FROM x_tbl),
59+
y AS (SELECT ROW_NUMBER() OVER () AS yid, geometry FROM y_tbl)
60+
SELECT x.xid, y.yid, {select_geom}
61+
FROM x
62+
JOIN y
63+
ON {on_pred}
64+
ORDER BY x.xid, y.yid; -- deterministic for tests
65+
"
66+
)
67+
)
68+
69+
res <- dplyr::tbl(con, "_ducksf_pairs") |>
70+
arrow::to_arrow() |>
71+
as.data.frame()
72+
xid <- as.integer(res$xid)
73+
yid <- as.integer(res$yid)
74+
75+
if (inherits(x, "sf")) {
76+
df_x <- sf::st_drop_geometry(x_sf)[xid, , drop = FALSE]
77+
if (inherits(y, "sf")) {
78+
df_y <- sf::st_drop_geometry(y_sf)[yid, , drop = FALSE]
79+
df <- data.frame(df_x, df_y, check.names = TRUE)
80+
} else {
81+
df <- df_x
82+
}
83+
geom <- if (isTRUE(compute_geometry)) {
84+
sf::st_as_sfc(res$geometry, crs = out_crs)
85+
} else {
86+
sf::st_sfc(rep(sf::st_geometrycollection(), nrow(res)), crs = out_crs)
87+
}
88+
sf_col <- attr(x_sf, "sf_column")
89+
df[[sf_col]] <- geom
90+
return(sf::st_sf(df, sf_column_name = sf_col))
91+
}
92+
93+
geom <- if (isTRUE(compute_geometry)) {
94+
sf::st_as_sfc(res$geometry, crs = out_crs)
95+
} else {
96+
sf::st_sfc(rep(sf::st_geometrycollection(), nrow(res)), crs = out_crs)
97+
}
98+
idx <- cbind(xid, yid)
99+
dimnames(idx) <- NULL
100+
attr(geom, "idx") <- idx
101+
102+
if (x_is_sfg) {
103+
if (!length(geom)) {
104+
return(sf::st_geometrycollection())
105+
}
106+
return(geom[[1]])
107+
}
108+
geom
109+
}

man/dst_intersection.Rd

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

man/ducksf_apply_keep_na.Rd

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

man/ducksf_build_denom.Rd

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

man/ducksf_build_interpolated_sf_view.Rd

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

man/ducksf_build_overlap.Rd

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

man/ducksf_build_proj_views.Rd

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

man/ducksf_check_cols_present.Rd

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

man/ducksf_collect_output.Rd

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

0 commit comments

Comments
 (0)