From c0d2117f1ceeb4cfe5e406831722523d696274f5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 29 Aug 2018 15:50:47 +0000 Subject: [PATCH] Add the geopoly_group_bbox() aggregate function to the Geopoly module. FossilOrigin-Name: 2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f --- ext/rtree/geopoly.c | 95 ++++++++++++++++++++++++++++++++++++++---- ext/rtree/visual01.txt | 22 ++++++++++ manifest | 14 +++---- manifest.uuid | 2 +- 4 files changed, 117 insertions(+), 16 deletions(-) diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c index 88cad4a172..70beffd7d1 100644 --- a/ext/rtree/geopoly.c +++ b/ext/rtree/geopoly.c @@ -477,9 +477,14 @@ static void geopolyAreaFunc( } /* -** Compute a bound-box on a polygon. Return a new GeoPoly object -** that describes the bounding box. Or, if aCoord is not a NULL pointer -** fill it in with the bounding box instead. +** If pPoly is a polygon, compute its bounding box. Then: +** +** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL +** (2) otherwise, compute a GeoPoly for the bounding box and return the +** new GeoPoly +** +** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from +** the bounding box in aCoord and return a pointer to that GeoPoly. */ static GeoPoly *geopolyBBox( sqlite3_context *context, /* For recording the error */ @@ -487,11 +492,21 @@ static GeoPoly *geopolyBBox( RtreeCoord *aCoord, /* Results here */ int *pRc /* Error code here */ ){ - GeoPoly *p = geopolyFuncParam(context, pPoly, pRc); GeoPoly *pOut = 0; + GeoPoly *p; + float mnX, mxX, mnY, mxY; + if( pPoly==0 && aCoord!=0 ){ + p = 0; + mnX = aCoord[0].f; + mxX = aCoord[1].f; + mnY = aCoord[2].f; + mxY = aCoord[3].f; + goto geopolyBboxFill; + }else{ + p = geopolyFuncParam(context, pPoly, pRc); + } if( p ){ int ii; - float mnX, mxX, mnY, mxY; mnX = mxX = p->a[0]; mnY = mxY = p->a[1]; for(ii=1; iinVertex; ii++){ @@ -504,6 +519,7 @@ static GeoPoly *geopolyBBox( } if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ + geopolyBboxFill: pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); if( pOut==0 ){ sqlite3_free(p); @@ -512,6 +528,8 @@ static GeoPoly *geopolyBBox( return 0; } pOut->nVertex = 4; + ii = 1; + pOut->hdr[0] = *(unsigned char*)ⅈ pOut->hdr[1] = 0; pOut->hdr[2] = 0; pOut->hdr[3] = 4; @@ -550,6 +568,58 @@ static void geopolyBBoxFunc( } } +/* +** State vector for the geopoly_group_bbox() aggregate function. +*/ +typedef struct GeoBBox GeoBBox; +struct GeoBBox { + int isInit; + RtreeCoord a[4]; +}; + + +/* +** Implementation of the geopoly_group_bbox(X) aggregate SQL function. +*/ +static void geopolyBBoxStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + RtreeCoord a[4]; + int rc = SQLITE_OK; + (void)geopolyBBox(context, argv[0], a, &rc); + if( rc==SQLITE_OK ){ + GeoBBox *pBBox; + pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); + if( pBBox==0 ) return; + if( pBBox->isInit==0 ){ + pBBox->isInit = 1; + memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); + }else{ + if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; + if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; + if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; + if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; + } + } +} +static void geopolyBBoxFinal( + sqlite3_context *context +){ + GeoPoly *p; + GeoBBox *pBBox; + pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); + if( pBBox==0 ) return; + p = geopolyBBox(context, 0, pBBox->a, 0); + if( p ){ + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + + /* ** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). ** Returns: @@ -1057,7 +1127,7 @@ static int geopolyInit( pRtree->nAux++; sqlite3_str_appendf(pSql, ",%s", argv[ii]); } - sqlite3_str_appendf(pSql, ",_bbox HIDDEN);"); + sqlite3_str_appendf(pSql, ");"); zSql = sqlite3_str_finish(pSql); if( !zSql ){ rc = SQLITE_NOMEM; @@ -1345,8 +1415,6 @@ static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ } } sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); - }else{ - /* Must be the _bbox column */ } return SQLITE_OK; } @@ -1559,12 +1627,23 @@ static int sqlite3_geopoly_init(sqlite3 *db){ { geopolyBBoxFunc, 1, "geopoly_bbox" }, { geopolyXformFunc, 7, "geopoly_xform" }, }; + static const struct { + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinal)(sqlite3_context*); + const char *zName; + } aAgg[] = { + { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" }, + }; int i; for(i=0; i' +.print '

Overlap Query And Result Bounding Box

' +.print '' +SELECT geopoly_svg(_shape, + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) + ) + FROM geo1, querypoly + WHERE geopoly_overlap(_shape, poly); +SELECT geopoly_svg(geopoly_bbox(poly), + 'style="fill:none;stroke:black;stroke-width:3"' + ) + FROM querypoly; +SELECT geopoly_svg(poly, + printf('style="fill:%s;fill-opacity:0.5;"',clr) + ) + FROM querypoly; +SELECT geopoly_svg(geopoly_group_bbox(_shape), + 'style="fill:none;stroke:red;stroke-width:3"' + ) + FROM geo1, querypoly + WHERE geopoly_overlap(_shape, poly); +.print '' + .print '

Bounding-Box Overlap Query

' .print '' SELECT geopoly_svg(_shape, diff --git a/manifest b/manifest index 87b80a42e6..c52c96c754 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\sserver1.test\sscript\son\sold\sPPC\sMacs\sdue\sto\sproblems\sin\sthe\npthreads\simplementation\son\sthose\sarchaic\smachines. -D 2018-08-28T21:12:02.935 +C Add\sthe\sgeopoly_group_bbox()\saggregate\sfunction\sto\sthe\sGeopoly\smodule. +D 2018-08-29T15:50:47.314 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 3b27e2e493d15697b39f5c2e722f86b5c2913fa662152e34614df9cf8bc2e112 +F ext/rtree/geopoly.c 0f1fda44b4515d2ab388f997593ac5030ff2023c6ae36fef3ca01b5bf7769e90 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 a3bc394ac37a031d8eda690fa35a6532717df2ae54cd066e1b8f45566b0a8650 +F ext/rtree/visual01.txt 6f2fdbde3a163034a47f007c43c7b5d52952a99d8258d6aafc3d87879e904e4a F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 @@ -1758,7 +1758,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 c0bf3ff3af4d34ef7801c16e39128e894b00699313f4915f57aa73b57642f7fd -R 95abfcfab7ce38adddfe464609758ff7 +P 43efdd8c7e468405c9d4956a8caa66548059499289cbcc091628de7b055268cd +R 67d74f447410c9c096d1d977e8daccbd U drh -Z c51195c228691c481dc919d190eb15c7 +Z b43229d61c5d2506dfee2bf7cbf08d25 diff --git a/manifest.uuid b/manifest.uuid index e7f7dc28b8..4cfef93773 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -43efdd8c7e468405c9d4956a8caa66548059499289cbcc091628de7b055268cd \ No newline at end of file +2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f \ No newline at end of file