From: drh Date: Mon, 27 Aug 2018 15:55:37 +0000 (+0000) Subject: Split the three-argument version of geopoly_within() off into a separate X-Git-Tag: version-3.25.0~60^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2a18c95f0f1ed2805c7b17b0055db33a138df7a;p=thirdparty%2Fsqlite.git Split the three-argument version of geopoly_within() off into a separate function named geopoly_contains_point(). FossilOrigin-Name: 5a0e1541037b5bbc1b4bf26a7da304c9b32ea72960aca8b9309cf2180757c8a4 --- diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 8b4246858e..3af3d32612 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -579,17 +579,50 @@ static int pointBeneathLine( return 0; } -/* Forward declaration */ -static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); - /* -** SQL function: geopoly_within(P,X,Y) -- 3-argument form +** SQL function: geopoly_contains_point(P,X,Y) ** ** Return +2 if point X,Y is within polygon P. ** Return +1 if point X,Y is on the polygon boundary. ** Return 0 if point X,Y is outside the polygon -** -** SQL function: geopoly_within(P1,P2) -- 2-argument form +*/ +static void geopolyContainsPointFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); + double x0 = sqlite3_value_double(argv[1]); + double y0 = sqlite3_value_double(argv[2]); + int v = 0; + int cnt = 0; + int ii; + if( p1==0 ) return; + for(ii=0; iinVertex-1; ii++){ + v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], + p1->a[ii*2+2],p1->a[ii*2+3]); + if( v==2 ) break; + cnt += v; + } + if( v!=2 ){ + v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], + p1->a[0],p1->a[1]); + } + if( v==2 ){ + sqlite3_result_int(context, 1); + }else if( ((v+cnt)&1)==0 ){ + sqlite3_result_int(context, 0); + }else{ + sqlite3_result_int(context, 2); + } + sqlite3_free(p1); +} + +/* Forward declaration */ +static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); + +/* +** SQL function: geopoly_within(P1,P2) ** ** Return +2 if P1 and P2 are the same polygon ** Return +1 if P2 is contained within P1 @@ -602,44 +635,17 @@ static void geopolyWithinFunc( sqlite3_value **argv ){ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); - if( p1==0 ) return; - if( argc==3 ){ - double x0 = sqlite3_value_double(argv[1]); - double y0 = sqlite3_value_double(argv[2]); - int v = 0; - int cnt = 0; - int ii; - for(ii=0; iinVertex-1; ii++){ - v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], - p1->a[ii*2+2],p1->a[ii*2+3]); - if( v==2 ) break; - cnt += v; - } - if( v!=2 ){ - v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], - p1->a[0],p1->a[1]); - } - if( v==2 ){ - sqlite3_result_int(context, 1); - }else if( ((v+cnt)&1)==0 ){ - sqlite3_result_int(context, 0); + GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); + if( p1 && p2 ){ + int x = geopolyOverlap(p1, p2); + if( x<0 ){ + sqlite3_result_error_nomem(context); }else{ - sqlite3_result_int(context, 2); - } - }else{ - assert( argc==2 ); - GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); - if( p2 ){ - int x = geopolyOverlap(p1, p2); - if( x<0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); - } - sqlite3_free(p2); + sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); } } sqlite3_free(p1); + sqlite3_free(p2); } /* Objects used by the overlap algorihm. */ @@ -1486,7 +1492,7 @@ static int geopolyFindFunction( *ppArg = 0; return SQLITE_INDEX_CONSTRAINT_FUNCTION; } - if( nArg==2 && sqlite3_stricmp(zName, "geopoly_within")==0 ){ + if( sqlite3_stricmp(zName, "geopoly_within")==0 ){ *pxFunc = geopolyWithinFunc; *ppArg = 0; return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; @@ -1528,16 +1534,16 @@ static int sqlite3_geopoly_init(sqlite3 *db){ int nArg; const char *zName; } aFunc[] = { - { geopolyAreaFunc, 1, "geopoly_area" }, - { geopolyBlobFunc, 1, "geopoly_blob" }, - { geopolyJsonFunc, 1, "geopoly_json" }, - { geopolySvgFunc, -1, "geopoly_svg" }, - { geopolyWithinFunc, 2, "geopoly_within" }, - { geopolyWithinFunc, 3, "geopoly_within" }, - { geopolyOverlapFunc, 2, "geopoly_overlap" }, - { geopolyDebugFunc, 1, "geopoly_debug" }, - { geopolyBBoxFunc, 1, "geopoly_bbox" }, - { geopolyXformFunc, 7, "geopoly_xform" }, + { geopolyAreaFunc, 1, "geopoly_area" }, + { geopolyBlobFunc, 1, "geopoly_blob" }, + { geopolyJsonFunc, 1, "geopoly_json" }, + { geopolySvgFunc, -1, "geopoly_svg" }, + { geopolyWithinFunc, 2, "geopoly_within" }, + { geopolyContainsPointFunc, 3, "geopoly_contains_point" }, + { geopolyOverlapFunc, 2, "geopoly_overlap" }, + { geopolyDebugFunc, 1, "geopoly_debug" }, + { geopolyBBoxFunc, 1, "geopoly_bbox" }, + { geopolyXformFunc, 7, "geopoly_xform" }, }; int i; for(i=0; i