mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-25 01:22:47 +00:00
1449cae461
git-svn-id: http://svn.osgeo.org/postgis/trunk@951 b70326c6-7e19-0410-871a-916f4a2858ee
345 lines
7.3 KiB
C
345 lines
7.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include "wktparse.h"
|
|
|
|
//#include "lwgeom_pg.h"
|
|
#include "liblwgeom.h"
|
|
|
|
//#define DEBUG_CALLS 1
|
|
|
|
LWGEOM *
|
|
lwgeom_deserialize(char *srl)
|
|
{
|
|
int type = lwgeom_getType(srl[0]);
|
|
|
|
switch (type)
|
|
{
|
|
case POINTTYPE:
|
|
return (LWGEOM *)lwpoint_deserialize(srl);
|
|
case LINETYPE:
|
|
return (LWGEOM *)lwline_deserialize(srl);
|
|
case POLYGONTYPE:
|
|
return (LWGEOM *)lwpoly_deserialize(srl);
|
|
case MULTIPOINTTYPE:
|
|
return (LWGEOM *)lwmpoint_deserialize(srl);
|
|
case MULTILINETYPE:
|
|
return (LWGEOM *)lwmline_deserialize(srl);
|
|
case MULTIPOLYGONTYPE:
|
|
return (LWGEOM *)lwmpoly_deserialize(srl);
|
|
case COLLECTIONTYPE:
|
|
return (LWGEOM *)lwcollection_deserialize(srl);
|
|
default:
|
|
lwerror("Unknown geometry type: %d", type);
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
size_t
|
|
lwgeom_serialize_size(LWGEOM *lwgeom)
|
|
{
|
|
int type = TYPE_GETTYPE(lwgeom->type);
|
|
|
|
#ifdef DEBUG_CALLS
|
|
lwnotice("lwgeom_serialize_size called");
|
|
#endif
|
|
|
|
switch (type)
|
|
{
|
|
case POINTTYPE:
|
|
return lwpoint_serialize_size((LWPOINT *)lwgeom);
|
|
case LINETYPE:
|
|
return lwline_serialize_size((LWLINE *)lwgeom);
|
|
case POLYGONTYPE:
|
|
return lwpoly_serialize_size((LWPOLY *)lwgeom);
|
|
case MULTIPOINTTYPE:
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
|
|
default:
|
|
lwerror("Unknown geometry type: %d", type);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
lwgeom_serialize_buf(LWGEOM *lwgeom, char *buf, size_t *retsize)
|
|
{
|
|
int type = TYPE_GETTYPE(lwgeom->type);
|
|
|
|
#ifdef DEBUG_CALLS
|
|
lwnotice("lwgeom_serialize_buf called with a %s",
|
|
lwgeom_typename(type));
|
|
#endif
|
|
switch (type)
|
|
{
|
|
case POINTTYPE:
|
|
lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
|
|
break;
|
|
case LINETYPE:
|
|
lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
|
|
break;
|
|
case POLYGONTYPE:
|
|
lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
|
|
break;
|
|
case MULTIPOINTTYPE:
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
|
|
retsize);
|
|
break;
|
|
default:
|
|
lwerror("Unknown geometry type: %d", type);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
char *
|
|
lwgeom_serialize(LWGEOM *lwgeom)
|
|
{
|
|
size_t size = lwgeom_serialize_size(lwgeom);
|
|
size_t retsize;
|
|
char *serialized = lwalloc(size);
|
|
|
|
lwgeom_serialize_buf(lwgeom, serialized, &retsize);
|
|
|
|
#ifdef DEBUG
|
|
if ( retsize != size )
|
|
{
|
|
lwerror("lwgeom_serialize: computed size %d, returned size %d",
|
|
size, retsize);
|
|
}
|
|
#endif
|
|
|
|
return serialized;
|
|
}
|
|
|
|
// Force Right-hand-rule on LWGEOM polygons
|
|
void
|
|
lwgeom_forceRHR(LWGEOM *lwgeom)
|
|
{
|
|
LWCOLLECTION *coll;
|
|
int i;
|
|
|
|
switch (TYPE_GETTYPE(lwgeom->type))
|
|
{
|
|
case POLYGONTYPE:
|
|
lwpoly_reverse((LWPOLY *)lwgeom);
|
|
return;
|
|
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
coll = (LWCOLLECTION *)lwgeom;
|
|
for (i=0; i<coll->ngeoms; i++)
|
|
lwgeom_forceRHR(coll->geoms[i]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Reverse vertex order of LWGEOM
|
|
void
|
|
lwgeom_reverse(LWGEOM *lwgeom)
|
|
{
|
|
int i;
|
|
LWCOLLECTION *col;
|
|
|
|
switch (TYPE_GETTYPE(lwgeom->type))
|
|
{
|
|
case LINETYPE:
|
|
lwline_reverse((LWLINE *)lwgeom);
|
|
return;
|
|
case POLYGONTYPE:
|
|
lwpoly_reverse((LWPOLY *)lwgeom);
|
|
return;
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
col = (LWCOLLECTION *)lwgeom;
|
|
for (i=0; i<col->ngeoms; i++)
|
|
lwgeom_reverse(col->geoms[i]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
int
|
|
lwgeom_compute_bbox_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
|
|
{
|
|
switch(TYPE_GETTYPE(lwgeom->type))
|
|
{
|
|
case POINTTYPE:
|
|
return lwpoint_compute_bbox_p((LWPOINT *)lwgeom, buf);
|
|
case LINETYPE:
|
|
return lwline_compute_bbox_p((LWLINE *)lwgeom, buf);
|
|
case POLYGONTYPE:
|
|
return lwpoly_compute_bbox_p((LWPOLY *)lwgeom, buf);
|
|
case MULTIPOINTTYPE:
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
return lwcollection_compute_bbox_p((LWCOLLECTION *)lwgeom, buf);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//dont forget to lwfree() result
|
|
|
|
BOX2DFLOAT4 *
|
|
lwgeom_compute_bbox(LWGEOM *lwgeom)
|
|
{
|
|
BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
|
|
if ( lwgeom_compute_bbox_p(lwgeom, result) ) return result;
|
|
else return NULL;
|
|
}
|
|
|
|
LWPOINT *
|
|
lwgeom_as_lwpoint(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == POINTTYPE ) return (LWPOINT *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWLINE *
|
|
lwgeom_as_lwline(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == LINETYPE ) return (LWLINE *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWPOLY *
|
|
lwgeom_as_lwpoly(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == POLYGONTYPE ) return (LWPOLY *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWCOLLECTION *
|
|
lwgeom_as_lwcollection(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type >= MULTIPOINTTYPE ) return (LWCOLLECTION *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWMPOINT *
|
|
lwgeom_as_lwmpoint(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == MULTIPOINTTYPE ) return (LWMPOINT *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWMLINE *
|
|
lwgeom_as_lwmline(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == MULTILINETYPE ) return (LWMLINE *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWMPOLY *
|
|
lwgeom_as_lwmpoly(LWGEOM *lwgeom)
|
|
{
|
|
if ( lwgeom->type == MULTIPOLYGONTYPE ) return (LWMPOLY *)lwgeom;
|
|
else return NULL;
|
|
}
|
|
|
|
LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwmline_as_lwgeom(LWMLINE *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
|
|
LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
|
|
|
|
void
|
|
lwgeom_release(LWGEOM *lwgeom)
|
|
{
|
|
uint32 i;
|
|
LWCOLLECTION *col;
|
|
|
|
// Collection
|
|
if ( (col=lwgeom_as_lwcollection(lwgeom)) )
|
|
{
|
|
for (i=0; i<col->ngeoms; i++)
|
|
{
|
|
lwgeom_release(col->geoms[i]);
|
|
}
|
|
lwfree(lwgeom);
|
|
}
|
|
|
|
// Single element
|
|
else lwfree(lwgeom);
|
|
|
|
}
|
|
|
|
// Clone an LWGEOM object. POINTARRAY are not copied.
|
|
LWGEOM *
|
|
lwgeom_clone(const LWGEOM *lwgeom)
|
|
{
|
|
switch(TYPE_GETTYPE(lwgeom->type))
|
|
{
|
|
case POINTTYPE:
|
|
return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
|
|
case LINETYPE:
|
|
return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
|
|
case POLYGONTYPE:
|
|
return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
|
|
case MULTIPOINTTYPE:
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
case COLLECTIONTYPE:
|
|
return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Add 'what' to 'to' at position 'where'.
|
|
// where=0 == prepend
|
|
// where=-1 == append
|
|
// Appended-to LWGEOM gets a new type based on new condition.
|
|
// Mix of dimensions is not allowed (TODO: allow it?).
|
|
LWGEOM *
|
|
lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
|
|
{
|
|
if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
|
|
{
|
|
lwerror("lwgeom_add: mixed dimensions not supported");
|
|
return NULL;
|
|
}
|
|
|
|
switch(TYPE_GETTYPE(to->type))
|
|
{
|
|
case POINTTYPE:
|
|
return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
|
|
case LINETYPE:
|
|
return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
|
|
case POLYGONTYPE:
|
|
return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
|
|
|
|
case MULTIPOINTTYPE:
|
|
case MULTILINETYPE:
|
|
case MULTIPOLYGONTYPE:
|
|
return (LWGEOM *)lwcollection_add((const LWCOLLECTION *)to, where, what);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return an alloced string
|
|
*/
|
|
char *
|
|
lwgeom_to_wkt(LWGEOM *lwgeom)
|
|
{
|
|
char *serialized = lwgeom_serialize(lwgeom);
|
|
if ( ! serialized ) {
|
|
lwerror("Error serializing geom %p", lwgeom);
|
|
}
|
|
char *ret = unparse_WKT(serialized, lwalloc, lwfree);
|
|
lwfree(serialized);
|
|
return ret;
|
|
}
|
|
|