[postgis-users] X() function working for POINTs and MULTIPOINTs

Paul Ramsey pramsey at refractions.net
Mon Mar 20 12:54:09 PST 2006


Fluff the geometries with multi() in your query:

select x(geometryn(multi(geom),1)) from geotable

P.

On Mar 20, 2006, at 8:13 AM, Bernhard Reimar Hoefle wrote:

> Hi!
> I wanted to mix POINT and MULTIPOINTs in one geometry column. I  
> know that it is
> not the most elegant way but for my purpose the best solution  
> concerning
> performance and disk storage.
>
> I wanted to get the coordinates (x,y,z) for each row.
>
> The PostGIS x() function does not support MULTIPOINTs and the  
> geometryN() does
> not support POINTs.
>
> select x('MULTIPOINT(1 1 1,2 2 2)'::GEOMETRY);
> ERROR:  Argument to X() must be a point
> ERROR:  Argument to X() must be a point
>
> select x(geometryn('POINT(2 2 2)'::GEOMETRY,1));
>  x
> ---
>
> (1 row)
>
> Hence, a simple SQL statement to extract coordinates from mixed  
> types is not
> possible.
>
> Therefore I modified the X() function to X(geometry,int) which  
> works for both
> types.
>
> Maybe it's interesting for someone working with the same 'dirty'  
> solution.
>
> Added lines in lwgeom_ogc.c:
> ##############################
>
> Datum LWGEOM_xx_point(PG_FUNCTION_ARGS);
>
> PG_FUNCTION_INFO_V1(LWGEOM_xx_point);
> Datum LWGEOM_xx_point(PG_FUNCTION_ARGS)
> {
> 	PG_LWGEOM *geom;
> 	LWPOINT *point = NULL;
> 	POINT2D p;
> 	int idx = PG_GETARG_INT32(1);
> 	LWCOLLECTION *coll;
> 	LWGEOM *subgeom;
>
> 	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
>
> 	if ( TYPE_GETTYPE(geom->type) == POINTTYPE )
> 	{
> 		point = lwgeom_getpoint(SERIALIZED_FORM(geom), 0);
> 		getPoint2d_p(point->point, 0, &p);
> 		PG_FREE_IF_COPY(geom, 0);
> 		PG_RETURN_FLOAT8(p.x);
> 	}
> 	else if ( TYPE_GETTYPE(geom->type) == MULTIPOINTTYPE )
> 	{
> 		idx -= 1; /* index is 1-based */
> 		coll = (LWCOLLECTION *)lwgeom_deserialize(SERIALIZED_FORM(geom));
>
> 		if ( idx < 0 ) PG_RETURN_NULL();
> 		if ( idx >= coll->ngeoms ) PG_RETURN_NULL();
>
> 		subgeom = coll->geoms[idx];
>
> 		/* Construct an LWPOINT */
> 		point = lwgeom_as_lwpoint(subgeom);
> 		getPoint2d_p(point->point, 0, &p);
> 		lwgeom_release((LWGEOM *)coll);
> 		PG_FREE_IF_COPY(geom, 0);
> 		PG_RETURN_FLOAT8(p.x);
> 	}
> 	else
> 		lwerror("First argument to x(geometry,integer) must be a point or  
> multipoint
> object");
> }
>
> Added lines in lwpostgis.sql:
> #############################
>
> CREATE OR REPLACE FUNCTION X(geometry, integer)
> 	RETURNS float8
> 	AS '$libdir/liblwgeom.so.1.1','LWGEOM_xx_point'
> 	LANGUAGE 'C' IMMUTABLE STRICT; -- WITH (isstrict);
>
>
> The same procedure can be done for Y(), Z().
> It was my first attempt in programming with C. I hope the C code is  
> ok?
>
> Better solutions and suggestions are welcome.
>
> Bernhard
>
> _______________________________________________
> postgis-users mailing list
> postgis-users at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-users




More information about the postgis-users mailing list