[postgis-commits] svn - r2795 - branches/1.3/lwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Wed May 28 15:58:35 PDT 2008


Author: pramsey
Date: 2008-05-28 15:58:35 -0700 (Wed, 28 May 2008)
New Revision: 2795

Modified:
   branches/1.3/lwgeom/box2d.c
   branches/1.3/lwgeom/liblwgeom.h
   branches/1.3/lwgeom/lwgeom_functions_analytic.c
   branches/1.3/lwgeom/lwgeom_functions_basic.c
   branches/1.3/lwgeom/lwgeom_svg.c
   branches/1.3/lwgeom/lwpostgis.sql.in
   branches/1.3/lwgeom/measures.c
Log:
Enhanced speed _ST_DWithin(g,g,d) that returns as soon as g and g are within d of each other, rather than using distance naively. Change ST_DWithin to use enhanced op. (Issue 20)


Modified: branches/1.3/lwgeom/box2d.c
===================================================================
--- branches/1.3/lwgeom/box2d.c	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/box2d.c	2008-05-28 22:58:35 UTC (rev 2795)
@@ -37,12 +37,12 @@
 		(box1->xmin==box2->xmin) &&
 		(box1->ymax==box2->ymax) &&
 		(box1->ymin==box2->ymin));
-#if 0 // changed to exact equality
+#if 0 
 	return(FPeq(box1->xmax, box2->xmax) &&
 				   FPeq(box1->xmin, box2->xmin) &&
 				   FPeq(box1->ymax, box2->ymax) &&
 				   FPeq(box1->ymin, box2->ymin));
-#endif // 0
+#endif
 }
 
 BOX2DFLOAT4 *

Modified: branches/1.3/lwgeom/liblwgeom.h
===================================================================
--- branches/1.3/lwgeom/liblwgeom.h	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/liblwgeom.h	2008-05-28 22:58:35 UTC (rev 2795)
@@ -943,6 +943,7 @@
 extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
 extern int azimuth_pt_pt(POINT2D *p1, POINT2D *p2, double *ret);
 extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2);
+extern double lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance);
 extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
 extern int32 lwgeom_npoints(uchar *serialized);
 extern char ptarray_isccw(const POINTARRAY *pa);

Modified: branches/1.3/lwgeom/lwgeom_functions_analytic.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_functions_analytic.c	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/lwgeom_functions_analytic.c	2008-05-28 22:58:35 UTC (rev 2795)
@@ -785,7 +785,7 @@
 	PG_LWGEOM *out_geom = NULL;
 	LWGEOM *out_lwgeom;
 	gridspec grid;
-	//BOX3D box3d;
+	/* BOX3D box3d; */
 
 	if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
 	datum = PG_GETARG_DATUM(0);
@@ -850,7 +850,7 @@
 
 		out_lwgeom->bbox = box3d_to_box2df(&box3d);
 	}
-#endif // 0
+#endif /* 0 */
 
 #if VERBOSE
 	elog(NOTICE, "SnapToGrid made a %s", lwgeom_typename(TYPE_GETTYPE(out_lwgeom->type)));
@@ -871,7 +871,7 @@
 	PG_LWGEOM *out_geom = NULL;
 	LWGEOM *out_lwgeom;
 	gridspec grid;
-	//BOX3D box3d;
+	/* BOX3D box3d; */
 	POINT4D offsetpoint;
 
 	if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
@@ -956,7 +956,7 @@
 
 		out_lwgeom->bbox = box3d_to_box2df(&box3d);
 	}
-#endif // 0
+#endif /* 0 */
 
 #if VERBOSE
 	elog(NOTICE, "SnapToGrid made a %s", lwgeom_typename(TYPE_GETTYPE(out_lwgeom->type)));
@@ -1009,7 +1009,7 @@
 
 	opa = ptarray_substring(ipa, from, to);
 
-	if ( opa->npoints == 1 ) // Point returned
+	if ( opa->npoints == 1 ) /* Point returned */
 		olwgeom = (LWGEOM *)lwpoint_construct(iline->SRID, NULL, opa);
 	else
 		olwgeom = (LWGEOM *)lwline_construct(iline->SRID, NULL, opa);
@@ -1357,8 +1357,8 @@
         /* assume bbox short-circuit has already been attempted */
         
         ring = polygon->rings[0];
