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);
}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. */
if( iRowidTerm>=0 ){
pIdxInfo->idxNum = 1;
+ pIdxInfo->idxStr = "rowid";
pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
pIdxInfo->estimatedCost = 30.0;
}
if( iFuncTerm>=0 ){
pIdxInfo->idxNum = 2;
+ pIdxInfo->idxStr = "rtree";
pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1;
pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0;
pIdxInfo->estimatedCost = 300.0;
return SQLITE_OK;
}
pIdxInfo->idxNum = 3;
+ pIdxInfo->idxStr = "fullscan";
pIdxInfo->estimatedCost = 3000000.0;
pIdxInfo->estimatedRows = 100000;
return SQLITE_OK;
*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;
}
{ 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" },
)
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)
)
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>'
-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
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
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
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
-d49be9838d237b57ba1f12ed00e2d3411314ee1b9c30ef7bbaf65aca20d0870e
\ No newline at end of file
+6eb5d09b7f9d9bf8edbf993dccc2e2f702b95ba96cf68445609feb0ccc3ac0f7
\ No newline at end of file