Skip to content

Commit 9b4d4de

Browse files
authored
Merge pull request #61 from r-spatial/dewey-attempt-matrix-index
Attempt indexed matrix
2 parents 37ad555 + bfac7fa commit 9b4d4de

20 files changed

+803
-167
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.DS_Store
44
.vscode
55
docs
6+
configure.log

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export(s2_make_line)
9393
export(s2_make_polygon)
9494
export(s2_max_distance)
9595
export(s2_max_distance_matrix)
96+
export(s2_may_intersect_matrix)
9697
export(s2_minimum_clearance_line_between)
9798
export(s2_num_points)
9899
export(s2_options)

R/RcppExports.R

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ cpp_s2_num_points <- function(geog) {
1717
.Call(`_s2_cpp_s2_num_points`, geog)
1818
}
1919

20+
cpp_s2_is_empty <- function(geog) {
21+
.Call(`_s2_cpp_s2_is_empty`, geog)
22+
}
23+
2024
cpp_s2_area <- function(geog) {
2125
.Call(`_s2_cpp_s2_area`, geog)
2226
}
@@ -101,6 +105,10 @@ cpp_s2_farthest_feature <- function(geog1, geog2) {
101105
.Call(`_s2_cpp_s2_farthest_feature`, geog1, geog2)
102106
}
103107

108+
cpp_s2_may_intersect_matrix <- function(geog1, geog2, maxEdgesPerCell, maxFeatureCells, s2options) {
109+
.Call(`_s2_cpp_s2_may_intersect_matrix`, geog1, geog2, maxEdgesPerCell, maxFeatureCells, s2options)
110+
}
111+
104112
cpp_s2_contains_matrix <- function(geog1, geog2, s2options) {
105113
.Call(`_s2_cpp_s2_contains_matrix`, geog1, geog2, s2options)
106114
}
@@ -113,14 +121,14 @@ cpp_s2_intersects_matrix <- function(geog1, geog2, s2options) {
113121
.Call(`_s2_cpp_s2_intersects_matrix`, geog1, geog2, s2options)
114122
}
115123

116-
cpp_s2_disjoint_matrix <- function(geog1, geog2, s2options) {
117-
.Call(`_s2_cpp_s2_disjoint_matrix`, geog1, geog2, s2options)
118-
}
119-
120124
cpp_s2_equals_matrix <- function(geog1, geog2, s2options) {
121125
.Call(`_s2_cpp_s2_equals_matrix`, geog1, geog2, s2options)
122126
}
123127

128+
cpp_s2_touches_matrix <- function(geog1, geog2, s2options) {
129+
.Call(`_s2_cpp_s2_touches_matrix`, geog1, geog2, s2options)
130+
}
131+
124132
cpp_s2_dwithin_matrix <- function(geog1, geog2, distance) {
125133
.Call(`_s2_cpp_s2_dwithin_matrix`, geog1, geog2, distance)
126134
}
@@ -133,6 +141,26 @@ cpp_s2_max_distance_matrix <- function(geog1, geog2) {
133141
.Call(`_s2_cpp_s2_max_distance_matrix`, geog1, geog2)
134142
}
135143

144+
cpp_s2_contains_matrix_brute_force <- function(geog1, geog2, s2options) {
145+
.Call(`_s2_cpp_s2_contains_matrix_brute_force`, geog1, geog2, s2options)
146+
}
147+
148+
cpp_s2_within_matrix_brute_force <- function(geog1, geog2, s2options) {
149+
.Call(`_s2_cpp_s2_within_matrix_brute_force`, geog1, geog2, s2options)
150+
}
151+
152+
cpp_s2_intersects_matrix_brute_force <- function(geog1, geog2, s2options) {
153+
.Call(`_s2_cpp_s2_intersects_matrix_brute_force`, geog1, geog2, s2options)
154+
}
155+
156+
cpp_s2_disjoint_matrix_brute_force <- function(geog1, geog2, s2options) {
157+
.Call(`_s2_cpp_s2_disjoint_matrix_brute_force`, geog1, geog2, s2options)
158+
}
159+
160+
cpp_s2_equals_matrix_brute_force <- function(geog1, geog2, s2options) {
161+
.Call(`_s2_cpp_s2_equals_matrix_brute_force`, geog1, geog2, s2options)
162+
}
163+
136164
s2_point_from_numeric <- function(x, y, z) {
137165
.Call(`_s2_s2_point_from_numeric`, x, y, z)
138166
}
@@ -157,6 +185,10 @@ cpp_s2_contains <- function(geog1, geog2, s2options) {
157185
.Call(`_s2_cpp_s2_contains`, geog1, geog2, s2options)
158186
}
159187