-        //root = createTree(ring);
-        //if(point_in_ring(root, &pt) != 1) 
+        /* root = createTree(ring); */
+        /* if(point_in_ring(root, &pt) != 1)  */
         if(point_in_ring_deprecated(polygon->rings[0], &pt) != 1)
         {
 #ifdef PGIS_DEBUG
@@ -1370,8 +1370,8 @@
         for(i=1; i<polygon->nrings; i++)
         {
                 ring = polygon->rings[i];
-                //root = createTree(ring);
-                //if(point_in_ring(root, &pt) != -1) 
+                /* root = createTree(ring); */
+                /* if(point_in_ring(root, &pt) != -1) */
                 if(point_in_ring_deprecated(polygon->rings[i], &pt) != -1)
                 {
 #ifdef PGIS_DEBUG
@@ -1438,8 +1438,8 @@
         /* assume bbox short-circuit has already been attempted */
         
         ring = polygon->rings[0];
-        //root = createTree(ring);
-        //if(point_in_ring(root, &pt) == -1) 
+        /* root = createTree(ring); */
+        /* if(point_in_ring(root, &pt) == -1) */
         if(point_in_ring_deprecated(ring, &pt) == -1)
         {
 #ifdef PGIS_DEBUG
@@ -1451,8 +1451,8 @@
         for(i=1; i<polygon->nrings; i++)
         {
                 ring = polygon->rings[i];
-                //root = createTree(ring);
-                //if(point_in_ring(root, &pt) == 1) 
+                /* root = createTree(ring); */
+                /* if(point_in_ring(root, &pt) == 1)  */
                 if(point_in_ring_deprecated(ring, &pt) == 1)
                 {
 #ifdef PGIS_DEBUG

Modified: branches/1.3/lwgeom/lwgeom_functions_basic.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_functions_basic.c	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/lwgeom_functions_basic.c	2008-05-28 22:58:35 UTC (rev 2795)
@@ -34,6 +34,7 @@
 Datum LWGEOM_npoints(PG_FUNCTION_ARGS);
 Datum LWGEOM_nrings(PG_FUNCTION_ARGS);
 Datum LWGEOM_area_polygon(PG_FUNCTION_ARGS);
+Datum LWGEOM_dwithin(PG_FUNCTION_ARGS);
 Datum postgis_uses_stats(PG_FUNCTION_ARGS);
 Datum postgis_autocache_bbox(PG_FUNCTION_ARGS);
 Datum postgis_scripts_released(PG_FUNCTION_ARGS);
@@ -1622,6 +1623,50 @@
 	PG_RETURN_FLOAT8(mindist);
 }
 
+/* Minimum 2d distance between objects in geom1 and geom2. */
+PG_FUNCTION_INFO_V1(LWGEOM_dwithin);
+Datum LWGEOM_dwithin(PG_FUNCTION_ARGS)
+{
+	PG_LWGEOM *geom1;
+	PG_LWGEOM *geom2;
+	double mindist, tolerance;
+
+#ifdef PROFILE
+	profstart(PROF_QRUN);
+#endif
+
+	geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+	geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+  tolerance = PG_GETARG_FLOAT8(2);
+
+  if( tolerance < 0 ) {		
+    elog(ERROR,"Tolerance cannot be less than zero\n");
+		PG_RETURN_NULL();
+  }
+
+	if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2))
+	{
+		elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
+		PG_RETURN_NULL();
+	}
+
+	mindist = lwgeom_mindistance2d_recursive_tolerance(
+	            SERIALIZED_FORM(geom1),
+		          SERIALIZED_FORM(geom2), 
+		          tolerance
+		        );
+
+#ifdef PROFILE
+	profstop(PROF_QRUN);
+	profreport("dist",geom1, geom2, NULL);
+#endif
+
+	PG_FREE_IF_COPY(geom1, 0);
+	PG_FREE_IF_COPY(geom2, 1);
+
+	PG_RETURN_BOOL(tolerance >= mindist);
+}
+
 /*
  *  Maximum 2d distance between linestrings.
  *  Returns NULL if given geoms are not linestrings.

Modified: branches/1.3/lwgeom/lwgeom_svg.c
===================================================================
--- branches/1.3/lwgeom/lwgeom_svg.c	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/lwgeom_svg.c	2008-05-28 22:58:35 UTC (rev 2795)
@@ -280,7 +280,7 @@
 	{
 		getPoint2d_p(pa, u, &pt);
 	      
-		//close PATH with 'Z' for polygon rings if last point equals first point
+		/* close PATH with 'Z' for polygon rings if last point equals first point */
 		if(u > 0 && u == (pa->npoints - 1) && polygonRing)
 		  {
 		    POINT2D firstPoint;
@@ -333,7 +333,7 @@
 
 	  if(u == (pa->npoints - 1) && polygonRing)
 	    {
-	      //close PATH with 'z' if last point equals first point
+	      /* close PATH with 'z' if last point equals first point */
 	      POINT2D firstPoint;
 	      getPoint2d_p(pa, 0, &firstPoint);
 	      if(pt.x == firstPoint.x && pt.y == firstPoint.y)

Modified: branches/1.3/lwgeom/lwpostgis.sql.in
===================================================================
--- branches/1.3/lwgeom/lwpostgis.sql.in	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/lwpostgis.sql.in	2008-05-28 22:58:35 UTC (rev 2795)
@@ -4430,10 +4430,16 @@
     AS 'SELECT $1 && $2 AND _ST_Touches($1,$2)'
     LANGUAGE 'SQL' _IMMUTABLE; -- WITH (iscachable);
 
+-- Availability: 1.3.4
+CREATEFUNCTION _ST_DWithin(geometry,geometry,float8)
+    RETURNS boolean
+    AS '@MODULE_FILENAME@', 'LWGEOM_dwithin'
+    LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
 -- Availability: 1.2.2
 CREATEFUNCTION ST_DWithin(geometry, geometry, float8)
     RETURNS boolean
-    AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND ST_Distance($1, $2) < $3'
+    AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DWithin($1, $2, $3)'
     LANGUAGE 'SQL' _IMMUTABLE; -- WITH (iscachable);
 
 -- Deprecation in 1.2.3

Modified: branches/1.3/lwgeom/measures.c
===================================================================
--- branches/1.3/lwgeom/measures.c	2008-05-28 21:58:32 UTC (rev 2794)
+++ branches/1.3/lwgeom/measures.c	2008-05-28 22:58:35 UTC (rev 2795)
@@ -47,7 +47,7 @@
 
 #ifdef PGIS_DEBUG
 	lwnotice("pt_in_ring_2d called with point: %g %g", p->x, p->y);
-	//printPA(ring);
+	/* printPA(ring); */
 #endif
 
 	/* loop through all edges of the polygon */
@@ -91,10 +91,10 @@
 
 	return sqrt ( hside*hside + vside*vside );
 
-	// the above is more readable
-	//return sqrt(
-	//	(p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
-	//	); 
+	/* the above is more readable
+	   return sqrt(
+	  	(p2->x-p1->x) * (p2->x-p1->x) + (p2->y-p1->y) * (p2->y-p1->y)
+		);  */
 }
 
 /*distance2d from p to line A->B */
@@ -510,7 +510,7 @@
 				poly2->rings[j]);
 			if ( d <= 0 ) return 0.0;
 
-			// mindist is -1 when not yet set
+			/* mindist is -1 when not yet set */
 			if (mindist > -1) mindist = LW_MIN(mindist, d);
 			else mindist = d;
 #ifdef PGIS_DEBUG
@@ -677,6 +677,12 @@
 double
 lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2)
 {
+  return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 );
+}
+
+double
+lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance)
+{
 	LWGEOM_INSPECTED *in1, *in2;
 	int i, j;
 	double mindist = -1;
@@ -688,13 +694,13 @@
 	{
 		uchar *g1 = lwgeom_getsubgeometry_inspected(in1, i);
 		int t1 = lwgeom_getType(g1[0]);
-		double dist=0;
+		double dist=tolerance;
 
 		/* it's a multitype... recurse */
 		if ( t1 >= 4 )
 		{
-			dist = lwgeom_mindistance2d_recursive(g1, lw2);
-			if ( dist == 0 ) return 0.0; /* can't be closer */
+			dist = lwgeom_mindistance2d_recursive_tolerance(g1, lw2, tolerance);
+			if ( dist <= tolerance ) return tolerance; /* can't be closer */
 			if ( mindist == -1 ) mindist = dist;
 			else mindist = LW_MIN(dist, mindist);
 			continue;
@@ -779,7 +785,7 @@
 			}
 			else /* it's a multitype... recurse */
 			{
-				dist = lwgeom_mindistance2d_recursive(g1, g2);
+				dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance);
 			}
 
 			if (mindist == -1 ) mindist = dist;
@@ -791,7 +797,7 @@
 #endif
 
 
-			if (mindist <= 0.0) return 0.0; /* can't be closer */
+			if (mindist <= tolerance) return tolerance; /* can't be closer */
 
 		}
 
@@ -802,6 +808,8 @@
 	return mindist;
 }
 
+
+
 int
 lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
 {



More information about the postgis-commits mailing list