Skip to content

Commit

Permalink
(#2026) fix performance regression in geography distance calculation
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/postgis/trunk@10531 b70326c6-7e19-0410-871a-916f4a2858ee
  • Loading branch information
pramsey committed Oct 23, 2012
1 parent ac9f562 commit 42ce299
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions liblwgeom/g_box.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions liblwgeom/liblwgeom.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions liblwgeom/liblwgeom_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 30 additions & 1 deletion liblwgeom/lwgeom.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,14 +565,43 @@ 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);
lwgeom->bbox = gbox_new(lwgeom->flags);
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)
{
Expand Down
4 changes: 4 additions & 0 deletions postgis/geography_measurement.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 42ce299

Please sign in to comment.