[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