$$ 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
}
+/*
+** 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);
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);
/* 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);