188+
cpp_s2_touches <- function(geog1, geog2, s2options) {
189+
.Call(`_s2_cpp_s2_touches`, geog1, geog2, s2options)
190+
}
191+
160192
cpp_s2_dwithin <- function(geog1, geog2, distance) {
161193
.Call(`_s2_cpp_s2_dwithin`, geog1, geog2, distance)
162194
}

R/s2-accessors.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ s2_num_points <- function(x) {
8585
#' @rdname s2_is_collection
8686
#' @export
8787
s2_is_empty <- function(x) {
88-
s2_num_points(x) == 0
88+
cpp_s2_is_empty(as_s2_geography(x))
8989
}
9090

9191
#' @rdname s2_is_collection

R/s2-matrix.R

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111
#' @inheritParams s2_contains
1212
#' @param x,y Geography vectors, coerced using [as_s2_geography()].
1313
#' `x` is considered the source, where as `y` is considered the target.
14+
#' @param max_edges_per_cell For [s2_may_intersect_matrix()],
15+
#' this values controls the nature of the index on `y`, with higher values
16+
#' leading to coarser index. Values should be between 10 and 50; the default
17+
#' of 50 is adequate for most use cases, but for specialized operations users
18+
#' may wish to use a lower value to increase performance.
19+
#' @param max_feature_cells For [s2_may_intersect_matrix()], this value
20+
#' controls the approximation of `x` used to identify potential intersections
21+
#' on `y`. The default value of 4 gives the best performance for most operations,
22+
#' but for specialized operations users may wish to use a higher value to increase
23+
#' performance.
1424
#'
1525
#' @return A vector of length `x`.
1626
#' @export
@@ -19,7 +29,7 @@
1929
#' See pairwise predicate functions (e.g., [s2_intersects()]).
2030
#'
2131
#' @examples
22-
#' city_names <- c("Vatican City", "San Marino", "Luxembourg", "Palikir")
32+
#' city_names <- c("Vatican City", "San Marino", "Luxembourg")
2333
#' cities <- s2_data_cities(city_names)
2434
#' country_names <- s2_data_tbl_countries$name
2535
#' countries <- s2_data_countries()
@@ -32,6 +42,9 @@
3242
#' # for each feature in x
3343
#' country_names[s2_farthest_feature(cities, countries)]
3444
#'
45+
#' # predicate matrices
46+
#' country_names[s2_intersects_matrix(cities, countries)[[1]]]
47+
#'
3548
#' # distance matrices
3649
#' s2_distance_matrix(cities, cities)
3750
#' s2_max_distance_matrix(cities, countries[1:4])
@@ -60,13 +73,13 @@ s2_max_distance_matrix <- function(x, y, radius = s2_earth_radius_meters()) {
6073

6174
#' @rdname s2_closest_feature
6275
#' @export
63-
s2_contains_matrix <- function(x, y, options = s2_options()) {
76+
s2_contains_matrix <- function(x, y, options = s2_options(model = 0)) {
6477
cpp_s2_contains_matrix(as_s2_geography(x), as_s2_geography(y), options)
6578
}
6679

6780
#' @rdname s2_closest_feature
6881
#' @export
69-
s2_within_matrix <- function(x, y, options = s2_options()) {
82+
s2_within_matrix <- function(x, y, options = s2_options(model = 0)) {
7083
cpp_s2_within_matrix(as_s2_geography(x), as_s2_geography(y), options)
7184
}
7285

@@ -91,7 +104,11 @@ s2_intersects_matrix <- function(x, y, options = s2_options()) {
91104
#' @rdname s2_closest_feature
92105
#' @export
93106
s2_disjoint_matrix <- function(x, y, options = s2_options()) {
94-
cpp_s2_disjoint_matrix(as_s2_geography(x), as_s2_geography(y), options)
107+
# disjoint is the odd one out, in that it requires a negation of intersects
108+
# this is inconvenient to do on the C++ level, and is easier to maintain
109+
# with setdiff() here (unless somebody complains that this is slow)
110+
intersection <- cpp_s2_intersects_matrix(as_s2_geography(x), as_s2_geography(y), options)
111+
Map(setdiff, list(seq_along(y)), intersection)
95112
}
96113

97114
#' @rdname s2_closest_feature
@@ -103,24 +120,51 @@ s2_equals_matrix <- function(x, y, options = s2_options()) {
103120
#' @rdname s2_closest_feature
104121
#' @export
105122
s2_touches_matrix <- function(x, y, options = s2_options()) {
106-
x <- as_s2_geography(x)
107-
y <- as_s2_geography(y)
108-
109-
options_closed <- options
110-
options_closed$polygon_model <- 2
111-
options_closed$polyline_model <- 2
112-
113-
options_open <- options
114-
options_open$polygon_model <- 0
115-
options_open$polyline_model <- 0
116-
117-
intersects_closed <- cpp_s2_intersects_matrix(x, y, options_closed)
118-
intersects_open <- cpp_s2_intersects_matrix(x, y, options_open)
119-
Map(setdiff, intersects_closed, intersects_open)
123+
cpp_s2_touches_matrix(as_s2_geography(x), as_s2_geography(y), options)
120124
}
121125

122126
#' @rdname s2_closest_feature
123127
#' @export
124128
s2_dwithin_matrix <- function(x, y, distance, radius = s2_earth_radius_meters()) {
125129
cpp_s2_dwithin_matrix(as_s2_geography(x), as_s2_geography(y), distance / radius)
126130
}
131+
132+
#' @rdname s2_closest_feature
133+
#' @export
134+
s2_may_intersect_matrix <- function(x, y, max_edges_per_cell = 50, max_feature_cells = 4) {
135+
cpp_s2_may_intersect_matrix(
136+
as_s2_geography(x), as_s2_geography(y),
137+
max_edges_per_cell, max_feature_cells,
138+
s2_options()
139+
)
140+
}
141+
142+
# ------- for testing, non-indexed versions of matrix operators -------
143+
144+
s2_contains_matrix_brute_force <- function(x, y, options = s2_options()) {
145+
cpp_s2_contains_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
146+
}
147+
148+
s2_within_matrix_brute_force <- function(x, y, options = s2_options()) {
149+
cpp_s2_within_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
150+
}
151+
152+
s2_covers_matrix_brute_force <- function(x, y, options = s2_options(model = 2)) {
153+
cpp_s2_contains_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
154+
}
155+
156+
s2_covered_by_matrix_brute_force <- function(x, y, options = s2_options(model = 2)) {
157+
cpp_s2_within_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
158+
}
159+
160+
s2_intersects_matrix_brute_force <- function(x, y, options = s2_options()) {
161+
cpp_s2_intersects_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
162+
}
163+
164+
s2_disjoint_matrix_brute_force <- function(x, y, options = s2_options()) {
165+
cpp_s2_disjoint_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
166+
}
167+
168+
s2_equals_matrix_brute_force <- function(x, y, options = s2_options()) {
169+
cpp_s2_equals_matrix_brute_force(as_s2_geography(x), as_s2_geography(y), options)
170+
}

R/s2-predicates.R

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,8 @@ s2_intersects_box <- function(x, lng1, lat1, lng2, lat2, detail = 1000, options
159159
#' @rdname s2_contains
160160
#' @export
161161
s2_touches <- function(x, y, options = s2_options()) {
162-
x <- as_s2_geography(x)
163-
y <- as_s2_geography(y)
164-
165-
options_closed <- options
166-
options_closed$polygon_model <- 2
167-
options_closed$polyline_model <- 2
168-
169-
options_open <- options
170-
options_open$polygon_model <- 0
171-
options_open$polyline_model <- 0
172-
173-
s2_intersects(x, y, options_closed) & !s2_intersects(x, y, options_open)
162+
recycled <- recycle_common(as_s2_geography(x), as_s2_geography(y))
163+
cpp_s2_touches(recycled[[1]], recycled[[2]], options)
174164
}
175165

176166
#' @rdname s2_contains

man/s2-package.Rd

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

man/s2_closest_feature.Rd

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

0 commit comments

Comments
 (0)