Provide the two-argument geopoly_within(P1,P2) routine that determines if
polygon P2 is contained within polygon P1. Make this function available to the query planner for optimized rtree lookups. Update the visual01.txt script to verify that the new functionality actually works. FossilOrigin-Name: 6eb5d09b7f9d9bf8edbf993dccc2e2f702b95ba96cf68445609feb0ccc3ac0f7
This commit is contained in:
parent
95327f539b
commit
27d62540e5
@ -579,34 +579,45 @@ static int pointBeneathLine(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2);
|
||||
|
||||
/*
|
||||
** SQL function: geopoly_within(P,X,Y)
|
||||
** SQL function: geopoly_within(P,X,Y) -- 3-argument form
|
||||
**
|
||||
** 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
|
||||
**
|
||||
** Return +2 if P1 and P2 are the same polygon
|
||||
** Return +1 if P2 is contained within P1
|
||||
** Return 0 if any part of P2 is on the outside of P1
|
||||
**
|
||||
*/
|
||||
static void geopolyWithinFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
|
||||
double x0 = sqlite3_value_double(argv[1]);
|
||||
double y0 = sqlite3_value_double(argv[2]);
|
||||
if( p ){
|
||||
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; ii<p->nVertex-1; ii++){
|
||||
v = pointBeneathLine(x0,y0,p->a[ii*2],p->a[ii*2+1],
|
||||
p->a[ii*2+2],p->a[ii*2+3]);
|
||||
for(ii=0; ii<p1->nVertex-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,p->a[ii*2],p->a[ii*2+1],
|
||||
p->a[0],p->a[1]);
|
||||
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);
|
||||
@ -615,8 +626,20 @@ static void geopolyWithinFunc(
|
||||
}else{
|
||||
sqlite3_result_int(context, 2);
|
||||
}
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}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_free(p1);
|
||||
}
|
||||
|
||||
/* Objects used by the overlap algorihm. */
|
||||
@ -1219,6 +1242,7 @@ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
|
||||
if( iRowidTerm>=0 ){
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->idxStr = "rowid";
|
||||
pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
|
||||
pIdxInfo->estimatedCost = 30.0;
|
||||
@ -1228,6 +1252,7 @@ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
}
|
||||
if( iFuncTerm>=0 ){
|
||||
pIdxInfo->idxNum = 2;
|
||||
pIdxInfo->idxStr = "rtree";
|
||||
pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0;
|
||||
pIdxInfo->estimatedCost = 300.0;
|
||||
@ -1235,6 +1260,7 @@ static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pIdxInfo->idxNum = 3;
|
||||
pIdxInfo->idxStr = "fullscan";
|
||||
pIdxInfo->estimatedCost = 3000000.0;
|
||||
pIdxInfo->estimatedRows = 100000;
|
||||
return SQLITE_OK;
|
||||
@ -1432,6 +1458,11 @@ static int geopolyFindFunction(
|
||||
*ppArg = 0;
|
||||
return SQLITE_INDEX_CONSTRAINT_FUNCTION;
|
||||
}
|
||||
if( nArg==2 && sqlite3_stricmp(zName, "geopoly_within")==0 ){
|
||||
*pxFunc = geopolyWithinFunc;
|
||||
*ppArg = 0;
|
||||
return SQLITE_INDEX_CONSTRAINT_FUNCTION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1473,6 +1504,7 @@ static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
{ 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" },
|
||||
|
@ -374,7 +374,16 @@ SELECT geopoly_svg(poly,
|
||||
)
|
||||
FROM querypoly;
|
||||
.print '</svg>'
|
||||
.print '<h1>Query</h1>'
|
||||
|
||||
.print '<h1>Overlap Query</h1>'
|
||||
.print '<pre>'
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE geopoly_overlap(_shape, poly);
|
||||
.print '</pre>'
|
||||
.print '<svg width="1000" height="800" style="border:1px solid black">'
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
@ -386,4 +395,67 @@ SELECT geopoly_svg(poly,
|
||||
)
|
||||
FROM querypoly;
|
||||
.print '</svg>'
|
||||
|
||||
.print '<h1>Within Query</h1>'
|
||||
.print '<pre>'
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE geopoly_within(_shape, poly);
|
||||
.print '</pre>'
|
||||
.print '<svg width="1000" height="800" style="border:1px solid black">'
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE geopoly_within(_shape, poly);
|
||||
SELECT geopoly_svg(poly,
|
||||
printf('style="fill:%s;fill-opacity:0.5;"',clr)
|
||||
)
|
||||
FROM querypoly;
|
||||
.print '</svg>'
|
||||
|
||||
.print '<h1>Not Overlap Query</h1>'
|
||||
.print '<pre>'
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE NOT geopoly_overlap(_shape, poly);
|
||||
.print '</pre>'
|
||||
.print '<svg width="1000" height="800" style="border:1px solid black">'
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE NOT geopoly_overlap(_shape, poly);
|
||||
SELECT geopoly_svg(poly,
|
||||
printf('style="fill:%s;fill-opacity:0.5;"',clr)
|
||||
)
|
||||
FROM querypoly;
|
||||
.print '</svg>'
|
||||
|
||||
.print '<h1>Not Within Query</h1>'
|
||||
.print '<pre>'
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE NOT geopoly_within(_shape, poly);
|
||||
.print '</pre>'
|
||||
.print '<svg width="1000" height="800" style="border:1px solid black">'
|
||||
SELECT geopoly_svg(_shape,
|
||||
printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
|
||||
)
|
||||
FROM geo1, querypoly
|
||||
WHERE NOT geopoly_within(_shape, poly);
|
||||
SELECT geopoly_svg(poly,
|
||||
printf('style="fill:%s;fill-opacity:0.5;"',clr)
|
||||
)
|
||||
FROM querypoly;
|
||||
.print '</svg>'
|
||||
.print '</html>'
|
||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\sharmless\scompiler\swarning.
|
||||
D 2018-08-25T18:57:12.922
|
||||
C Provide\sthe\stwo-argument\sgeopoly_within(P1,P2)\sroutine\sthat\sdetermines\sif\npolygon\sP2\sis\scontained\swithin\spolygon\sP1.\s\sMake\sthis\sfunction\savailable\sto\nthe\squery\splanner\sfor\soptimized\srtree\slookups.\s\sUpdate\sthe\svisual01.txt\nscript\sto\sverify\sthat\sthe\snew\sfunctionality\sactually\sworks.
|
||||
D 2018-08-25T19:51:49.457
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in d06f463c5b623a61ac27f5cb8214fca9e53a6704d34d6b8f2124e2b1b293c88f
|
||||
@ -359,7 +359,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
|
||||
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c 9d4f90cdb08bc46de463c5ee1ab7cf114f33f7d512165a9b60eb710a5801777a
|
||||
F ext/rtree/geopoly.c b495718226257fe7a69df3367ae9a440a81f99e63013177cb327fbc8a12a1d92
|
||||
F ext/rtree/rtree.c f3c2f1b5eea75b98d4d3dcdec2ebf2a69c036b53f2f3d196e61bf5016298255f
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
|
||||
@ -386,7 +386,7 @@ F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae926833
|
||||
F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F ext/rtree/visual01.txt ce5473774986a7fde188de9cbfc554f9c0f07109c61a5169019bd0c514776c11
|
||||
F ext/rtree/visual01.txt c5cceddea30ab74099365a54ee8850f085d01503050353240eda48b6062ad3f4
|
||||
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
|
||||
F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc
|
||||
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
|
||||
@ -1757,7 +1757,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P c446c8841192054c97ba5003fb6185b135a687b36c10fe0986e627282955520a
|
||||
R a41568f93760504ebb09f57d0f907e04
|
||||
P d49be9838d237b57ba1f12ed00e2d3411314ee1b9c30ef7bbaf65aca20d0870e
|
||||
R d6a6a8b236c31c3e94eaf646cbba5241
|
||||
U drh
|
||||
Z e5256e66a995508165b2fa785b46beee
|
||||
Z 150d6fa9f487a014f94bf1a66214204f
|
||||
|
@ -1 +1 @@
|
||||
d49be9838d237b57ba1f12ed00e2d3411314ee1b9c30ef7bbaf65aca20d0870e
|
||||
6eb5d09b7f9d9bf8edbf993dccc2e2f702b95ba96cf68445609feb0ccc3ac0f7
|
Loading…
x
Reference in New Issue
Block a user