From: Sandro Santilli Date: Tue, 21 Dec 2004 17:46:44 +0000 (+0000) Subject: Made asText and asBinary strict OGC conformant, introduced asEWKT and asEWKB X-Git-Tag: pgis_1_0_0RC1~129 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5f59c5f1ec46dfd91526dfd13f72bceb2d780776;p=postgis Made asText and asBinary strict OGC conformant, introduced asEWKT and asEWKB for extended version outputs. git-svn-id: http://svn.osgeo.org/postgis/trunk@1175 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/postgis.xml b/doc/postgis.xml index b7b596925..7b6cf03e9 100644 --- a/doc/postgis.xml +++ b/doc/postgis.xml @@ -696,42 +696,67 @@ AND GIS Objects - The GIS objects supported by PostGIS are the "Simple Features" - defined by the OpenGIS Consortium (OGC). As of version 0.9, PostGIS - supports all the objects and functions specified in the OGC "Simple + The GIS objects supported by PostGIS are a superset of + the "Simple Features" defined by the OpenGIS Consortium (OGC). + As of version 0.9, PostGIS supports all the objects and functions + specified in the OGC "Simple Features for SQL" specification. - Examples of the text representations of the spatial objects of the - features are as follows: + Examples of the text representations (WKT) of the spatial + objects of the features are as follows: - POINT(0 0) -- XY + POINT(0 0) - POINT(0 0 0) -- XYZ + LINESTRING(0 0,1 1,1 2) - POINTM(0 0 0) -- XYM + POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)) - POINT(0 0 0 0) -- XYZM + MULTIPOINT(0 0,1 2) - LINESTRING(0 0,1 1,1 2) + MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4)) - POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 - 0,1 1 0)) + MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), + ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))) - MULTIPOINT(0 0 0,1 2 1) + GEOMETRYCOLLECTION(POINT(2 3),LINESTRING((2 3,3 4))) + + + + + PostGIS extends the standard with support for 3DZ,3DM and 4D + coordinates. Examples of the text representations (EWKT) of the + extended spatial objects of the features are as follows: + + + + + POINT(0 0 0) -- XYZ + + + + POINTM(0 0 0) -- XYM + + + + POINT(0 0 0 0) -- XYZM + + + + MULTIPOINTM(0 0 0,1 2 1) @@ -739,28 +764,23 @@ AND 1)) + + POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 + 0,1 1 0)) + + MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0))) - GEOMETRYCOLLECTION(POINT(2 3 9),LINESTRING((2 3 4,3 4 + GEOMETRYCOLLECTIONM(POINT(2 3 9),LINESTRING((2 3 4,3 4 5))) + - Note that in the examples above there are features with - 2-dimensional, 3-dimensional (XYZ,XYM) and 4-dimensional coordinates. - PostGIS supports 2D,3DZ,3DM and 4D coordinates -- if you describe a - feature with 2D coordinates when you insert it, the database will - return that feature to you with 2D coordinates when you extract it. - See the sections on the force_2d(), - force_3dz(), - force_3dm() and - force_4d() functions for information - on converting features to a particular coordinate dimension - representation. Standard versus Canonical Forms @@ -793,23 +813,24 @@ VALUES ( The "canonical form" of the spatial objects in PostgreSQL is a text representation which includes all the information necessary to construct the object. Unlike the OpenGIS standard forms, it includes - the type, coordinate, and SRID information. The - canonical form is the default form returned from a SELECT query. - Since version 1.0.0 the canonical form is an HEX-encoded WKB with - an optional SRID=#; prefix. + the type, dimensions, coordinate, and SRID + information. The canonical form is the default form returned from a + SELECT query. + Since version 1.0.0 the canonical form is an HEX-encoded extended + WKB (EWKB). The example below shows the difference between the OGC standard and PostGIS canonical forms: db=> SELECT AsText(geom) AS OGCGeom FROM SPATIALTABLE; OGCGeom ------------------------------------------------- -POINT(-126.4 45.32) + POINT(-126.4 45.32) (1 row) db=> SELECT geom AS PostGISGeom FROM thetable; PostGISGeom ------------------------------------------------- -SRID=312;01010000009A99999999995FC0295C8FC2F5A84640 + 0101000020380100009A99999999995FC0295C8FC2F5A84640 (1 row) @@ -3934,7 +3955,7 @@ FROM geometry_table; - asbinary(geometry,'NDR') + asBinary(geometry,'NDR') Returns the geometry in the OGC "well-known-binary" format, @@ -3945,7 +3966,7 @@ FROM geometry_table; - asbinary(geometry,'XDR') + asBinary(geometry,'XDR') Returns the geometry in the OGC "well-known-binary" format, diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index cbfc0de46..b8c24d62e 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -28,12 +28,6 @@ Datum LWGEOM_length2d_linestring(PG_FUNCTION_ARGS); Datum LWGEOM_length_linestring(PG_FUNCTION_ARGS); Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS); Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS); -Datum LWGEOM_force_2d(PG_FUNCTION_ARGS); -Datum LWGEOM_force_3dm(PG_FUNCTION_ARGS); -Datum LWGEOM_force_3dz(PG_FUNCTION_ARGS); -Datum LWGEOM_force_4d(PG_FUNCTION_ARGS); -Datum LWGEOM_force_collection(PG_FUNCTION_ARGS); -Datum LWGEOM_force_multi(PG_FUNCTION_ARGS); Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS); Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS); Datum LWGEOM_translate(PG_FUNCTION_ARGS); @@ -2547,3 +2541,36 @@ Datum LWGEOM_addpoint(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } + +//convert LWGEOM to wwkt (in TEXT format) +PG_FUNCTION_INFO_V1(LWGEOM_asEWKT); +Datum LWGEOM_asEWKT(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *lwgeom; + PG_LWGEOM *ogclwgeom; + char *result_cstring; + int len; + char *result,*loc_wkt; + //char *semicolonLoc; + + init_pg_func(); + + lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + result_cstring = unparse_WKT(SERIALIZED_FORM(lwgeom),lwalloc,lwfree); + + //semicolonLoc = strchr(result_cstring,';'); + + ////loc points to start of wkt + //if (semicolonLoc == NULL) loc_wkt = result_cstring; + //else loc_wkt = semicolonLoc +1; + loc_wkt = result_cstring; + + 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/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 0e7699aa7..410c03349 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -31,10 +31,6 @@ void elog_ERROR(const char* string); -// needed for OGC conformance -Datum LWGEOMFromWKB(PG_FUNCTION_ARGS); -Datum WKBFromLWGEOM(PG_FUNCTION_ARGS); - Datum LWGEOM_in(PG_FUNCTION_ARGS); Datum LWGEOM_out(PG_FUNCTION_ARGS); Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS); diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index 92cd4c445..1314eb79d 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -55,6 +55,8 @@ Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS); Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS); // ---- AsText(geometry) Datum LWGEOM_asText(PG_FUNCTION_ARGS); +// ---- AsBinary(geometry, [XDR|NDR]) +Datum LWGEOM_asBinary(PG_FUNCTION_ARGS); // ---- GeometryFromText(text, integer) Datum LWGEOM_from_text(PG_FUNCTION_ARGS); // ---- IsClosed(geometry) @@ -733,22 +735,27 @@ PG_FUNCTION_INFO_V1(LWGEOM_asText); Datum LWGEOM_asText(PG_FUNCTION_ARGS) { PG_LWGEOM *lwgeom; + PG_LWGEOM *ogclwgeom; char *result_cstring; int len; char *result,*loc_wkt; - //char *semicolonLoc; + char *semicolonLoc; init_pg_func(); lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - result_cstring = unparse_WKT(SERIALIZED_FORM(lwgeom),lwalloc,lwfree); - //semicolonLoc = strchr(result_cstring,';'); + /* Force to 2d */ + ogclwgeom = (PG_LWGEOM *)DatumGetPointer(DirectFunctionCall1( + LWGEOM_force_2d, PointerGetDatum(lwgeom))); - ////loc points to start of wkt - //if (semicolonLoc == NULL) loc_wkt = result_cstring; - //else loc_wkt = semicolonLoc +1; - loc_wkt = result_cstring; + result_cstring = unparse_WKT(SERIALIZED_FORM(ogclwgeom),lwalloc,lwfree); + + 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); @@ -760,6 +767,39 @@ Datum LWGEOM_asText(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +//convert LWGEOM to wkb (in BINARY format) +PG_FUNCTION_INFO_V1(LWGEOM_asBinary); +Datum LWGEOM_asBinary(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *ogclwgeom; + char *result; + + init_pg_func(); + + /* Force to 2d */ + ogclwgeom = (PG_LWGEOM *)DatumGetPointer(DirectFunctionCall1( + LWGEOM_force_2d, PG_GETARG_DATUM(0))); + + /* Drop SRID */ + ogclwgeom = (PG_LWGEOM *)DatumGetPointer(DirectFunctionCall2( + LWGEOM_setSRID, PointerGetDatum(ogclwgeom), -1)); + + /* Call WKBFromLWGEOM */ + if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) ) + { + result = (char *)DatumGetPointer(DirectFunctionCall2( + WKBFromLWGEOM, PointerGetDatum(ogclwgeom), + PG_GETARG_DATUM(1))); + } + else + { + result = (char *)DatumGetPointer(DirectFunctionCall1( + WKBFromLWGEOM, PointerGetDatum(ogclwgeom))); + } + + PG_RETURN_POINTER(result); +} + char line_is_closed(LWLINE *line) { POINT4D *sp, *ep; diff --git a/lwgeom/lwgeom_pg.h b/lwgeom/lwgeom_pg.h index 62a94a676..19621960f 100644 --- a/lwgeom/lwgeom_pg.h +++ b/lwgeom/lwgeom_pg.h @@ -43,5 +43,15 @@ Datum LWGEOM_same(PG_FUNCTION_ARGS); Datum BOX3D_construct(PG_FUNCTION_ARGS); Datum BOX2DFLOAT4_ymin(PG_FUNCTION_ARGS); +Datum LWGEOM_force_2d(PG_FUNCTION_ARGS); +Datum LWGEOM_force_3dm(PG_FUNCTION_ARGS); +Datum LWGEOM_force_3dz(PG_FUNCTION_ARGS); +Datum LWGEOM_force_4d(PG_FUNCTION_ARGS); +Datum LWGEOM_force_collection(PG_FUNCTION_ARGS); +Datum LWGEOM_force_multi(PG_FUNCTION_ARGS); + +Datum LWGEOMFromWKB(PG_FUNCTION_ARGS); +Datum WKBFromLWGEOM(PG_FUNCTION_ARGS); + #endif // !defined _LWGEOM_PG_H 1 diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 62c505a28..5f48a1da8 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1119,12 +1119,12 @@ CREATEFUNCTION SetSRID(geometry,int4) CREATEFUNCTION AsBinary(geometry) RETURNS bytea - AS '@MODULE_FILENAME@','WKBFromLWGEOM' + AS '@MODULE_FILENAME@','LWGEOM_asBinary' LANGUAGE 'C' WITH (isstrict,iscachable); CREATEFUNCTION AsBinary(geometry,text) RETURNS bytea - AS '@MODULE_FILENAME@','WKBFromLWGEOM' + AS '@MODULE_FILENAME@','LWGEOM_asBinary' LANGUAGE 'C' WITH (isstrict,iscachable); CREATEFUNCTION AsText(geometry) @@ -1703,6 +1703,21 @@ CREATEFUNCTION ndims(geometry) AS '@MODULE_FILENAME@', 'LWGEOM_ndims' LANGUAGE 'C' WITH (iscachable,isstrict); +CREATEFUNCTION AsEWKT(geometry) + RETURNS TEXT + AS '@MODULE_FILENAME@','LWGEOM_asEWKT' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION AsEWKB(geometry) + RETURNS BYTEA + AS '@MODULE_FILENAME@','WKBFromLWGEOM' + LANGUAGE 'C' WITH (isstrict,iscachable); + +CREATEFUNCTION AsEWKB(geometry,text) + RETURNS bytea + AS '@MODULE_FILENAME@','WKBFromLWGEOM' + LANGUAGE 'C' WITH (isstrict,iscachable); + ------------------------------------------------------------------------ -- CONSTRUCTORS ------------------------------------------------------------------------