]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the geopoly_group_bbox() aggregate function to the Geopoly module.
authordrh <drh@noemail.net>
Wed, 29 Aug 2018 15:50:47 +0000 (15:50 +0000)
committerdrh <drh@noemail.net>
Wed, 29 Aug 2018 15:50:47 +0000 (15:50 +0000)
FossilOrigin-Name: 2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f

ext/rtree/geopoly.c
ext/rtree/visual01.txt
manifest
manifest.uuid

index 88cad4a1720951159199368aa47dc0c15eed5809..70beffd7d18a38beb452aa606d1ca8fddba7861e 100644 (file)
@@ -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; ii<p->nVertex; 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*)&ii;
       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<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
     rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
                                  SQLITE_UTF8, 0,
                                  aFunc[i].xFunc, 0, 0);
   }
+  for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
+    rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0,
+                                 0, aAgg[i].xStep, aAgg[i].xFinal);
+  }
   if( rc==SQLITE_OK ){
     rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0);
   }
index b248b76bc8d283ff67c2745eeb3924dbd669c978..fc1b26a749a00f2f269d99ec6a000a55b0065a07 100644 (file)
@@ -400,6 +400,28 @@ SELECT geopoly_svg(poly,
   FROM querypoly;
 .print '</svg>'
 
+.print '<h1>Overlap Query And Result Bounding Box</h1>'
+.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_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 '</svg>'
+
 .print '<h1>Bounding-Box Overlap Query</h1>'
 .print '<svg width="1000" height="800" style="border:1px solid black">'
 SELECT geopoly_svg(_shape,
index 87b80a42e69a0fdf6a8a84845ec4b63b746e3bda..c52c96c754f641cc9fe974db52e6887cf1a3378c 100644 (file)
--- 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
index e7f7dc28b8c75f6f4ac18b82bb2121678d4da1bc..4cfef93773f41c7e4c5758290a4e7280caeab135 100644 (file)
@@ -1 +1 @@
-43efdd8c7e468405c9d4956a8caa66548059499289cbcc091628de7b055268cd
\ No newline at end of file
+2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f
\ No newline at end of file