]> granicus.if.org Git - postgis/commitdiff
Define alias ST_Perimeter (for geography ST_Length) (#526)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 17 Jun 2011 21:11:05 +0000 (21:11 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 17 Jun 2011 21:11:05 +0000 (21:11 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@7414 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/geography.sql.in.c
postgis/geography_measurement.c

index b860a5c4bd7420ba457c2a1e5197830ed309eae4..2b1431c6577001c752cb33dbf51689c2df4732a8 100644 (file)
@@ -658,6 +658,21 @@ CREATE OR REPLACE FUNCTION ST_Length(text)
        $$ SELECT ST_Length($1::geometry);  $$
        LANGUAGE 'SQL' IMMUTABLE STRICT;
 
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_Perimeter(geography, boolean)
+       RETURNS float8
+       AS 'MODULE_PATHNAME','geography_perimeter'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_Perimeter(geography)
+       RETURNS float8
+       AS 'SELECT ST_Perimeter($1, true)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+
 -- Availability: 1.5.0
 CREATE OR REPLACE FUNCTION _ST_PointOutside(geography)
        RETURNS geography
index 30b5bd86c730fdf04b0aceaa92747cb03596cef5..9ea6d2bae371a529a91463f52ba52ea93cc029ca 100644 (file)
@@ -268,9 +268,68 @@ Datum geography_area(PG_FUNCTION_ARGS)
 
 }
 
+/*
+** geography_perimeter(GSERIALIZED *g)
+** returns double perimeter in meters for area features
+*/
+PG_FUNCTION_INFO_V1(geography_perimeter);
+Datum geography_perimeter(PG_FUNCTION_ARGS)
+{
+       LWGEOM *lwgeom = NULL;
+       GSERIALIZED *g = NULL;
+       double length;
+       bool use_spheroid = LW_TRUE;
+       SPHEROID s;
+    int type;
+
+       /* Get our geometry object loaded into memory. */
+       g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       
+       /* Only return for area features. */
+    type = gserialized_get_type(g);
+    if ( ! (type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE) )
+    {
+               PG_RETURN_FLOAT8(0.0);
+    }
+       
+       lwgeom = lwgeom_from_gserialized(g);
+
+       /* EMPTY things have no perimeter */
+       if ( lwgeom_is_empty(lwgeom) )
+       {
+               lwgeom_free(lwgeom);
+               PG_RETURN_FLOAT8(0.0);
+       }
+
+       /* Read our calculation type */
+       use_spheroid = PG_GETARG_BOOL(1);
+
+       /* Initialize spheroid */
+       spheroid_init(&s, WGS84_MAJOR_AXIS, WGS84_MINOR_AXIS);
+
+       /* User requests spherical calculation, turn our spheroid into a sphere */
+       if ( ! use_spheroid )
+               s.a = s.b = s.radius;
+
+       /* Calculate the length */
+       length = lwgeom_length_spheroid(lwgeom, &s);
+
+       /* Something went wrong... */
+       if ( length < 0.0 )
+       {
+               elog(ERROR, "lwgeom_length_spheroid returned length < 0.0");
+               PG_RETURN_NULL();
+       }
+
+       /* Clean up, but not all the way to the point arrays */
+       lwgeom_free(lwgeom);
+
+       PG_FREE_IF_COPY(g, 0);
+       PG_RETURN_FLOAT8(length);
+}
 
 /*
-** geography_length_sphere(GSERIALIZED *g)
+** geography_length(GSERIALIZED *g)
 ** returns double length in meters
 */
 PG_FUNCTION_INFO_V1(geography_length);
@@ -287,7 +346,7 @@ Datum geography_length(PG_FUNCTION_ARGS)
        lwgeom = lwgeom_from_gserialized(g);
 
        /* EMPTY things have no length */
-       if ( lwgeom_is_empty(lwgeom) )
+       if ( lwgeom_is_empty(lwgeom) || lwgeom->type == POLYGONTYPE || lwgeom->type == MULTIPOLYGONTYPE )
        {
                lwgeom_free(lwgeom);
                PG_RETURN_FLOAT8(0.0);
@@ -309,12 +368,12 @@ Datum geography_length(PG_FUNCTION_ARGS)
        /* Something went wrong... */
        if ( length < 0.0 )
        {
-               elog(ERROR, "geography_length_sphere returned length < 0.0");
+               elog(ERROR, "lwgeom_length_spheroid returned length < 0.0");
                PG_RETURN_NULL();
        }
 
-       /* Clean up, but not all the way to the point arrays */
-       lwgeom_release(lwgeom);
+       /* Clean up */
+       lwgeom_free(lwgeom);
 
        PG_FREE_IF_COPY(g, 0);
        PG_RETURN_FLOAT8(length);