From afbe4962918ad4a146e2b8d1053f6449c8f39789 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 25 Aug 2004 07:29:32 +0000 Subject: [PATCH] Moved some OGC functions from lwgeom_inout.c to lwgeom_ogc.c. Added area2d (area) to lwgeom_functions_basic.c git-svn-id: http://svn.osgeo.org/postgis/trunk@744 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/MISSING_OBJECTS | 2 - lwgeom/lwgeom_functions_basic.c | 64 +++++++++++++++++++++++++++ lwgeom/lwgeom_inout.c | 76 +-------------------------------- lwgeom/lwgeom_ogc.c | 57 ++++++++++++++++++++++++- lwgeom/lwpostgis.sql.in | 62 ++++++++++++++++++--------- 5 files changed, 162 insertions(+), 99 deletions(-) diff --git a/lwgeom/MISSING_OBJECTS b/lwgeom/MISSING_OBJECTS index 5c89b2e54..4fdbfc657 100644 --- a/lwgeom/MISSING_OBJECTS +++ b/lwgeom/MISSING_OBJECTS @@ -69,8 +69,6 @@ FUNC: KEEPING FUNCTION: [combine_bbox(box3d, geometry)] FUNC: KEEPING FUNCTION: [length3d(geometry)] FUNC: KEEPING FUNCTION: [length(geometry)] -FUNC: KEEPING FUNCTION: [area2d(geometry)] -FUNC: KEEPING FUNCTION: [area(geometry)] FUNC: KEEPING FUNCTION: [perimeter3d(geometry)] FUNC: KEEPING FUNCTION: [perimeter(geometry)] diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 6f94e3bfc..98ecf3bc4 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -28,6 +28,7 @@ Datum combine_box2d(PG_FUNCTION_ARGS); Datum LWGEOM_mem_size(PG_FUNCTION_ARGS); Datum LWGEOM_summary(PG_FUNCTION_ARGS); Datum LWGEOM_npoints(PG_FUNCTION_ARGS); +Datum LWGEOM_area2d(PG_FUNCTION_ARGS); Datum postgis_uses_stats(PG_FUNCTION_ARGS); Datum postgis_scripts_released(PG_FUNCTION_ARGS); Datum postgis_lib_version(PG_FUNCTION_ARGS); @@ -36,6 +37,7 @@ Datum postgis_lib_version(PG_FUNCTION_ARGS); // internal char * lwgeom_summary_recursive(char *serialized, int offset); int32 lwgeom_npoints_recursive(char *serialized); +double lwgeom_polygon_area2d(LWPOLY *poly); /*------------------------------------------------------------------*/ @@ -312,3 +314,65 @@ Datum LWGEOM_npoints(PG_FUNCTION_ARGS) PG_RETURN_INT32(npoints); } +//find the 2d area of the outer ring - sum (area 2d of inner rings) +// Could use a more numerically stable calculator... +double lwgeom_polygon_area2d(LWPOLY *poly) +{ + double poly_area=0.0; + int i; + +//elog(NOTICE,"in lwgeom_polygon_area2d (%d rings)", poly->nrings); + + for (i=0; inrings; i++) + { + int j; + POINTARRAY *ring = poly->rings[i]; + double ringarea = 0.0; + +//elog(NOTICE," rings %d has %d points", i, ring->npoints); + for (j=0; jnpoints-1; j++) + { + POINT2D *p1 = (POINT2D *)getPoint(ring, j); + POINT2D *p2 = (POINT2D *)getPoint(ring, j+1); + ringarea += ( p1->x * p2->y ) - ( p1->y * p2->x ); + } + + ringarea /= 2.0; +//elog(NOTICE," ring 1 has area %lf",ringarea); + ringarea = fabs(ringarea ); + if (i != 0) //outer + ringarea = -1.0*ringarea ; // its a hole + + poly_area += ringarea; + } + + return poly_area; +} + +// Calculate the area of all the subobj in a polygon +// area(point) = 0 +// area (line) = 0 +// area(polygon) = find its 2d area +PG_FUNCTION_INFO_V1(LWGEOM_area2d); +Datum LWGEOM_area2d(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM_INSPECTED *inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); + LWPOLY *poly; + double area = 0.0; + int i; + +//elog(NOTICE, "in LWGEOM_area2d"); + + for (i=0; ingeometries; i++) + { + poly = lwgeom_getpoly_inspected(inspected, i); + if ( poly == NULL ) continue; + area += lwgeom_polygon_area2d(poly); +//elog(NOTICE, " LWGEOM_area2d found a poly (%f)", area); + } + + pfree_inspected(inspected); + + PG_RETURN_FLOAT8(area); +} diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 8054414f9..45ee1c9b4 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -20,6 +20,7 @@ #define DEBUG +#include "lwgeom_pg.h" #include "wktparse.h" void elog_ERROR(const char* string); @@ -27,14 +28,8 @@ void elog_ERROR(const char* string); extern unsigned char parse_hex(char *str); extern void deparse_hex(unsigned char str, unsigned char *result); - - extern char *parse_lwgeom_wkt(char *wkt_input); -static void *palloc_fn(size_t size); -static void free_fn(void *ptr); - - // 3d or 4d. There is NOT a (x,y,m) point type!!! #define WKB3DOFFSET 0x80000000 @@ -47,9 +42,6 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS); Datum LWGEOM_out(PG_FUNCTION_ARGS); // needed for OGC conformance -Datum LWGEOM_from_text(PG_FUNCTION_ARGS); - -Datum LWGEOM_asText(PG_FUNCTION_ARGS); Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS); Datum LWGEOM_getBBOX(PG_FUNCTION_ARGS); @@ -242,29 +234,6 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } -//given wkt and SRID, return a geometry -//actually we cheat, postgres will convert the string to a geometry for us... -PG_FUNCTION_INFO_V1(LWGEOM_from_text); -Datum LWGEOM_from_text(PG_FUNCTION_ARGS) -{ - LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); - int32 SRID; - LWGEOM *result = NULL; - - // read user-requested SRID if any - if ( PG_NARGS() > 1 ) - { - SRID = PG_GETARG_INT32(1); - if ( SRID != lwgeom_getSRID(geom) ) - { - result = lwgeom_setSRID(geom, SRID); - pfree(geom); - } - } - if ( ! result ) result = geom; - - PG_RETURN_POINTER(result); -} @@ -503,34 +472,6 @@ unsigned char parse_hex(char *str) return (unsigned char) ((result_high<<4) + result_low); } -//convert LWGEOM to wkt (in TEXT format) -PG_FUNCTION_INFO_V1(LWGEOM_asText); -Datum LWGEOM_asText(PG_FUNCTION_ARGS) -{ - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result_cstring = unparse_WKT(lwgeom,palloc_fn,free_fn); - int len; - - char *result,*loc_wkt; - char *semicolonLoc; - - semicolonLoc = strchr(result_cstring,';'); - - //loc points to start of wkt - if (semicolonLoc == NULL) loc_wkt = result_cstring; - else loc_wkt = semicolonLoc +1; - - len = strlen(loc_wkt)+4; - result = palloc(len); - memcpy(result, &len, 4); - - memcpy(result+4,loc_wkt, len-4); - - pfree(result_cstring); - PG_RETURN_POINTER(result); -} - - // puts a bbox inside the geometry PG_FUNCTION_INFO_V1(LWGEOM_addBBOX); Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS) @@ -584,21 +525,6 @@ void elog_ERROR(const char* string) elog(ERROR,string); } -static void free_fn(void *ptr) -{ - //elog(NOTICE," pfree(%p)", ptr); - pfree(ptr); -} - -static void *palloc_fn(size_t size) -{ - void * result; - result = palloc(size); - //elog(NOTICE," palloc(%d) = %p", size, result); - return result; -} - - // parse WKT input // parse_WKT_lwgeom(TEXT) -> LWGEOM PG_FUNCTION_INFO_V1(parse_WKT_lwgeom); diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index f8f0747b0..ef20633ad 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -15,6 +15,7 @@ #include "lwgeom.h" +#include "lwgeom_pg.h" //#define DEBUG @@ -53,7 +54,10 @@ Datum LWGEOM_z_point(PG_FUNCTION_ARGS); Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS); // ---- EndPoint(geometry) Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS); - +// ---- AsText(geometry) +Datum LWGEOM_asText(PG_FUNCTION_ARGS); +// ---- GeometryFromText(text, integer) +Datum LWGEOM_from_text(PG_FUNCTION_ARGS); // internal int32 lwgeom_numpoints_linestring_recursive(char *serialized); @@ -671,3 +675,54 @@ Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } + +//given wkt and SRID, return a geometry +//actually we cheat, postgres will convert the string to a geometry for us... +PG_FUNCTION_INFO_V1(LWGEOM_from_text); +Datum LWGEOM_from_text(PG_FUNCTION_ARGS) +{ + LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); + int32 SRID; + LWGEOM *result = NULL; + + // read user-requested SRID if any + if ( PG_NARGS() > 1 ) + { + SRID = PG_GETARG_INT32(1); + if ( SRID != lwgeom_getSRID(geom) ) + { + result = lwgeom_setSRID(geom, SRID); + pfree(geom); + } + } + if ( ! result ) result = geom; + + PG_RETURN_POINTER(result); +} +//convert LWGEOM to wkt (in TEXT format) +PG_FUNCTION_INFO_V1(LWGEOM_asText); +Datum LWGEOM_asText(PG_FUNCTION_ARGS) +{ + char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + char *result_cstring = unparse_WKT(lwgeom,palloc_fn,free_fn); + int len; + + char *result,*loc_wkt; + char *semicolonLoc; + + semicolonLoc = strchr(result_cstring,';'); + + //loc points to start of wkt + if (semicolonLoc == NULL) loc_wkt = result_cstring; + else loc_wkt = semicolonLoc +1; + + len = strlen(loc_wkt)+4; + result = palloc(len); + memcpy(result, &len, 4); + + memcpy(result+4,loc_wkt, len-4); + + pfree(result_cstring); + PG_RETURN_POINTER(result); +} + diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index fbe72937c..b963ae52c 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -11,6 +11,10 @@ -- -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- $Log$ +-- Revision 1.16 2004/08/25 07:29:32 strk +-- Moved some OGC functions from lwgeom_inout.c to lwgeom_ogc.c. +-- Added area2d (area) to lwgeom_functions_basic.c +-- -- Revision 1.15 2004/08/24 16:33:41 strk -- Added StartPoint(), EndPoint() -- @@ -133,11 +137,6 @@ CREATEFUNCTION geometryfromtext(geometry) AS '@MODULE_FILENAME@','LWGEOM_from_text' LANGUAGE 'C' WITH (isstrict,iscachable); -CREATEFUNCTION geometryfromtext(geometry, int4) - RETURNS geometry - AS '@MODULE_FILENAME@','LWGEOM_from_text' - LANGUAGE 'C' WITH (isstrict,iscachable); - CREATEFUNCTION geomfromtext(geometry) RETURNS geometry AS ' SELECT geometryfromtext($1) @@ -819,28 +818,14 @@ CREATEFUNCTION getSRID(geometry) AS '@MODULE_FILENAME@','LWGEOM_getSRID' LANGUAGE 'C' WITH (isstrict,iscachable); --- defined for backward compatibility -CREATEFUNCTION SRID(geometry) - RETURNS int4 - AS '@MODULE_FILENAME@','LWGEOM_getSRID' - LANGUAGE 'C' WITH (isstrict,iscachable); - -CREATEFUNCTION setSRID(geometry,int4) - RETURNS geometry - AS '@MODULE_FILENAME@','LWGEOM_setSRID' - LANGUAGE 'C' WITH (isstrict,iscachable); - -CREATEFUNCTION asText(geometry) - RETURNS TEXT - AS '@MODULE_FILENAME@','LWGEOM_asText' - LANGUAGE 'C' WITH (isstrict,iscachable); - CREATEFUNCTION getbbox(geometry) RETURNS box2d AS '@MODULE_FILENAME@','LWGEOM_to_BOX2DFLOAT4' LANGUAGE 'C' WITH (isstrict,iscachable); +------------------------------------------------------------------------ -- DEBUG +------------------------------------------------------------------------ CREATEFUNCTION mem_size(geometry) RETURNS int4 @@ -858,6 +843,8 @@ CREATEFUNCTION npoints(geometry) LANGUAGE 'C' WITH (isstrict); ------------------------------------------------------------------------ +-- OGC defined +------------------------------------------------------------------------ CREATEFUNCTION NumPoints(geometry) RETURNS int4 @@ -929,6 +916,39 @@ CREATEFUNCTION EndPoint(geometry) AS '@MODULE_FILENAME@', 'LWGEOM_endpoint_linestring' LANGUAGE 'C' WITH (isstrict); +CREATEFUNCTION SRID(geometry) + RETURNS int4 + AS '@MODULE_FILENAME@','LWGEOM_getSRID' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION SetSRID(geometry,int4) + RETURNS geometry + AS '@MODULE_FILENAME@','LWGEOM_setSRID' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION AsText(geometry) + RETURNS TEXT + AS '@MODULE_FILENAME@','LWGEOM_asText' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION GeometryFromText(geometry, int4) + RETURNS geometry + AS '@MODULE_FILENAME@','LWGEOM_from_text' + LANGUAGE 'C' WITH (isstrict,iscachable); + +------------------------------------------------------------------------ +-- Misures +------------------------------------------------------------------------ + +CREATEFUNCTION area2d(geometry) + RETURNS FLOAT8 + AS '@MODULE_FILENAME@', 'LWGEOM_area2d' + LANGUAGE 'C' WITH (isstrict); + +CREATEFUNCTION area(geometry) + RETURNS FLOAT8 + AS '@MODULE_FILENAME@','LWGEOM_area2d' + LANGUAGE 'C' WITH (isstrict); ------------------------------------------------------------------------ -- 2.40.0