[postgis-users] points to polyline or polygon

David Blasby dblasby at refractions.net
Wed Jul 16 10:27:10 PDT 2003


> On a similar note can anyone comment or provide direction on writing custom
> functions to help do this kind of thing?  I'd be particularly interested in
> how the proces compares to Oracle's pl/sql.  I guess taking a peek at
> postgis.sql would be a good place for me to start eh?  Although I see a lot
> of your functions are bundled into postgis.dll right?


I think these type of function would be great inside the actual postgis 
distribution (ie. written in "C").  I want to do these functions, but 
I'm too busy right now.  They are, fortunately, very easy to write.

So, if someone wanted to add the functions here's what you will have to 
do (this is for multipoint to linestring):

1. Edit postgis.h, add a line like:
	Datum multipoint2linestring(PG_FUNCTION_ARGS);

2. Add the function to postgis_fn.c.

I just wrote this for this message - I have no idea if it even compiles, 
let alone works.  But, it shows you the underlying idea of the 
conversion function.
See postgis_inout.c:: make_point(), make_linestring(), make_polygon().
Also look at the functions in postgis_fn.c that do something like what 
you want to do.  For example, if you want to create a polygon, look at 
envelope() since it also returns a polygon.
	
// multipoint2linestring(<multipoint>)
//  returns a geometry (type linestring) that has its points in the
//  same order as the multipoint
PG_FUNCTION_INFO_V1(multipoint2linestring);
Datum multipoint2linestring(PG_FUNCTION_ARGS)
{
	GEOMETRY *geom_in = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	int32			*offsets1;
	POINT3D			*allPts;
	LINE3D			*line;
	int                     t;
	POINT3D			*pt;
	int			size; //of the line object
	GEOMETRY		*result;

		// error check
	if (geom->type != MULTIPOINTTYPE )
	{
		elog(ERROR,"multipoint2linestring(<multipoint>) - you didnt give me a 
multipoint\n");
		PG_RETURN_NULL();
	}
	if (geom->nobjs < 2)
	{
		elog(ERROR,"multipoint2linestring(<multipoint>) - multipoint must have 
at least 2 points in it\n");
		PG_RETURN_NULL();
	}

		// de-serialization step
	offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * 
geom->nobjs ) ;

		// make an array of the points in the multipoint object
	allPts = palloc( sizeof(POINT3D) * geom->nobjs); 	
	for(t =0; t<geom->nobjs; t++)
	{
			// get point t from the multipoint
		pt = (POINT3D*)((char *) geom +offsets1[t]) ;
			// stick it in the allPts array
		allPts[t] = *pt; // have the compiler do the copy
	}
		// construct a line from the array of points
	line = make_line( geom->nobjs, allPts, &size);
	pfree(allPts);  // free up space

		// create a geometry object from the line
	result = make_oneobj_geometry(size, (char*) line, LINESTRINGTYPE, 
geom->is3d,geom->SRID, geom->scale, geom->offx, geom->offy);

	return result;
}


3. add the function to the postgis_sql_common.sql.in file:
CREATE FUNCTION linestringfrommultipoint(geometry)
	RETURNS geometry
	AS '@MODULE_FILENAME@','multipoint2linestring'
	LANGUAGE 'C' WITH (isstrict);


4. build postgis (ie. 'make');

5. once you get it to compile, and think its going to work you can 
either make a new database (and use the new postgis.sql that has your 
function in it), or you can just add the function to an already existing 
database (look in postgis.sql for your new function - then copy and past).

6. test it -

	select linestringFromMultipoint('MULTPOINT(0 0, 1 1)');
	select linestringFromMultipoint('MULTPOINT(0 0)');  -- error
	select linestringFromMultipoint('POINT(0 0)');  -- error





More information about the postgis-users mailing list