/ Check-in [77bb7b7d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Preliminary tests show geopoly_overlap() is working.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | geojson
Files: files | file ages | folders
SHA3-256: 77bb7b7d7278725e4e02935d485c3540bb41f4fc29ca8da679b2a380ebc38d7d
User & Date: drh 2018-05-12 20:28:51
Context
2018-05-12
21:09
Add the geopoly_svg() SQL function. check-in: 318ba5f0 user: drh tags: geojson
20:28
Preliminary tests show geopoly_overlap() is working. check-in: 77bb7b7d user: drh tags: geojson
16:05
An initial attempt at an overlap function in the geopoly extension. check-in: c857976e user: drh tags: geojson
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/geopoly.c.

    16     16   #include "sqlite3ext.h"
    17     17   SQLITE_EXTENSION_INIT1
    18     18   #include <assert.h>
    19     19   #include <string.h>
    20     20   #include <stdlib.h>
    21     21   #include <stdio.h>
    22     22   #define SQLITE_HAVE_GEOPLOY 1
           23  +
           24  +/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */
           25  +#ifdef GEOPOLY_ENABLE_DEBUG
           26  +  static int geo_debug = 0;
           27  +# define GEODEBUG(X) if(geo_debug)printf X
           28  +#else
           29  +# define GEODEBUG(X)
           30  +#endif
    23     31   
    24     32   #ifndef JSON_NULL   /* The following stuff repeats things found in json1 */
    25     33   /*
    26     34   ** Versions of isspace(), isalnum() and isdigit() to which it is safe
    27     35   ** to pass signed char values.
    28     36   */
    29     37   #ifdef sqlite3Isdigit
................................................................................
   635    643   static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
   636    644     int nVertex = p1->nVertex + p2->nVertex + 2;
   637    645     GeoOverlap *p;
   638    646     int nByte;
   639    647     GeoEvent *pThisEvent;
   640    648     double rX;
   641    649     int rc = 0;
          650  +  int needSort = 0;
   642    651     GeoSegment *pActive = 0;
   643    652     GeoSegment *pSeg;
   644    653     unsigned char aOverlap[4];
   645    654   
   646    655     nByte = sizeof(GeoEvent)*nVertex*2 
   647    656              + sizeof(GeoSegment)*nVertex 
   648    657              + sizeof(GeoOverlap);
................................................................................
   656    665     pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
   657    666     rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
   658    667     memset(aOverlap, 0, sizeof(aOverlap));
   659    668     while( pThisEvent ){
   660    669       if( pThisEvent->x!=rX ){
   661    670         GeoSegment *pPrev = 0;
   662    671         int iMask = 0;
   663         -      printf("Distinct X: %g\n", pThisEvent->x);
          672  +      GEODEBUG(("Distinct X: %g\n", pThisEvent->x));
   664    673         rX = pThisEvent->x;
   665         -      pActive = geopolySortSegmentsByYAndC(pActive);
          674  +      if( needSort ){
          675  +        pActive = geopolySortSegmentsByYAndC(pActive);
          676  +        needSort = 0;
          677  +      }
          678  +      for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
          679  +        if( pPrev ){
          680  +          if( pPrev->y!=pSeg->y ){
          681  +            GEODEBUG(("MASK: %d\n", iMask));
          682  +            aOverlap[iMask] = 1;
          683  +          }
          684  +        }
          685  +        iMask ^= pSeg->side;
          686  +        pPrev = pSeg;
          687  +      }
          688  +      pPrev = 0;
   666    689         for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
   667    690           double y = pSeg->C*rX + pSeg->B;
   668         -        printf("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y);
          691  +        GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y));
   669    692           pSeg->y = y;
   670    693           if( pPrev ){
   671    694             if( pPrev->y>pSeg->y ){
   672    695               rc = 1;
   673         -            printf("Crossing: %d.%d and %d.%d\n",
          696  +            GEODEBUG(("Crossing: %d.%d and %d.%d\n",
   674    697                       pPrev->side, pPrev->idx,
   675         -                    pSeg->side, pSeg->idx);
          698  +                    pSeg->side, pSeg->idx));
   676    699               goto geopolyOverlapDone;
   677    700             }else if( pPrev->y!=pSeg->y ){
   678         -            printf("MASK: %d\n", iMask);
          701  +            GEODEBUG(("MASK: %d\n", iMask));
   679    702               aOverlap[iMask] = 1;
   680    703             }
   681    704           }
   682    705           iMask ^= pSeg->side;
   683    706           pPrev = pSeg;
   684    707         }
   685    708       }
   686         -    printf("%s %d.%d C=%g B=%g\n",
          709  +    GEODEBUG(("%s %d.%d C=%g B=%g\n",
   687    710         pThisEvent->eType ? "RM " : "ADD",
   688    711         pThisEvent->pSeg->side, pThisEvent->pSeg->idx,
   689    712         pThisEvent->pSeg->C,
   690         -      pThisEvent->pSeg->B);
          713  +      pThisEvent->pSeg->B));
   691    714       if( pThisEvent->eType==0 ){
   692    715         /* Add a segment */
   693    716         pSeg = pThisEvent->pSeg;
   694    717         pSeg->y = pSeg->C*rX + pSeg->B;
   695    718         pSeg->pNext = pActive;
   696    719         pActive = pSeg;
          720  +      needSort = 1;
   697    721       }else{
   698    722         /* Remove a segment */
   699    723         if( pActive==pThisEvent->pSeg ){
   700    724           pActive = pActive->pNext;
   701    725         }else{
   702    726           for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
   703    727             if( pSeg->pNext==pThisEvent->pSeg ){
................................................................................
   753    777         sqlite3_result_int(context, x);
   754    778       }
   755    779     }
   756    780     sqlite3_free(p1);
   757    781     sqlite3_free(p2);
   758    782   }
   759    783   
          784  +/*
          785  +** Enable or disable debugging output
          786  +*/
          787  +static void geopolyDebugFunc(
          788  +  sqlite3_context *context,
          789  +  int argc,
          790  +  sqlite3_value **argv
          791  +){
          792  +#ifdef GEOPOLY_ENABLE_DEBUG
          793  +  geo_debug = sqlite3_value_int(argv[0]);
          794  +#endif
          795  +}
   760    796   
   761    797   #ifdef _WIN32
   762    798   __declspec(dllexport)
   763    799   #endif
   764    800   int sqlite3_geopoly_init(
   765    801     sqlite3 *db, 
   766    802     char **pzErrMsg, 
................................................................................
   773    809       const char *zName;
   774    810     } aFunc[] = {
   775    811        { geopolyAreaFunc,          1,    "geopoly_area"     },
   776    812        { geopolyBlobFunc,          1,    "geopoly_blob"     },
   777    813        { geopolyJsonFunc,          1,    "geopoly_json"     },
   778    814        { geopolyWithinFunc,        3,    "geopoly_within"   },
   779    815        { geopolyOverlapFunc,       2,    "geopoly_overlap"  },
          816  +     { geopolyDebugFunc,         1,    "geopoly_debug"    },
   780    817     };
   781    818     int i;
   782    819     SQLITE_EXTENSION_INIT2(pApi);
   783    820     (void)pzErrMsg;  /* Unused parameter */
   784    821     for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
   785    822       rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
   786    823                                    SQLITE_UTF8, 0,
   787    824                                    aFunc[i].xFunc, 0, 0);
   788    825     }
   789    826     return rc;
   790    827   }