]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Replace the new geopoly_reverse() function with geopoly_ccw(). The
authordrh <drh@noemail.net>
Mon, 8 Oct 2018 18:55:56 +0000 (18:55 +0000)
committerdrh <drh@noemail.net>
Mon, 8 Oct 2018 18:55:56 +0000 (18:55 +0000)
geopoly_ccw() function only reverses the vertex order if doing so is necessary
to get the correct right-hand winding rule on the polygon.

FossilOrigin-Name: 075066944b13b18d339ccf87ae16f0b91bf00f40bd70f71c6beba6aa6c43f0b6

ext/rtree/geopoly.c
manifest
manifest.uuid

index c3f3478b5ca0a6171075c753f8218f1400aaa676..be582a3e1b85e2178357a5986c6a58c585269a1b 100644 (file)
@@ -464,6 +464,27 @@ static void geopolyXformFunc(
   }
 }
 
+/*
+** Compute the area enclosed by the polygon.
+**
+** This routine can also be used to detect polygons that rotate in
+** the wrong direction.  Polygons are suppose to be counter-clockwise (CCW).
+** This routine returns a negative value for clockwise (CW) polygons.
+*/
+static double geopolyArea(GeoPoly *p){
+  double rArea = 0.0;
+  int ii;
+  for(ii=0; ii<p->nVertex-1; ii++){
+    rArea += (p->a[ii*2] - p->a[ii*2+2])           /* (x0 - x1) */
+              * (p->a[ii*2+1] + p->a[ii*2+3])      /* (y0 + y1) */
+              * 0.5;
+  }
+  rArea += (p->a[ii*2] - p->a[0])                  /* (xN - x0) */
+           * (p->a[ii*2+1] + p->a[1])              /* (yN + y0) */
+           * 0.5;
+  return rArea;
+}
+
 /*
 ** Implementation of the geopoly_area(X) function.
 **
@@ -479,44 +500,41 @@ static void geopolyAreaFunc(
 ){
   GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
   if( p ){
-    double rArea = 0.0;
-    int ii;
-    for(ii=0; ii<p->nVertex-1; ii++){
-      rArea += (p->a[ii*2] - p->a[ii*2+2])           /* (x0 - x1) */
-                * (p->a[ii*2+1] + p->a[ii*2+3])      /* (y0 + y1) */
-                * 0.5;
-    }
-    rArea += (p->a[ii*2] - p->a[0])                  /* (xN - x0) */
-             * (p->a[ii*2+1] + p->a[1])              /* (yN + y0) */
-             * 0.5;
-    sqlite3_result_double(context, rArea);
+    sqlite3_result_double(context, geopolyArea(p));
     sqlite3_free(p);
   }            
 }
 
 /*
-** Implementation of the geopoly_reverse(X) function.
+** Implementation of the geopoly_ccw(X) function.
+**
+** If the rotation of polygon X is clockwise (incorrect) instead of
+** counter-clockwise (the correct winding order according to RFC7946)
+** then reverse the order of the vertexes in polygon X.  
 **
-** Reverse the order of the vertexes in polygon X.  This can be used
-** to convert an historical polygon that uses a clockwise rotation into
-** a well-formed GeoJSON polygon that uses counter-clockwise rotation.
+** In other words, this routine returns a CCW polygon regardless of the
+** winding order of its input.
+**
+** Use this routine to sanitize historical inputs that that sometimes
+** contain polygons that wind in the wrong direction.
 */
-static void geopolyReverseFunc(
+static void geopolyCcwFunc(
   sqlite3_context *context,
   int argc,
   sqlite3_value **argv
 ){
   GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
   if( p ){
-    int ii, jj;
-    for(ii=2, jj=p->nVertex*2 - 4; ii<jj; ii+=2, jj-=2){
-      GeoCoord t = p->a[ii];
-      p->a[ii] = p->a[jj];
-      p->a[jj] = t;
-      t = p->a[ii+1];
-      p->a[ii+1] = p->a[jj+1];
-      p->a[jj+1] = t;
-
+    if( geopolyArea(p)<0.0 ){
+      int ii, jj;
+      for(ii=2, jj=p->nVertex*2 - 4; ii<jj; ii+=2, jj-=2){
+        GeoCoord t = p->a[ii];
+        p->a[ii] = p->a[jj];
+        p->a[jj] = t;
+        t = p->a[ii+1];
+        p->a[ii+1] = p->a[jj+1];
+        p->a[jj+1] = t;
+      }
     }
     sqlite3_result_blob(context, p->hdr, 
        4+8*p->nVertex, SQLITE_TRANSIENT);
@@ -1751,7 +1769,7 @@ static int sqlite3_geopoly_init(sqlite3 *db){
      { geopolyBBoxFunc,          1, 1,    "geopoly_bbox"             },
      { geopolyXformFunc,         7, 1,    "geopoly_xform"            },
      { geopolyRegularFunc,       4, 1,    "geopoly_regular"          },
-     { geopolyReverseFunc,       1, 1,    "geopoly_reverse"          },
+     { geopolyCcwFunc,           1, 1,    "geopoly_ccw"              },
   };
   static const struct {
     void (*xStep)(sqlite3_context*,int,sqlite3_value**);
index 7a838f249e7096985638fc01eaa94371ab85201b..bc450e6e5ff93e07bae39774af0f5980e20b69d7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\sgeopoly_reverse()\sfunction\sto\sthe\sGeoPoly\sextension.
-D 2018-10-08T12:58:59.969
+C Replace\sthe\snew\sgeopoly_reverse()\sfunction\swith\sgeopoly_ccw().\s\sThe\ngeopoly_ccw()\sfunction\sonly\sreverses\sthe\svertex\sorder\sif\sdoing\sso\sis\snecessary\nto\sget\sthe\scorrect\sright-hand\swinding\srule\son\sthe\spolygon.
+D 2018-10-08T18:55:56.767
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
@@ -361,7 +361,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 9d8411b2bcaab719f65acc8a84d16200d5139ac634787df546c31bf9972b34e6
+F ext/rtree/geopoly.c 2464b3325fcc2878ed08458efeb995f830f4eef28bbf3da9757c4bd95e6f9549
 F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20
 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
@@ -1771,7 +1771,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 aac8f1dff0728c629b5cbf30369ee91c5862a707ede694dc2628d1d4f5a6c202
-R 6c483dda78db6c9ea6a6a082c4feae71
+P 690dd18a5768c5a8cdfa92d5b01901c1a7b1fb6ebb90399f56a3112e41609f92
+R 35a6105ea46a39f4869622077b954203
 U drh
-Z f525bca01c12c5943b4f7c604400e173
+Z 59baf7542a91be0562e1f0570ed59fd4
index b8eda6748ba2db6735bd6828c7170ac17eb42aa1..b661feba37ed2781f3f63c3060e04d2cbaa1b1db 100644 (file)
@@ -1 +1 @@
-690dd18a5768c5a8cdfa92d5b01901c1a7b1fb6ebb90399f56a3112e41609f92
\ No newline at end of file
+075066944b13b18d339ccf87ae16f0b91bf00f40bd70f71c6beba6aa6c43f0b6
\ No newline at end of file