]> granicus.if.org Git - postgis/commitdiff
(#2026) fix performance regression in geography distance calculation
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 23 Oct 2012 22:17:12 +0000 (22:17 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 23 Oct 2012 22:17:12 +0000 (22:17 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10531 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
liblwgeom/g_box.c
liblwgeom/liblwgeom.h.in
liblwgeom/liblwgeom_internal.h
liblwgeom/lwgeom.c
postgis/geography_measurement.c

diff --git a/NEWS b/NEWS
index 319edbbe6efe19e0464996b4956b4d4741d9c302..78d34eca98612afe9dc67befa5aff155416563f2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -83,6 +83,7 @@ PostGIS 2.1.0
   - #1957, ST_Distance to a one-point LineString returns NULL 
   - #1976, Geography point-in-ring code overhauled for more reliability
   - #1981, cleanup of unused variables causing warnings with gcc 4.6+
+  - #2026, improve performance of distance calculations 
   - #2057, Fixed linking issue for raster2psql to libpq
 
 PostGIS 2.0.1
index 90763f6469fb743086d50e6a856103fd581cbf00..5fd08b69454b47b2d0f1d1cf4f1452f7aad067f8 100644 (file)
@@ -26,6 +26,12 @@ void gbox_init(GBOX *gbox)
        memset(gbox, 0, sizeof(GBOX));
 }
 
+GBOX* gbox_clone(const GBOX *gbox)
+{
+       GBOX *g = lwalloc(sizeof(GBOX));
+       memcpy(g, gbox, sizeof(GBOX));
+       return g;
+}
 
 /* TODO to be removed */
 BOX3D* box3d_from_gbox(const GBOX *gbox)
index 595364bfffe5133a520ffdf5f93f01029b18f49d..03b4c1dc5b471acc19ef046de4843920415d20e3 100644 (file)
@@ -681,6 +681,10 @@ extern void lwgeom_drop_srid(LWGEOM *lwgeom);
  * NULL if the geometry is empty.
  */
 extern void lwgeom_add_bbox(LWGEOM *lwgeom);
+/**
+* Compute a box for geom and all sub-geometries, if not already computed
+*/
+extern void lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox);
 
 /** 
  * Get a non-empty geometry bounding box, computing and
index 89491bf231b8920d61b00550394fb14e20dd22a9..87b38a90c0e5cf35cbc878a6350f0dabf9501e23 100644 (file)
@@ -330,6 +330,7 @@ GBOX *box2d_clone(const GBOX *lwgeom);
 LWLINE *lwline_clone_deep(const LWLINE *lwgeom);
 LWPOLY *lwpoly_clone_deep(const LWPOLY *lwgeom);
 LWCOLLECTION *lwcollection_clone_deep(const LWCOLLECTION *lwgeom);
+GBOX *gbox_clone(const GBOX *gbox);
 
 /*
 * Startpoint
index e03cb5330a78c72a0a3c4e9ee3f60508428201a3..54dd155f949eeeca3a3aaf4182bff3cdf185fe40 100644 (file)
@@ -565,7 +565,7 @@ void
 lwgeom_add_bbox(LWGEOM *lwgeom)
 {
        /* an empty LWGEOM has no bbox */
-       if( lwgeom_is_empty(lwgeom) ) return;
+       if ( lwgeom_is_empty(lwgeom) ) return;
 
        if ( lwgeom->bbox ) return;
        FLAGS_SET_BBOX(lwgeom->flags, 1);
@@ -573,6 +573,35 @@ lwgeom_add_bbox(LWGEOM *lwgeom)
        lwgeom_calculate_gbox(lwgeom, lwgeom->bbox);
 }
 
+void 
+lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox)
+{
+       if ( lwgeom_is_empty(lwgeom) ) return;
+
+       FLAGS_SET_BBOX(lwgeom->flags, 1);
+       
+       if ( ! ( gbox || lwgeom->bbox ) )
+       {
+               lwgeom->bbox = gbox_new(lwgeom->flags);
+               lwgeom_calculate_gbox(lwgeom, lwgeom->bbox);            
+       }
+       else if ( gbox && ! lwgeom->bbox )
+       {
+               lwgeom->bbox = gbox_clone(gbox);
+       }
+       
+       if ( lwgeom_is_collection(lwgeom) )
+       {
+               int i;
+               LWCOLLECTION *lwcol = (LWCOLLECTION*)lwgeom;
+
+               for ( i = 0; i < lwcol->ngeoms; i++ )
+               {
+                       lwgeom_add_bbox_deep(lwcol->geoms[i], lwgeom->bbox);
+               }
+       }
+}
+
 const GBOX *
 lwgeom_get_bbox(const LWGEOM *lwg)
 {
index f3ec0c106aebe36866cadbaaf0585807a5bd1ccf..c4ee647e80c1cdf9a347e0dabc45a7542ac805ee 100644 (file)
@@ -87,6 +87,10 @@ Datum geography_distance_uncached(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();
        }
 
+       /* Make sure we have boxes attached */
+       lwgeom_add_bbox_deep(lwgeom1, NULL);
+       lwgeom_add_bbox_deep(lwgeom2, NULL);
+       
        distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, &s, FP_TOLERANCE);
 
        /* Clean up */