[postgis-commits] svn - r3028 - branches/1.3/lwgeom
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Mon Sep 29 11:25:01 PDT 2008
Author: pramsey
Date: 2008-09-29 11:25:00 -0700 (Mon, 29 Sep 2008)
New Revision: 3028
Modified:
branches/1.3/lwgeom/lwgeom_functions_analytic.c
branches/1.3/lwgeom/lwgeom_functions_lrs.c
branches/1.3/lwgeom/lwgeom_geos_c.c
branches/1.3/lwgeom/lwgeom_rtree.c
branches/1.3/lwgeom/lwgeom_rtree.h
Log:
Backport memory improvements and multi-polygon support for p-i-p
shortcuts from trunk.
Modified: branches/1.3/lwgeom/lwgeom_functions_analytic.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_functions_analytic.c 2008-09-29 16:20:42 UTC (rev 3027)
+++ branches/1.3/lwgeom/lwgeom_functions_analytic.c 2008-09-29 18:25:00 UTC (rev 3028)
@@ -1136,7 +1136,7 @@
* return 1 iff point is inside ring pts
* return 0 iff point is on ring pts
*/
-int point_in_ring(RTREE_NODE *root, POINT2D *point)
+int point_in_ring_rtree(RTREE_NODE *root, POINT2D *point)
{
int wn = 0;
int i;
@@ -1224,7 +1224,7 @@
* return 1 iff point is inside ring pts
* return 0 iff point is on ring pts
*/
-int point_in_ring_deprecated(POINTARRAY *pts, POINT2D *point)
+int point_in_ring(POINTARRAY *pts, POINT2D *point)
{
int wn = 0;
int i;
@@ -1306,7 +1306,7 @@
* return 0 iff point outside polygon or on boundary
* return 1 iff point inside polygon
*/
-int point_in_polygon(RTREE_NODE **root, int ringCount, LWPOINT *point)
+int point_in_polygon_rtree(RTREE_NODE **root, int ringCount, LWPOINT *point)
{
int i;
POINT2D pt;
@@ -1318,7 +1318,7 @@
getPoint2d_p(point->point, 0, &pt);
/* assume bbox short-circuit has already been attempted */
- if(point_in_ring(root[0], &pt) != 1)
+ if(point_in_ring_rtree(root[0], &pt) != 1)
{
#ifdef PGIS_DEBUG
lwnotice("point_in_polygon: outside exterior ring.");
@@ -1328,7 +1328,7 @@
for(i=1; i<ringCount; i++)
{
- if(point_in_ring(root[i], &pt) != -1)
+ if(point_in_ring_rtree(root[i], &pt) != -1)
{
#ifdef PGIS_DEBUG
lwnotice("point_in_polygon: within hole %d.", i);
@@ -1340,150 +1340,192 @@
}
/*
- * return 0 iff point outside polygon or on boundary
- * return 1 iff point inside polygon
+ * return -1 if point outside polygon
+ * return 0 if point on boundary
+ * return 1 if point inside polygon
+ *
+ * Expected **root order is all the exterior rings first, then all the holes
+ *
+ * TODO: this could be made slightly more efficient by ordering the rings in
+ * EIIIEIIIEIEI order (exterior/interior) and including list of exterior ring
+ * positions on the cache object.
*/
-int point_in_polygon_deprecated(LWPOLY *polygon, LWPOINT *point)
+int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int ringCount, LWPOINT *point)
{
- int i;
- POINTARRAY *ring;
- POINT2D pt;
+ int i;
+ POINT2D pt;
+ int result = -1;
#ifdef PGIS_DEBUG_CALLS
- lwnotice("point_in_polygon_deprecated called.");
+ lwnotice("point_in_multipolygon_rtree called for %p %d %d %p.", root, polyCount, ringCount, point);
#endif
- getPoint2d_p(point->point, 0, &pt);
- /* assume bbox short-circuit has already been attempted */
-
- ring = polygon->rings[0];
- /* root = createTree(ring); */
- /* if(point_in_ring(root, &pt) != 1) */
- if(point_in_ring_deprecated(polygon->rings[0], &pt) != 1)
- {
-#ifdef PGIS_DEBUG
- lwnotice("point_in_polygon: outside exterior ring.");
+ getPoint2d_p(point->point, 0, &pt);
+ /* assume bbox short-circuit has already been attempted */
+
+ /* is the point inside (not outside) any of the exterior rings? */
+ for( i = 0; i < polyCount; i++ )
+ {
+ int in_ring = point_in_ring_rtree(root[i], &pt);
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("point_in_multipolygon_rtree: exterior ring (%d), point_in_ring returned %d", i, in_ring);
#endif
- return 0;
- }
+ if( in_ring != -1 ) /* not outside this ring */
+ {
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("point_in_multipolygon_rtree: inside exterior ring.");
+#endif
+ result = in_ring;
+ break;
+ }
+ }
+
+ if( result == -1 ) /* strictly outside all rings */
+ return result;
- for(i=1; i<polygon->nrings; i++)
- {
- ring = polygon->rings[i];
- /* root = createTree(ring); */
- /* if(point_in_ring(root, &pt) != -1) */
- if(point_in_ring_deprecated(polygon->rings[i], &pt) != -1)
- {
-#ifdef PGIS_DEBUG
- lwnotice("point_in_polygon: within hole %d.", i);
+ /* ok, it's in a ring, but if it's in a hole it's still outside */
+ for( i = polyCount; i < ringCount; i++ )
+ {
+ int in_ring = point_in_ring_rtree(root[i], &pt);
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("point_in_multipolygon_rtree: hole (%d), point_in_ring returned %d", i, in_ring);
#endif
- return 0;
- }
- }
- return 1;
+ if( in_ring == 1 ) /* completely inside hole */
+ {
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("point_in_multipolygon_rtree: within hole %d.", i);
+#endif
+ return -1;
+ }
+ if( in_ring == 0 ) /* on the boundary of a hole */
+ {
+ result = 0;
+ }
+ }
+ return result; /* -1 = outside, 0 = boundary, 1 = inside */
+
}
+
+
/*
- * return 0 iff point inside polygon or on boundary
- * return 1 iff point outside polygon
+ * return -1 iff point outside polygon
+ * return 0 iff point on boundary
+ * return 1 iff point inside polygon
*/
-int point_outside_polygon(RTREE_NODE **root, int ringCount, LWPOINT *point)
+int point_in_polygon(LWPOLY *polygon, LWPOINT *point)
{
- int i;
+ int i, result, in_ring;
+ POINTARRAY *ring;
POINT2D pt;
#ifdef PGIS_DEBUG_CALLS
- lwnotice("point_outside_polygon called.");
+ lwnotice("point_in_polygon_deprecated called.");
#endif
getPoint2d_p(point->point, 0, &pt);
/* assume bbox short-circuit has already been attempted */
- if(point_in_ring(root[0], &pt) == -1)
+ ring = polygon->rings[0];
+ in_ring = point_in_ring(polygon->rings[0], &pt);
+ if( in_ring == -1) /* outside the exterior ring */
{
#ifdef PGIS_DEBUG
- lwnotice("point_outside_polygon: outside exterior ring.");
+ lwnotice("point_in_polygon: outside exterior ring.");
#endif
- return 1;
+ return -1;
}
+ result = in_ring;
- for(i=1; i<ringCount; i++)
+ for(i=1; i<polygon->nrings; i++)
{
- if(point_in_ring(root[i], &pt) == 1)
+ ring = polygon->rings[i];
+ in_ring = point_in_ring(polygon->rings[i], &pt);
+ if(in_ring == 1) /* inside a hole => outside the polygon */
{
#ifdef PGIS_DEBUG
- lwnotice("point_outside_polygon: within hole %d.", i);
+ lwnotice("point_in_polygon: within hole %d.", i);
#endif
- return 1;
+ return -1;
}
+ if(in_ring == 0) /* on the edge of a hole */
+ {
+#ifdef PGIS_DEBUG
+ lwnotice("point_in_polygon: on edge of hole %d.", i);
+#endif
+ return 0;
+ }
}
- return 0;
+ return result; /* -1 = outside, 0 = boundary, 1 = inside */
}
/*
- * return 0 iff point inside polygon or on boundary
- * return 1 iff point outside polygon
+ * return -1 iff point outside multipolygon
+ * return 0 iff point on multipolygon boundary
+ * return 1 iff point inside multipolygon
*/
-int point_outside_polygon_deprecated(LWPOLY *polygon, LWPOINT *point)
+int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
{
- int i;
+ int i, j, result, in_ring;
POINTARRAY *ring;
POINT2D pt;
-#ifdef PGIS_DEBUG_CALLS
- lwnotice("point_outside_polygon_deprecated called.");
+#ifdef PGIS_DEBUG
+ lwnotice("point_in_polygon called.");
#endif
getPoint2d_p(point->point, 0, &pt);
/* assume bbox short-circuit has already been attempted */
-
- ring = polygon->rings[0];
- /* root = createTree(ring); */
- /* if(point_in_ring(root, &pt) == -1) */
- if(point_in_ring_deprecated(ring, &pt) == -1)
- {
+
+ result = -1;
+
+ for(j = 0; j < mpolygon->ngeoms; j++ )
+ {
+
+ LWPOLY *polygon = mpolygon->geoms[j];
+ ring = polygon->rings[0];
+ in_ring = point_in_ring(polygon->rings[0], &pt);
+ if( in_ring == -1) /* outside the exterior ring */
+ {
#ifdef PGIS_DEBUG
- lwnotice("point_outside_polygon_deprecated: outside exterior ring.");
+ lwnotice("point_in_polygon: outside exterior ring.");
#endif
- return 1;
- }
+ continue;
+ }
+ if( in_ring == 0 )
+ {
+ return 0;
+ }
- for(i=1; i<polygon->nrings; i++)
- {
+ result = in_ring;
+
+ for(i=1; i<polygon->nrings; i++)
+ {
ring = polygon->rings[i];
- /* root = createTree(ring); */
- /* if(point_in_ring(root, &pt) == 1) */
- if(point_in_ring_deprecated(ring, &pt) == 1)
+ in_ring = point_in_ring(polygon->rings[i], &pt);
+ if(in_ring == 1) /* inside a hole => outside the polygon */
{
#ifdef PGIS_DEBUG
- lwnotice("point_outside_polygon_deprecated: within hole %d.", i);
+ lwnotice("point_in_polygon: within hole %d.", i);
#endif
- return 1;
+ result = -1;
+ break;
}
- }
- return 0;
-}
-
-
-/*
- * return 0 iff point is outside every polygon
- */
-/* Not yet functional.
-int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
-{
- int i;
-
-#ifdef PGIS_DEBUG_CALLS
- lwnotice("point_in_multipolygon called.");
+ if(in_ring == 0) /* on the edge of a hole */
+ {
+#ifdef PGIS_DEBUG
+ lwnotice("point_in_polygon: on edge of hole %d.", i);
#endif
-
- for(i=1; i<mpolygon->ngeoms; i++)
- {
- if(point_in_polygon((LWPOLY *)mpolygon->geoms[i], point)!=0) return 1;
- }
- return 0;
+ return 0;
+ }
+ }
+ if( result != -1)
+ {
+ return result;
+ }
+ }
+ return result;
}
-*/
/*******************************************************************************
Modified: branches/1.3/lwgeom/lwgeom_functions_lrs.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_functions_lrs.c 2008-09-29 16:20:42 UTC (rev 3027)
+++ branches/1.3/lwgeom/lwgeom_functions_lrs.c 2008-09-29 18:25:00 UTC (rev 3028)
@@ -16,8 +16,8 @@
#include "lwgeom_pg.h"
#include "math.h"
-#define DEBUG_LRS 0
-#define DEBUG_INTERPOLATION 0
+#define DEBUG_LRS 1
+#define DEBUG_INTERPOLATION 1
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS);
@@ -151,7 +151,7 @@
* numbers.
*
* The two points must be equal anyway.
- */
+
if ( m0 == m1 )
{
memcpy(p2, p1, sizeof(POINT4D));
@@ -159,6 +159,7 @@
else ret |= 0x0100;
return ret;
}
+XXX */
/*
* Second point out of range, project
@@ -338,7 +339,7 @@
*/
static LWGEOM *
lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
-{
+{
POINTARRAY *ipa=lwline_in->points;
int i;
LWGEOM **geoms;
@@ -377,6 +378,7 @@
/* This is a point */
if ( pa->npoints == 1 )
{
+
lwpoint=lwalloc(sizeof(LWPOINT));
lwpoint->type=lwgeom_makeType_full(
TYPE_HASZ(pa->dims),
@@ -414,6 +416,8 @@
lwerror("ptarray_locate_between_m returned a POINARRAY set containing POINTARRAY with 0 points");
}
+
+
}
if ( ngeoms == 1 )
@@ -427,6 +431,9 @@
else if ( typeflag == 2 ) outtype=MULTILINETYPE;
else outtype = COLLECTIONTYPE;
+ lwnotice(" XXX lwline_locate_between_m: %s", lwgeom_to_ewkt((LWGEOM *)lwcollection_construct(outtype,
+ lwline_in->SRID, NULL, ngeoms, geoms)));
+
return (LWGEOM *)lwcollection_construct(outtype,
lwline_in->SRID, NULL, ngeoms, geoms);
}
Modified: branches/1.3/lwgeom/lwgeom_geos_c.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_geos_c.c 2008-09-29 16:20:42 UTC (rev 3027)
+++ branches/1.3/lwgeom/lwgeom_geos_c.c 2008-09-29 18:25:00 UTC (rev 3028)
@@ -46,6 +46,8 @@
/* #define UNITE_USING_BUFFER 1 */
/* #define MAXGEOMSPOINTS 21760 */
+/* PROTOTYPES start */
+
Datum relate_full(PG_FUNCTION_ARGS);
Datum relate_pattern(PG_FUNCTION_ARGS);
Datum disjoint(PG_FUNCTION_ARGS);
@@ -85,7 +87,13 @@
GEOSGeom LWGEOM2GEOS(LWGEOM *g);
void errorIfGeometryCollection(PG_LWGEOM *g1, PG_LWGEOM *g2);
+int point_in_polygon_rtree(RTREE_NODE **root, int ringCount, LWPOINT *point);
+int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int ringCount, LWPOINT *point);
+int point_in_polygon(LWPOLY *polygon, LWPOINT *point);
+int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *pont);
+/* PROTOTYPES end */
+
PG_FUNCTION_INFO_V1(postgis_geos_version);
Datum postgis_geos_version(PG_FUNCTION_ARGS)
{
@@ -1430,13 +1438,7 @@
PG_RETURN_BOOL(result);
}
-int point_in_polygon(RTREE_NODE **root, int ringCount, LWPOINT *point);
-int point_in_polygon_deprecated(LWPOLY *polygon, LWPOINT *point);
-int point_outside_polygon(RTREE_NODE **root, int ringCount, LWPOINT *point);
-int point_outside_polygon_deprecated(LWPOLY *polygon, LWPOINT *point);
-int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point);
-
PG_FUNCTION_INFO_V1(contains);
Datum contains(PG_FUNCTION_ARGS)
{
@@ -1446,7 +1448,7 @@
bool result;
BOX2DFLOAT4 box1, box2;
int type1, type2;
- LWPOLY *poly;
+ LWGEOM *lwgeom;
/* LWMPOLY *mpoly; */
LWPOINT *point;
RTREE_POLY_CACHE *poly_cache;
@@ -1467,13 +1469,14 @@
* geom1 bounding box we can prematurely return FALSE.
* Do the test IFF BOUNDING BOX AVAILABLE.
*/
- if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
- getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
+ if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) &&
+ getbox2d_p(SERIALIZED_FORM(geom2), &box2) )
{
- if ( box2.xmin < box1.xmin ) PG_RETURN_BOOL(FALSE);
- if ( box2.xmax > box1.xmax ) PG_RETURN_BOOL(FALSE);
- if ( box2.ymin < box1.ymin ) PG_RETURN_BOOL(FALSE);
- if ( box2.ymax > box1.ymax ) PG_RETURN_BOOL(FALSE);
+ if ( ( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) ||
+ ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ) )
+ {
+ PG_RETURN_BOOL(FALSE);
+ }
}
/*
* short-circuit 2: if geom2 is a point and geom1 is a polygon
@@ -1481,13 +1484,13 @@
*/
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POLYGONTYPE && type2 == POINTTYPE)
- {
+ if((type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE) && type2 == POINTTYPE)
+ {
#ifdef PGIS_DEBUG
lwnotice("Point in Polygon test requested...short-circuiting.");
#endif
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom1));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom1));
point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
#ifdef PGIS_DEBUG
lwnotice("Precall point_in_polygon %p, %p", poly, point);
@@ -1499,53 +1502,40 @@
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom1), fcinfo->flinfo->fn_extra);
+ poly_cache = retrieveCache(lwgeom, SERIALIZED_FORM(geom1), fcinfo->flinfo->fn_extra);
fcinfo->flinfo->fn_extra = poly_cache;
MemoryContextSwitchTo(old_context);
- if(point_in_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
+ if( poly_cache->ringIndices )
+ {
+ result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point);
+ }
+ else if ( type1 == POLYGONTYPE )
+ {
+ result = point_in_polygon((LWPOLY*)lwgeom, point);
+ }
+ else if ( type1 == MULTIPOLYGONTYPE )
+ {
+ result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
+ }
+ else {
+ /* Gulp! Should not be here... */
+ elog(ERROR,"Type isn't poly or multipoly!");
+ PG_RETURN_NULL();
+ }
+ PG_FREE_IF_COPY(geom1, 0);
+ PG_FREE_IF_COPY(geom2, 1);
+ lwgeom_release((LWGEOM *)lwgeom);
+ lwgeom_release((LWGEOM *)point);
+ if( result == 1 ) /* completely inside */
+ {
+ PG_RETURN_BOOL(TRUE);
+ }
+ else
+ {
+ PG_RETURN_BOOL(FALSE);
+ }
}
- /* Not yet functional
- else if(type1 == MULTIPOLYGONTYPE && type2 == POINTTYPE)
- {
-#ifdef PGIS_DEBUG
- lwnotice("Point in MultiPolygon test requested...short-circuiting.");
-#endif
- mpoly = lwmpoly_deserialize(SERIALIZED_FORM(geom1));
- point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
- if(point_in_multipolygon(mpoly, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)mpoly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)mpoly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
- }
- */
else
{
#ifdef PGIS_DEBUG
@@ -1612,7 +1602,7 @@
bool result;
BOX2DFLOAT4 box1, box2;
int type1, type2;
- LWPOLY *poly;
+ LWGEOM *lwgeom;
/* LWMPOLY *mpoly; */
LWPOINT *point;
RTREE_POLY_CACHE *poly_cache;
@@ -1648,13 +1638,13 @@
*/
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POLYGONTYPE && type2 == POINTTYPE)
+ if((type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE) && type2 == POINTTYPE)
{
#ifdef PGIS_DEBUG
lwnotice("Point in Polygon test requested...short-circuiting.");
#endif
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom1));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom1));
point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
#ifdef PGIS_DEBUG
lwnotice("Precall point_in_polygon %p, %p", poly, point);
@@ -1666,26 +1656,40 @@
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom1), fcinfo->flinfo->fn_extra);
+ poly_cache = retrieveCache(lwgeom, SERIALIZED_FORM(geom1), fcinfo->flinfo->fn_extra);
fcinfo->flinfo->fn_extra = poly_cache;
MemoryContextSwitchTo(old_context);
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
+ if( poly_cache->ringIndices )
+ {
+ result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point);
+ }
+ else if ( type1 == POLYGONTYPE )
+ {
+ result = point_in_polygon((LWPOLY*)lwgeom, point);
+ }
+ else if ( type1 == MULTIPOLYGONTYPE )
+ {
+ result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
+ }
+ else {
+ /* Gulp! Should not be here... */
+ elog(ERROR,"Type isn't poly or multipoly!");
+ PG_RETURN_NULL();
+ }
+
+ PG_FREE_IF_COPY(geom1, 0);
+ PG_FREE_IF_COPY(geom2, 1);
+ lwgeom_release((LWGEOM *)lwgeom);
+ lwgeom_release((LWGEOM *)point);
+ if( result != -1 ) /* not outside */
+ {
+ PG_RETURN_BOOL(TRUE);
+ }
+ else
+ {
+ PG_RETURN_BOOL(FALSE);
+ }
}
else
{
@@ -1747,7 +1751,7 @@
GEOSGeom g1,g2;
bool result;
BOX2DFLOAT4 box1, box2;
- LWPOLY *poly;
+ LWGEOM *lwgeom;
LWPOINT *point;
int type1, type2;
MemoryContext old_context;
@@ -1782,14 +1786,14 @@
*/
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POINTTYPE && type2 == POLYGONTYPE)
+ if((type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE) && type1 == POINTTYPE)
{
#ifdef PGIS_DEBUG
lwnotice("Point in Polygon test requested...short-circuiting.");
#endif
point = lwpoint_deserialize(SERIALIZED_FORM(geom1));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom2));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom2));
/*
* Switch the context to the function-scope context,
@@ -1797,26 +1801,40 @@
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
+ poly_cache = retrieveCache(lwgeom, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
fcinfo->flinfo->fn_extra = poly_cache;
MemoryContextSwitchTo(old_context);
- if(point_in_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
+ if( poly_cache->ringIndices )
+ {
+ result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point);
+ }
+ else if ( type2 == POLYGONTYPE )
+ {
+ result = point_in_polygon((LWPOLY*)lwgeom, point);
+ }
+ else if ( type2 == MULTIPOLYGONTYPE )
+ {
+ result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
+ }
+ else {
+ /* Gulp! Should not be here... */
+ elog(ERROR,"Type isn't poly or multipoly!");
+ PG_RETURN_NULL();
+ }
+
+ PG_FREE_IF_COPY(geom1, 0);
+ PG_FREE_IF_COPY(geom2, 1);
+ lwgeom_release((LWGEOM *)lwgeom);
+ lwgeom_release((LWGEOM *)point);
+ if( result == 1 ) /* completely inside */
+ {
+ PG_RETURN_BOOL(TRUE);
+ }
+ else
+ {
+ PG_RETURN_BOOL(FALSE);
+ }
}
initGEOS(lwnotice, lwnotice);
@@ -1877,7 +1895,7 @@
GEOSGeom g1,g2;
bool result;
BOX2DFLOAT4 box1, box2;
- LWPOLY *poly;
+ LWGEOM *lwgeom;
LWPOINT *point;
int type1, type2;
MemoryContext old_context;
@@ -1917,14 +1935,14 @@
*/
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POINTTYPE && type2 == POLYGONTYPE)
+ if((type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE) && type1 == POINTTYPE)
{
#ifdef PGIS_DEBUG
lwnotice("Point in Polygon test requested...short-circuiting.");
#endif
point = lwpoint_deserialize(SERIALIZED_FORM(geom1));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom2));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom2));
/*
* Switch the context to the function-scope context,
@@ -1932,26 +1950,40 @@
* future use, then switch back to the local context.
*/
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
+ poly_cache = retrieveCache(lwgeom, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
fcinfo->flinfo->fn_extra = poly_cache;
MemoryContextSwitchTo(old_context);
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
+ if( poly_cache->ringIndices )
+ {
+ result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point);
+ }
+ else if ( type2 == POLYGONTYPE )
+ {
+ result = point_in_polygon((LWPOLY*)lwgeom, point);
+ }
+ else if ( type2 == MULTIPOLYGONTYPE )
+ {
+ result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
+ }
+ else {
+ /* Gulp! Should not be here... */
+ elog(ERROR,"Type isn't poly or multipoly!");
+ PG_RETURN_NULL();
+ }
+
+ PG_FREE_IF_COPY(geom1, 0);
+ PG_FREE_IF_COPY(geom2, 1);
+ lwgeom_release((LWGEOM *)lwgeom);
+ lwgeom_release((LWGEOM *)point);
+ if( result != -1 ) /* not outside */
+ {
+ PG_RETURN_BOOL(TRUE);
+ }
+ else
+ {
+ PG_RETURN_BOOL(FALSE);
+ }
}
initGEOS(lwnotice, lwnotice);
@@ -2085,13 +2117,14 @@
Datum intersects(PG_FUNCTION_ARGS)
{
PG_LWGEOM *geom1;
- PG_LWGEOM *geom2;
+ PG_LWGEOM *geom2;
+ uchar *serialized_poly;
GEOSGeom g1,g2;
bool result;
BOX2DFLOAT4 box1, box2;
- int type1, type2;
+ int type1, type2, polytype;
LWPOINT *point;
- LWPOLY *poly;
+ LWGEOM *lwgeom;
MemoryContext old_context;
RTREE_POLY_CACHE *poly_cache;
@@ -2125,76 +2158,63 @@
*/
type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POINTTYPE && type2 == POLYGONTYPE)
+ if( (type1 == POINTTYPE && (type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE)) ||
+ (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE)))
{
#ifdef PGIS_DEBUG
lwnotice("Point in Polygon test requested...short-circuiting.");
#endif
- point = lwpoint_deserialize(SERIALIZED_FORM(geom1));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom2));
+ if( type1 == POINTTYPE ) {
+ point = lwpoint_deserialize(SERIALIZED_FORM(geom1));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom2));
+ serialized_poly = SERIALIZED_FORM(geom2);
+ polytype = type2;
+ } else {
+ point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
+ lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom1));
+ serialized_poly = SERIALIZED_FORM(geom1);
+ polytype = type1;
+ }
- /*
- * Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
- * future use, then switch back to the local context.
- */
- old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
- fcinfo->flinfo->fn_extra = poly_cache;
- MemoryContextSwitchTo(old_context);
+ /*
+ * Switch the context to the function-scope context,
+ * retrieve the appropriate cache object, cache it for
+ * future use, then switch back to the local context.
+ */
+ old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
+ poly_cache = retrieveCache(lwgeom, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
+ fcinfo->flinfo->fn_extra = poly_cache;
+ MemoryContextSwitchTo(old_context);
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
+ if( poly_cache->ringIndices )
{
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
+ result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point);
}
- else
+ else if ( polytype == POLYGONTYPE )
{
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
+ result = point_in_polygon((LWPOLY*)lwgeom, point);
}
- }
- else if(type1 == POLYGONTYPE && type2 == POINTTYPE)
- {
- #ifdef PGIS_DEBUG
- lwnotice("Point in Polygon test requested...short-circuiting.");
-#endif
- point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom1));
+ else if ( polytype == MULTIPOLYGONTYPE )
+ {
+ result = point_in_multipolygon((LWMPOLY*)lwgeom, point);
+ }
+ else {
+ /* Gulp! Should not be here... */
+ elog(ERROR,"Type isn't poly or multipoly!");
+ PG_RETURN_NULL();
+ }
- /*
- * Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
- * future use, then switch back to the local context.
- */
- old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom1), fcinfo->flinfo->fn_extra);
- fcinfo->flinfo->fn_extra = poly_cache;
- MemoryContextSwitchTo(old_context);
-
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
+ PG_FREE_IF_COPY(geom1, 0);
+ PG_FREE_IF_COPY(geom2, 1);
+ lwgeom_release((LWGEOM *)lwgeom);
+ lwgeom_release((LWGEOM *)point);
+ if( result != -1 ) /* not outside */
{
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
PG_RETURN_BOOL(TRUE);
}
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 1);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
+ else {
PG_RETURN_BOOL(FALSE);
}
-
}
@@ -2329,11 +2349,6 @@
GEOSGeom g1,g2;
bool result;
BOX2DFLOAT4 box1, box2;
- int type1, type2;
- LWPOLY *poly;
- LWPOINT *point;
- MemoryContext old_context;
- RTREE_POLY_CACHE *poly_cache;
#ifdef PROFILE
profstart(PROF_QRUN);
@@ -2359,83 +2374,6 @@
if ( box2.ymin > box1.ymax ) PG_RETURN_BOOL(TRUE);
}
- /*
- * short-circuit 2: if the geoms are a point and a polygon,
- * call the point_outside_polygon function.
- */
- type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]);
- type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]);
- if(type1 == POINTTYPE && type2 == POLYGONTYPE)
- {
-#ifdef PGIS_DEBUG
- lwnotice("Point outside Polygon test requested...short-circuiting.");
-#endif
- point = lwpoint_deserialize(SERIALIZED_FORM(geom1));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom2));
-
- /*
- * Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
- * future use, then switch back to the local context.
- */
- old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
- fcinfo->flinfo->fn_extra = poly_cache;
- MemoryContextSwitchTo(old_context);
-
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 0);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 0);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
- }
- else if(type1 == POLYGONTYPE && type2 == POINTTYPE)
- {
-#ifdef PGIS_DEBUG
- lwnotice("Point outside Polygon test requested...short-circuiting.");
-#endif
- point = lwpoint_deserialize(SERIALIZED_FORM(geom2));
- poly = lwpoly_deserialize(SERIALIZED_FORM(geom1));
-
- /*
- * Switch the context to the function-scope context,
- * retrieve the appropriate cache object, cache it for
- * future use, then switch back to the local context.
- */
- old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- poly_cache = retrieveCache(poly, SERIALIZED_FORM(geom2), fcinfo->flinfo->fn_extra);
- fcinfo->flinfo->fn_extra = poly_cache;
- MemoryContextSwitchTo(old_context);
-
- if(point_outside_polygon(poly_cache->ringIndices, poly_cache->ringCount, point) == 0)
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 0);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(FALSE);
- }
- else
- {
- PG_FREE_IF_COPY(geom1, 0);
- PG_FREE_IF_COPY(geom2, 0);
- lwgeom_release((LWGEOM *)poly);
- lwgeom_release((LWGEOM *)point);
- PG_RETURN_BOOL(TRUE);
- }
- }
-
initGEOS(lwnotice, lwnotice);
#ifdef PROFILE
Modified: branches/1.3/lwgeom/lwgeom_rtree.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_rtree.c 2008-09-29 16:20:42 UTC (rev 3027)
+++ branches/1.3/lwgeom/lwgeom_rtree.c 2008-09-29 18:25:00 UTC (rev 3028)
@@ -77,6 +77,7 @@
}
root = nodes[0];
+ lwfree(nodes);
#ifdef PGIS_DEBUG
lwnotice("createTree returning %p", root);
@@ -207,17 +208,42 @@
#ifdef PGIS_DEBUG_CALLS
lwnotice("freeTree called for %p", root);
#endif
- if(root->leftNode)
- freeTree(root->leftNode);
- if(root->rightNode)
- freeTree(root->rightNode);
- lwfree(root->interval);
- if(root->segment)
- lwfree(root->segment);
- lwfree(root);
+ if(root->leftNode)
+ freeTree(root->leftNode);
+ if(root->rightNode)
+ freeTree(root->rightNode);
+ lwfree(root->interval);
+ if(root->segment) {
+ lwfree(root->segment->points->serialized_pointlist);
+ lwfree(root->segment->points);
+ lwgeom_release((LWGEOM *)root->segment);
+ }
+ lwfree(root);
}
/*
+ * Free the cache object and all the sub-objects properly.
+ */
+void clearCache(RTREE_POLY_CACHE *cache)
+{
+ int i;
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("clearCache called for %p", cache);
+#endif
+ for(i = 0; i < cache->ringCount; i++)
+ {
+ freeTree(cache->ringIndices[i]);
+ }
+ lwfree(cache->ringIndices);
+ lwfree(cache->poly);
+ cache->poly = 0;
+ cache->ringIndices = 0;
+ cache->ringCount = 0;
+ cache->polyCount = 0;
+}
+
+
+/*
* Retrieves a collection of line segments given the root and crossing value.
* The collection is a multilinestring consisting of two point lines
* representing the segments of the ring that may be crossed by the
@@ -387,28 +413,98 @@
}
-RTREE_POLY_CACHE *createNewCache(LWPOLY *poly, uchar *serializedPoly)
+RTREE_POLY_CACHE * createCache()
{
- RTREE_POLY_CACHE *result;
- int i, length;
+ RTREE_POLY_CACHE *result;
+ result = lwalloc(sizeof(RTREE_POLY_CACHE));
+ result->polyCount = 0;
+ result->ringCount = 0;
+ result->ringIndices = 0;
+ result->poly = 0;
+ return result;
+}
+void populateCache(RTREE_POLY_CACHE *currentCache, LWGEOM *lwgeom, uchar *serializedPoly)
+{
+ int i, j, k, length;
+ LWMPOLY *mpoly;
+ LWPOLY *poly;
+ int nrings;
+
#ifdef PGIS_DEBUG_CALLS
- lwnotice("createNewCache called with %p", poly);
+ lwnotice("populateCache called with cache %p geom %p", currentCache, lwgeom);
#endif
- result = lwalloc(sizeof(RTREE_POLY_CACHE));
- result->ringIndices = lwalloc(sizeof(RTREE_NODE *) * poly->nrings);
- result->ringCount = poly->nrings;
- length = lwgeom_size_poly(serializedPoly);
- result->poly = lwalloc(length);
- memcpy(result->poly, serializedPoly, length);
- for(i = 0; i < result->ringCount; i++)
- {
- result->ringIndices[i] = createTree(poly->rings[i]);
- }
-#ifdef PGIS_DEBUG
- lwnotice("createNewCache returning %p", result);
+
+ if(TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE)
+ {
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("populateCache MULTIPOLYGON");
#endif
- return result;
+ mpoly = (LWMPOLY *)lwgeom;
+ nrings = 0;
+ /*
+ ** Count the total number of rings.
+ */
+ for( i = 0; i < mpoly->ngeoms; i++ )
+ {
+ nrings += mpoly->geoms[i]->nrings;
+ }
+ currentCache->polyCount = mpoly->ngeoms;
+ currentCache->ringCount = nrings;
+ currentCache->ringIndices = lwalloc(sizeof(RTREE_NODE *) * nrings);
+ /*
+ ** Load the exterior rings onto the ringIndices array first
+ */
+ for( i = 0; i < mpoly->ngeoms; i++ )
+ {
+ currentCache->ringIndices[i] = createTree(mpoly->geoms[i]->rings[0]);
+ }
+ /*
+ ** Load the interior rings (holes) onto ringIndices next
+ */
+ for( j = 0; j < mpoly->ngeoms; j++ )
+ {
+ for( k = 1; k < mpoly->geoms[j]->nrings; k++ )
+ {
+ currentCache->ringIndices[i] = createTree(mpoly->geoms[j]->rings[k]);
+ i++;
+ }
+ }
+ }
+ else if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
+ {
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("populateCache POLYGON");
+#endif
+ poly = (LWPOLY *)lwgeom;
+ currentCache->polyCount = 1;
+ currentCache->ringCount = poly->nrings;
+ /*
+ ** Just load the rings on in order
+ */
+ currentCache->ringIndices = lwalloc(sizeof(RTREE_NODE *) * poly->nrings);
+ for( i = 0; i < poly->nrings; i++ )
+ {
+ currentCache->ringIndices[i] = createTree(poly->rings[i]);
+ }
+ }
+ else
+ {
+ /* Uh oh, shouldn't be here. */
+ return;
+ }
+
+ /*
+ ** Copy the serialized form of the polygon into the cache so
+ ** we can test for equality against subsequent polygons.
+ */
+ length = lwgeom_size(serializedPoly);
+ currentCache->poly = lwalloc(length);
+ memcpy(currentCache->poly, serializedPoly, length);
+#ifdef PGIS_DEBUG_CALLS
+ lwnotice("populateCache returning %p", currentCache);
+#endif
+
}
/*
@@ -418,10 +514,10 @@
* method. The method will allocate memory for the cache it creates,
* as well as freeing the memory of any cache that is no longer applicable.
*/
-RTREE_POLY_CACHE *retrieveCache(LWPOLY *poly, uchar *serializedPoly,
+RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, uchar *serializedPoly,
RTREE_POLY_CACHE *currentCache)
{
- int i, length;
+ int length;
#ifdef PGIS_DEBUG_CALLS
lwnotice("retrieveCache called with %p %p %p", poly, serializedPoly, currentCache);
@@ -431,51 +527,35 @@
#ifdef PGIS_DEBUG
lwnotice("No existing cache, create one.");
#endif
- return createNewCache(poly, serializedPoly);
+ return createCache();
}
if(!(currentCache->poly))
{
#ifdef PGIS_DEBUG
- lwnotice("Cache contains no polygon, creating new cache.");
+ lwnotice("Cache contains no polygon, populating it.");
#endif
- return createNewCache(poly, serializedPoly);
+ populateCache(currentCache, lwgeom, serializedPoly);
+ return currentCache;
}
length = lwgeom_size_poly(serializedPoly);
- if(lwgeom_size_poly(currentCache->poly) != length)
+ if(lwgeom_size(currentCache->poly) != length)
{
#ifdef PGIS_DEBUG
lwnotice("Polygon size mismatch, creating new cache.");
#endif
- for(i = 0; i < currentCache->ringCount; i++)
- {
- freeTree(currentCache->ringIndices[i]);
- }
- lwfree(currentCache->ringIndices);
- lwfree(currentCache->poly);
- lwfree(currentCache);
- return createNewCache(poly, serializedPoly);
- }
- for(i = 0; i < length; i++)
- {
- uchar a = serializedPoly[i];
- uchar b = currentCache->poly[i];
- if(a != b)
- {
+ clearCache(currentCache);
+ return currentCache;
+ }
+ if( memcmp(serializedPoly, currentCache->poly, length) )
+ {
#ifdef PGIS_DEBUG
- lwnotice("Polygon mismatch, creating new cache. %c, %c", a, b);
+ lwnotice("Polygon mismatch, creating new cache. %c, %c", a, b);
#endif
- for(i = 0; i < currentCache->ringCount; i++)
- {
- freeTree(currentCache->ringIndices[i]);
- }
- lwfree(currentCache->ringIndices);
- lwfree(currentCache->poly);
- lwfree(currentCache);
- return createNewCache(poly, serializedPoly);
- }
- }
+ clearCache(currentCache);
+ return currentCache;
+ }
#ifdef PGIS_DEBUG
lwnotice("Polygon match, retaining current cache, %p.", currentCache);
Modified: branches/1.3/lwgeom/lwgeom_rtree.h
===================================================================
--- branches/1.3/lwgeom/lwgeom_rtree.h 2008-09-29 16:20:42 UTC (rev 3027)
+++ branches/1.3/lwgeom/lwgeom_rtree.h 2008-09-29 18:25:00 UTC (rev 3028)
@@ -47,6 +47,7 @@
{
RTREE_NODE **ringIndices;
int ringCount;
+ int polyCount;
uchar *poly;
} RTREE_POLY_CACHE;
@@ -54,6 +55,10 @@
* Creates a new cachable index if needed, or returns the current cache if
* it is applicable to the current polygon.
*/
-RTREE_POLY_CACHE *retrieveCache(LWPOLY *poly, uchar *serializedPoly, RTREE_POLY_CACHE *currentCache);
+RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, uchar *serializedPoly, RTREE_POLY_CACHE *currentCache);
+RTREE_POLY_CACHE *createCache(void);
+/* Frees the cache. */
+void populateCache(RTREE_POLY_CACHE *cache, LWGEOM *lwgeom, uchar *serializedPoly);
+void clearCache(RTREE_POLY_CACHE *cache);
#endif /* !defined _LIBLWGEOM_H */
More information about the postgis-commits
mailing list