mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Split the three-argument version of geopoly_within() off into a separate
function named geopoly_contains_point(). FossilOrigin-Name: 5a0e1541037b5bbc1b4bf26a7da304c9b32ea72960aca8b9309cf2180757c8a4
This commit is contained in:
@ -579,17 +579,50 @@ static int pointBeneathLine(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2);
|
||||
|
||||
/*
|
||||
** SQL function: geopoly_within(P,X,Y) -- 3-argument form
|
||||
** SQL function: geopoly_contains_point(P,X,Y)
|
||||
**
|
||||
** 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
|
||||
*/
|
||||
static void geopolyContainsPointFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
|
||||
double x0 = sqlite3_value_double(argv[1]);
|
||||
double y0 = sqlite3_value_double(argv[2]);
|
||||
int v = 0;
|
||||
int cnt = 0;
|
||||
int ii;
|
||||
if( p1==0 ) return;
|
||||
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,p1->a[ii*2],p1->a[ii*2+1],
|
||||
p1->a[0],p1->a[1]);
|
||||
}
|
||||
if( v==2 ){
|
||||
sqlite3_result_int(context, 1);
|
||||
}else if( ((v+cnt)&1)==0 ){
|
||||
sqlite3_result_int(context, 0);
|
||||
}else{
|
||||
sqlite3_result_int(context, 2);
|
||||
}
|
||||
sqlite3_free(p1);
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2);
|
||||
|
||||
/*
|
||||
** SQL function: geopoly_within(P1,P2)
|
||||
**
|
||||
** Return +2 if P1 and P2 are the same polygon
|
||||
** Return +1 if P2 is contained within P1
|
||||
@ -602,44 +635,17 @@ static void geopolyWithinFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
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<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,p1->a[ii*2],p1->a[ii*2+1],
|
||||
p1->a[0],p1->a[1]);
|
||||
}
|
||||
if( v==2 ){
|
||||
sqlite3_result_int(context, 1);
|
||||
}else if( ((v+cnt)&1)==0 ){
|
||||
sqlite3_result_int(context, 0);
|
||||
GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0);
|
||||
if( p1 && p2 ){
|
||||
int x = geopolyOverlap(p1, p2);
|
||||
if( x<0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_int(context, 2);
|
||||
}
|
||||
}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_result_int(context, x==2 ? 1 : x==4 ? 2 : 0);
|
||||
}
|
||||
}
|
||||
sqlite3_free(p1);
|
||||
sqlite3_free(p2);
|
||||
}
|
||||
|
||||
/* Objects used by the overlap algorihm. */
|
||||
@ -1486,7 +1492,7 @@ static int geopolyFindFunction(
|
||||
*ppArg = 0;
|
||||
return SQLITE_INDEX_CONSTRAINT_FUNCTION;
|
||||
}
|
||||
if( nArg==2 && sqlite3_stricmp(zName, "geopoly_within")==0 ){
|
||||
if( sqlite3_stricmp(zName, "geopoly_within")==0 ){
|
||||
*pxFunc = geopolyWithinFunc;
|
||||
*ppArg = 0;
|
||||
return SQLITE_INDEX_CONSTRAINT_FUNCTION+1;
|
||||
@ -1528,16 +1534,16 @@ static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
int nArg;
|
||||
const char *zName;
|
||||
} aFunc[] = {
|
||||
{ geopolyAreaFunc, 1, "geopoly_area" },
|
||||
{ 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" },
|
||||
{ geopolyBBoxFunc, 1, "geopoly_bbox" },
|
||||
{ geopolyXformFunc, 7, "geopoly_xform" },
|
||||
{ geopolyAreaFunc, 1, "geopoly_area" },
|
||||
{ geopolyBlobFunc, 1, "geopoly_blob" },
|
||||
{ geopolyJsonFunc, 1, "geopoly_json" },
|
||||
{ geopolySvgFunc, -1, "geopoly_svg" },
|
||||
{ geopolyWithinFunc, 2, "geopoly_within" },
|
||||
{ geopolyContainsPointFunc, 3, "geopoly_contains_point" },
|
||||
{ geopolyOverlapFunc, 2, "geopoly_overlap" },
|
||||
{ geopolyDebugFunc, 1, "geopoly_debug" },
|
||||
{ geopolyBBoxFunc, 1, "geopoly_bbox" },
|
||||
{ geopolyXformFunc, 7, "geopoly_xform" },
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
|
Reference in New Issue
Block a user