1414#include " wkb.h"
1515
1616typedef char (* log_fn)(GEOSContextHandle_t, const GEOSGeometry *, const GEOSGeometry *);
17- typedef char (* log_prfn)(GEOSContextHandle_t, const GEOSPreparedGeometry *, const GEOSGeometry *);
17+ typedef char (* log_prfn)(GEOSContextHandle_t, const GEOSPreparedGeometry *,
18+ const GEOSGeometry *);
1819typedef GEOSGeom (* geom_fn)(GEOSContextHandle_t, const GEOSGeom, const GEOSGeom);
1920
21+ void cb (void *item, void *userdata) { // callback function for tree selection
22+ std::vector<size_t > *ret = (std::vector<size_t > *) userdata;
23+ ret->push_back (*((size_t *) item));
24+ }
25+
2026static void __errorHandler (const char *fmt, ...) { // #nocov start
2127
2228 char buf[BUFSIZ], *p;
@@ -193,9 +199,16 @@ Rcpp::List CPL_geos_binop(Rcpp::List sfc0, Rcpp::List sfc1, std::string op, doub
193199
194200 std::vector<GEOSGeom> gmv0 = geometries_from_sfc (hGEOSCtxt, sfc0, NULL );
195201 std::vector<GEOSGeom> gmv1 = geometries_from_sfc (hGEOSCtxt, sfc1, NULL );
202+ std::vector<size_t > items (gmv1.size ());
196203
197204 Rcpp::List ret_list;
198205
206+ GEOSSTRtree *tree1 = GEOSSTRtree_create_r (hGEOSCtxt, 10 );
207+ for (size_t i = 0 ; i < gmv1.size (); i++) {
208+ items[i] = i;
209+ GEOSSTRtree_insert_r (hGEOSCtxt, tree1, gmv1[i], &(items[i]));
210+ }
211+
199212 using namespace Rcpp ; // so that later on the (i,_) works
200213 if (op == " relate" ) { // character return matrix:
201214 Rcpp::CharacterVector out (sfc0.length () * sfc1.length ());
@@ -253,19 +266,39 @@ Rcpp::List CPL_geos_binop(Rcpp::List sfc0, Rcpp::List sfc1, std::string op, doub
253266 sparsemat[i] = get_which (rowi);
254267 R_CheckUserInterrupt ();
255268 }
269+ } else if (op == " disjoint" ) {
270+ for (int i = 0 ; i < sfc0.length (); i++) { // row
271+ Rcpp::LogicalVector rowi (sfc1.length ());
272+ for (int j = 0 ; j < sfc1.length (); j++)
273+ rowi (j) = chk_ (GEOSDisjoint_r (hGEOSCtxt, gmv0[i], gmv1[j]));
274+ if (! sparse)
275+ densemat (i,_) = rowi; // #nocov
276+ else
277+ sparsemat[i] = get_which (rowi);
278+ R_CheckUserInterrupt ();
279+ }
256280 } else {
257281 if (prepared) {
258282 log_prfn logical_fn = which_prep_geom_fn (op);
259283 for (int i = 0 ; i < sfc0.length (); i++) { // row
260- Rcpp::LogicalVector rowi (sfc1.length ());
261284 const GEOSPreparedGeometry *pr = GEOSPrepare_r (hGEOSCtxt, gmv0[i]);
262- for (int j = 0 ; j < sfc1.length (); j++)
263- rowi (j) = chk_ (logical_fn (hGEOSCtxt, pr, gmv1[j]));
264- GEOSPreparedGeom_destroy_r (hGEOSCtxt, pr);
265- if (! sparse)
285+ if (sparse) {
286+ // pre-select sfc1's using tree:
287+ std::vector<size_t > tree_sel, sel;
288+ GEOSSTRtree_query_r (hGEOSCtxt, tree1, gmv0[i], cb, &tree_sel);
289+ for (int j = 0 ; j < tree_sel.size (); j++)
290+ if (chk_ (logical_fn (hGEOSCtxt, pr, gmv1[tree_sel[j]])))
291+ sel.push_back (tree_sel[j] + 1 ); // 1-based
292+ std::sort (sel.begin (), sel.end ());
293+ sparsemat[i] = Rcpp::IntegerVector (sel.begin (), sel.end ());
294+ } else {
295+ Rcpp::LogicalVector rowi (sfc1.length ());
296+ for (int j = 0 ; j < sfc1.length (); j++)
297+ rowi (j) = chk_ (logical_fn (hGEOSCtxt, pr, gmv1[j]));
298+ GEOSPreparedGeom_destroy_r (hGEOSCtxt, pr);
266299 densemat (i,_) = rowi;
267- else
268- sparsemat[i] = get_which (rowi);
300+ }
301+
269302 R_CheckUserInterrupt ();
270303 }
271304 } else {
@@ -500,6 +533,7 @@ Rcpp::List CPL_geos_op2(std::string op, Rcpp::List sfcx, Rcpp::List sfcy) {
500533 std::vector<GEOSGeom> y = geometries_from_sfc (hGEOSCtxt, sfcy, &dim);
501534 std::vector<GEOSGeom> out;
502535 std::vector<double > index_x, index_y;
536+ std::vector<size_t > items (x.size ());
503537
504538 geom_fn geom_function;
505539
@@ -514,8 +548,20 @@ Rcpp::List CPL_geos_op2(std::string op, Rcpp::List sfcx, Rcpp::List sfcy) {
514548 else
515549 throw std::invalid_argument (" invalid operation" ); // #nocov
516550
551+ GEOSSTRtree *tree = GEOSSTRtree_create_r (hGEOSCtxt, 10 );
552+ for (size_t i = 0 ; i < x.size (); i++) {
553+ items[i] = i;
554+ GEOSSTRtree_insert_r (hGEOSCtxt, tree, x[i], &(items[i]));
555+ }
556+
517557 for (size_t i = 0 ; i < y.size (); i++) {
518- for (size_t j = 0 ; j < x.size (); j++) {
558+ // select x's using tree:
559+ std::vector<size_t > sel;
560+ sel.reserve (x.size ());
561+ GEOSSTRtree_query_r (hGEOSCtxt, tree, y[i], cb, &sel);
562+ std::sort (sel.begin (), sel.end ());
563+ for (size_t item = 0 ; item < sel.size (); item++) {
564+ size_t j = sel[item];
519565 GEOSGeom geom = geom_function (hGEOSCtxt, x[j], y[i]);
520566 if (geom == NULL )
521567 throw std::range_error (" GEOS exception" ); // #nocov
@@ -528,6 +574,7 @@ Rcpp::List CPL_geos_op2(std::string op, Rcpp::List sfcx, Rcpp::List sfcy) {
528574 }
529575 R_CheckUserInterrupt ();
530576 }
577+ GEOSSTRtree_destroy_r (hGEOSCtxt, tree);
531578
532579 // clean up x and y:
533580 for (size_t i = 0 ; i < x.size (); i++)
0 commit comments