From: Sandro Santilli Date: Wed, 29 Sep 2004 10:50:30 +0000 (+0000) Subject: Big layout change. X-Git-Tag: pgis_1_0_0RC1~363 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=904c0d565217a5236d5f0b773b4109eeb0425f0d;p=postgis Big layout change. lwgeom.h is public API liblwgeom.h is private header lwgeom_pg.h is for PG-links lw.c contains type-specific functions git-svn-id: http://svn.osgeo.org/postgis/trunk@909 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/Makefile b/lwgeom/Makefile index 03258716d..729ccefdd 100644 --- a/lwgeom/Makefile +++ b/lwgeom/Makefile @@ -66,7 +66,7 @@ ifeq ($(USE_STATS),1) override CFLAGS += -DUSE_STATS endif -OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o lwgeom_svg.o lwgeom_gml.o $(GEOS_WRAPPER) +OBJS=lwgeom_pg.o lwgeom.o lwpoint.o lwline.o lwpoly.o lwmpoint.o lwmline.o lwmpoly.o lwcollection.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o lwgeom_svg.o lwgeom_gml.o $(GEOS_WRAPPER) OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwpostgis.sql diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h new file mode 100644 index 000000000..fbe3aab1b --- /dev/null +++ b/lwgeom/liblwgeom.h @@ -0,0 +1,849 @@ +#ifndef _LIBLWGEOM_H +#define _LIBLWGEOM_H 1 + +//liblwgeom.h + + +typedef void* (*lwallocator)(size_t size); +typedef void* (*lwreallocator)(void *mem, size_t size); +typedef void (*lwfreeor)(void* mem); +typedef void (*lwreporter)(const char* fmt, ...); + +#ifndef C_H +typedef unsigned int uint32; +typedef int int32; +#endif + +/* prototypes */ +void *default_allocator(size_t size); +void *default_reallocator(void *mem, size_t size); +void default_freeor(void *ptr); +void default_errorreporter(const char *fmt, ...); +void default_noticereporter(const char *fmt, ...); + +/* globals */ +extern lwreallocator lwrealloc; +extern lwallocator lwalloc; +extern lwfreeor lwfree; +extern lwreporter lwerror; +extern lwreporter lwnotice; + +//----------------------------------------------------------------- + +typedef struct +{ + float xmin; + float ymin; + float xmax; + float ymax; +} BOX2DFLOAT4; + +typedef struct +{ + double xmin, ymin, zmin; + double xmax, ymax, zmax; +} BOX3D; + + +typedef struct chiptag +{ + int size; //unused (for use by postgresql) + + int endian_hint; // the number 1 in the endian of this datastruct + + BOX3D bvol; + int SRID; + char future[4]; + float factor; // Usually 1.0. + // Integer values are multiplied by this number + // to get the actual height value + // (for sub-meter accuracy height data). + + int datatype; // 1 = float32, + // 5 = 24bit integer, + // 6 = 16bit integer (short) + // 101 = float32 (NDR), + // 105 = 24bit integer (NDR), + // 106=16bit int (NDR) + + int height; + int width; + int compression; // 0 = no compression, 1 = differencer + // 0x80 = new value + // 0x7F = nodata + + // this is provided for convenience, it should be set to + // sizeof(chip) bytes into the struct because the serialized form is: + //
+ // NULL when serialized + void *data; // data[0] = bottm left, + // data[width] = 1st pixel, 2nd row (uncompressed) + +} CHIP; + +/* + * standard definition of an ellipsoid (what wkt calls a spheroid) + * f = (a-b)/a + * e_sq = (a*a - b*b)/(a*a) + * b = a - fa + */ +typedef struct +{ + double a; //semimajor axis + double b; //semiminor axis + double f; //flattening + double e; //eccentricity (first) + double e_sq; //eccentricity (first), squared + char name[20]; //name of ellipse +} SPHEROID; + + +// POINT3D already defined in postgis.h +// ALL LWGEOM structures will use POINT3D as an abstract point. +// This means a 2d geometry will be stored as (x,y) in its serialized +// form, but all functions will work on (x,y,0). This keeps all the +// analysis functions simple. +// NOTE: for GEOS integration, we'll probably set z=NaN +// so look out - z might be NaN for 2d geometries! +typedef struct { double x,y,z; } POINT3D; + + +// type for 2d points. When you convert this to 3d, the +// z component will be either 0 or NaN. +typedef struct +{ + double x; + double y; +} POINT2D; + +typedef struct +{ + double x; + double y; + double z; + double m; +} POINT4D; + +// Point array abstracts a lot of the complexity of points and point lists. +// It handles miss-alignment in the serialized form, 2d/3d translation +// (2d points converted to 3d will have z=0 or NaN) +// DONT MIX 2D and 3D POINTS! *EVERYTHING* is either one or the other +typedef struct +{ + char *serialized_pointlist; // array of POINT 2D, 3D or 4D. + // probably missaligned. + // points to a double + char ndims; // 2=2d, 3=3d, 4=4d + uint32 npoints; +} POINTARRAY; + +// copies a point from the point array into the parameter point +// will set point's z=0 (or NaN) if pa is 2d +// will set point's m=0 (or NaN( if pa is 3d or 2d +// NOTE: point is a real POINT3D *not* a pointer +extern POINT4D getPoint4d(const POINTARRAY *pa, int n); + +// copies a point from the point array into the parameter point +// will set point's z=0 (or NaN) if pa is 2d +// will set point's m=0 (or NaN) if pa is 3d or 2d +// NOTE: this will modify the point32d pointed to by 'point'. +extern void getPoint4d_p(const POINTARRAY *pa, int n, char *point); + +// copies a point from the point array into the parameter point +// will set point's z=0 (or NaN) if pa is 2d +// NOTE: point is a real POINT3D *not* a pointer +extern POINT3D getPoint3d(const POINTARRAY *pa, int n); + +// copies a point from the point array into the parameter point +// will set point's z=0 (or NaN) if pa is 2d +// NOTE: this will modify the point3d pointed to by 'point'. +extern void getPoint3d_p(const POINTARRAY *pa, int n, char *point); + + +// copies a point from the point array into the parameter point +// z value (if present is not returned) +// NOTE: point is a real POINT3D *not* a pointer +extern POINT2D getPoint2d(const POINTARRAY *pa, int n); + +// copies a point from the point array into the parameter point +// z value (if present is not returned) +// NOTE: this will modify the point2d pointed to by 'point'. +extern void getPoint2d_p(const POINTARRAY *pa, int n, char *point); + +// get a pointer to nth point of a POINTARRAY +// You'll need to cast it to appropriate dimensioned point. +// Note that if you cast to a higher dimensional point you'll +// possibly corrupt the POINTARRAY. +extern char *getPoint(const POINTARRAY *pa, int n); +//--- here is a macro equivalent, for speed... +//#define getPoint(x,n) &( (x)->serialized_pointlist[((x)->ndims*8)*(n)] ) + + +// constructs a POINTARRAY. +// NOTE: points is *not* copied, so be careful about modification (can be aligned/missaligned) +// NOTE: ndims is descriptive - it describes what type of data 'points' +// points to. No data conversion is done. +extern POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints); + +//calculate the bounding box of a set of points +// returns a 3d box +// if pa is 2d, then box3d's zmin/zmax will be either 0 or NaN +// dont call on an empty pa +extern BOX3D *pointArray_bbox(const POINTARRAY *pa); + +//size of point represeneted in the POINTARRAY +// 16 for 2d, 24 for 3d, 32 for 4d +extern int pointArray_ptsize(const POINTARRAY *pa); + + +/* + * + * LWGEOM types are an 8-bit char in this format: + * + * BSDDtttt + * + * WHERE + * B = 16 byte BOX2DFLOAT4 follows (probably not aligned) [before SRID] + * S = 4 byte SRID attached (0= not attached (-1), 1= attached) + * DD = dimentionality (0=2d, 1=3d, 2= 4d) + * tttt = actual type (as per the WKB type): + * + * enum wkbGeometryType { + * wkbPoint = 1, + * wkbLineString = 2, + * wkbPolygon = 3, + * wkbMultiPoint = 4, + * wkbMultiLineString = 5, + * wkbMultiPolygon = 6, + * wkbGeometryCollection = 7 + * }; + * + */ +#define POINTTYPE 1 +#define LINETYPE 2 +#define POLYGONTYPE 3 +#define MULTIPOINTTYPE 4 +#define MULTILINETYPE 5 +#define MULTIPOLYGONTYPE 6 +#define COLLECTIONTYPE 7 + +#define TYPE_SETTYPE(c,t) (((c)&0xF0)|t) +#define TYPE_SETDIMS(c,d) (((c)&0xCF)|d) +#define TYPE_SETHASBBOX(c,b) (((c)&0x7F)|b) +#define TYPE_SETHASSRID(c,s) (((c)&0xBF)|s) + +extern char lwgeom_hasBBOX(unsigned char type); // true iff B bit set +extern int lwgeom_ndims(unsigned char type); // returns the DD value +extern int lwgeom_getType(unsigned char type); // returns the tttt value + +extern unsigned char lwgeom_makeType(int ndims, char hasSRID, int type); +extern unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, char hasBBOX); +extern char lwgeom_hasSRID(unsigned char type); // true iff S bit is set +extern char lwgeom_hasBBOX(unsigned char type); // true iff B bit set + + + +/* + * This is the binary representation of lwgeom compatible + * with postgresql varlena struct + */ +typedef struct { + uint32 size; + unsigned char type; // encodes ndims, type, bbox presence, + // srid presence + char data[1]; +} PG_LWGEOM; + +/* + * Construct a full LWGEOM type (including size header) + * from a serialized form. + * The constructed LWGEOM object will be allocated using palloc + * and the serialized form will be copied. + * If you specify a SRID other then -1 it will be set. + * If you request bbox (wantbbox=1) it will be extracted or computed + * from the serialized form. + */ +extern PG_LWGEOM *PG_LWGEOM_construct(char *serialized, int SRID, int wantbbox); + +/* + * Use this macro to extract the char * required + * by most functions from an PG_LWGEOM struct. + * (which is an PG_LWGEOM w/out int32 size casted to char *) + */ +#define SERIALIZED_FORM(x) ((char *)(x))+4 + + +/* + * This function computes the size in bytes + * of the serialized geometries. + */ +extern uint32 lwgeom_size(const char *serialized_form); +extern uint32 lwgeom_size_subgeom(const char *serialized_form, int geom_number); +extern uint32 lwgeom_size_line(const char *serialized_line); +extern uint32 lwgeom_size_point(const char *serialized_point); +extern uint32 lwgeom_size_poly(const char *serialized_line); + + +//-------------------------------------------------------- +// all the base types (point/line/polygon) will have a +// basic constructor, basic de-serializer, basic serializer, +// bounding box finder and (TODO) serialized form size finder. +//-------------------------------------------------------- + +typedef struct +{ + char ndims; // 2=2d, 3=3d, 4=4d, 5=undef + int SRID; // spatial ref sys + POINTARRAY *point; // hide 2d/3d (this will be an array of 1 point) +} LWPOINT; // "light-weight point" + +// construct a new point. point will NOT be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +extern LWPOINT *lwpoint_construct(int ndims, int SRID, POINTARRAY *point); + +// given the LWPOINT serialized form (or a pointer into a muli* one) +// construct a proper LWPOINT. +// serialized_form should point to the 8bit type format (with type = 1) +// Returns NULL if serialized form is not a point. +// See serialized form doc +extern LWPOINT *lwpoint_deserialize(char *serialized_form); + +// Find size this point would get when serialized (no BBOX) +extern uint32 lwpoint_size(LWPOINT *point); + +// convert this point into its serialize form +// result's first char will be the 8bit type. See serialized form doc +extern char *lwpoint_serialize(LWPOINT *point); + +// same as above, writes to buf +extern void lwpoint_serialize_buf(LWPOINT *point, char *buf, int *size); + +// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) +extern BOX3D *lwpoint_findbbox(LWPOINT *point); + +// convenience functions to hide the POINTARRAY +extern POINT2D lwpoint_getPoint2d(const LWPOINT *point); +extern POINT3D lwpoint_getPoint3d(const LWPOINT *point); + +//-------------------------------------------------------- + +typedef struct +{ + char ndims; // 2=2d, 3=3d, 4=4d, 5=undef + int SRID; // spatial ref sys -1=none + POINTARRAY *points; // array of POINT3D +} LWLINE; //"light-weight line" + +// construct a new LWLINE. points will *NOT* be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +extern LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points); + +// given the LWGEOM serialized form (or a pointer into a muli* one) +// construct a proper LWLINE. +// serialized_form should point to the 8bit type format (with type = 2) +// See serialized form doc +extern LWLINE *lwline_deserialize(char *serialized_form); + +// find the size this line would get when serialized (no BBOX) +extern uint32 lwline_size(LWLINE *line); + +// convert this line into its serialize form +// result's first char will be the 8bit type. See serialized form doc +// copies data. +extern char *lwline_serialize(LWLINE *line); + +// same as above, writes to buf +extern void lwline_serialize_buf(LWLINE *line, char *buf, int *size); + +// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) +extern BOX3D *lwline_findbbox(LWLINE *line); + +//-------------------------------------------------------- + +typedef struct +{ + int32 SRID; + char ndims; + int nrings; + POINTARRAY **rings; // list of rings (list of points) +} LWPOLY; // "light-weight polygon" + +// construct a new LWPOLY. arrays (points/points per ring) will NOT be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +extern LWPOLY *lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points); + +// given the LWPOLY serialized form (or a pointer into a muli* one) +// construct a proper LWPOLY. +// serialized_form should point to the 8bit type format (with type = 3) +// See serialized form doc +extern LWPOLY *lwpoly_deserialize(char *serialized_form); + +// find the size this polygon would get when serialized (no bbox!) +extern uint32 lwpoly_size(LWPOLY *poly); + +// create the serialized form of the polygon +// result's first char will be the 8bit type. See serialized form doc +// points copied +extern char *lwpoly_serialize(LWPOLY *poly); + +// same as above, writes to buf +extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *size); + +// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) +extern BOX3D *lwpoly_findbbox(LWPOLY *poly); + +//-------------------------------------------------------- + +// MULTIPOINTTYPE +typedef struct +{ + int32 SRID; + char ndims; + int npoints; + LWPOINT **points; +} LWMPOINT; + +// MULTILINETYPE +typedef struct +{ + int32 SRID; + char ndims; + int nlines; + LWLINE **lines; +} LWMLINE; + +// MULTIPOLYGONTYPE +typedef struct +{ + int32 SRID; + char ndims; + int npolys; + LWPOLY **polys; +} LWMPOLY; + +// COLLECTIONTYPE +typedef struct +{ + int32 SRID; + char ndims; + int ngeoms; + struct LWGEOM **geoms; +} LWCOLLECTION; + +// LWGEOM (any type) +typedef struct +{ + char type; + union { + LWPOINT *point; + LWMPOINT *mpoint; + LWLINE *line; + LWMLINE *mline; + LWPOLY *poly; + LWMPOLY *mpoly; + LWCOLLECTION *collection; + }; +} LWGEOM; + +LWGEOM *lwgeom_deserialize(char *serializedform); +LWMPOINT *lwmpoint_deserialize(char *serializedform); +LWMLINE *lwmline_deserialize(char *serializedform); +LWMPOLY *lwmpoly_deserialize(char *serializedform); +LWCOLLECTION *lwcollection_deserialize(char *serializedform); + +//------------------------------------------------------ + +//------------------------------------------------------ +// Multi-geometries +// +// These are all handled equivelently so its easy to write iterator code. +// NOTE NOTE: you can hand in a non-multigeometry to most of these functions +// and get usual behavior (ie. get geometry 0 on a POINT +// will return the point). +// This makes coding even easier since you dont have to necessarily +// differenciate between the multi* and non-multi geometries. +// +// NOTE: these usually work directly off the serialized form, so +// they're a little more difficult to handle (and slower) +// NOTE NOTE: the get functions maybe slow, so we may want to have an "analysed" +// lwgeom that would just have pointer to the start of each sub-geometry. +//------------------------------------------------------ + + + +// use this version for speed. READ-ONLY! +typedef struct +{ + int SRID; + const char *serialized_form; // orginal structure + unsigned char type; // 8-bit type for the LWGEOM + int ngeometries; // number of sub-geometries + char * * const sub_geoms; // list of pointers (into serialized_form) of the sub-geoms +} LWGEOM_INSPECTED; + +extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number); + +/* + * This structure is intended to be used for geometry collection construction. + * Does not allow specification of collection structure + * (serialization chooses the simpler form) + */ +typedef struct +{ + int SRID; + int ndims; + uint32 npoints; + char **points; + uint32 nlines; + char **lines; + uint32 npolys; + char **polys; +} LWGEOM_EXPLODED; + +void pfree_exploded(LWGEOM_EXPLODED *exploded); + +// Returns a 'palloced' union of the two input exploded geoms. +// Returns NULL if SRID or ndims do not match. +LWGEOM_EXPLODED * lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2); + +/* + * This function recursively scan the given serialized geometry + * and returns a list of _all_ subgeoms in it (deep-first) + */ +extern LWGEOM_EXPLODED *lwgeom_explode(char *serialized); + +/* + * Return the length of the serialized form corresponding + * to this exploded structure. + */ +extern uint32 lwexploded_findlength(LWGEOM_EXPLODED *exp, int wantbbox); + +// Serialize an LWGEOM_EXPLODED object. +// SRID and ndims will be taken from exploded structure. +// wantbbox will determine result bbox. +extern char *lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox); + +// Same as lwexploded_serialize but writing to pre-allocated space +extern void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, char *buf, int *retsize); + +// note - for a simple type (ie. point), this will have sub_geom[0] = serialized_form. +// for multi-geomtries sub_geom[0] will be a few bytes into the serialized form +// This function just computes the length of each sub-object and pre-caches this info. +// For a geometry collection of multi* geometries, you can inspect the sub-components +// as well. +extern LWGEOM_INSPECTED *lwgeom_inspect(const char *serialized_form); + + +// 1st geometry has geom_number = 0 +// if the actual sub-geometry isnt a POINT, null is returned (see _gettype()). +// if there arent enough geometries, return null. +// this is fine to call on a point (with geom_num=0), multipoint or geometrycollection +extern LWPOINT *lwgeom_getpoint(char *serialized_form, int geom_number); +extern LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number); + +// 1st geometry has geom_number = 0 +// if the actual geometry isnt a LINE, null is returned (see _gettype()). +// if there arent enough geometries, return null. +// this is fine to call on a line, multiline or geometrycollection +extern LWLINE *lwgeom_getline(char *serialized_form, int geom_number); +extern LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number); + +// 1st geometry has geom_number = 0 +// if the actual geometry isnt a POLYGON, null is returned (see _gettype()). +// if there arent enough geometries, return null. +// this is fine to call on a polygon, multipolygon or geometrycollection +extern LWPOLY *lwgeom_getpoly(char *serialized_form, int geom_number); +extern LWPOLY *lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number); + +// this gets the serialized form of a sub-geometry +// 1st geometry has geom_number = 0 +// if this isnt a multi* geometry, and geom_number ==0 then it returns +// itself +// returns null on problems. +// in the future this is how you would access a muli* portion of a +// geometry collection. +// GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1)) +// ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1) +// --> POINT(1 1) +// you can inspect the sub-geometry as well if you wish. +extern char *lwgeom_getsubgeometry(const char *serialized_form, int geom_number); +extern char *lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number); + + +// 1st geometry has geom_number = 0 +// use geom_number = -1 to find the actual type of the serialized form. +// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1) +// --> multipoint +// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0) +// --> point +// gets the 8bit type of the geometry at location geom_number +extern char lwgeom_getsubtype(char *serialized_form, int geom_number); +extern char lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number); + + +// how many sub-geometries are there? +// for point,line,polygon will return 1. +extern int lwgeom_getnumgeometries(char *serialized_form); +extern int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected); + + + +// set finalType to COLLECTIONTYPE or 0 (0 means choose a best type) +// (ie. give it 2 points and ask it to be a multipoint) +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +// all subgeometries must have the same SRID +// if you want to construct an inspected, call this then inspect the result... +extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometries, char **serialized_subs); + + +// construct the empty geometry (GEOMETRYCOLLECTION(EMPTY)) +extern char *lwgeom_constructempty(int SRID,int ndims); +extern void lwgeom_constructempty_buf(int SRID, int ndims, char *buf, int *size); +int lwgeom_empty_length(int SRID); + +// get the SRID from the LWGEOM +// none present => -1 +extern int lwgeom_getSRID(PG_LWGEOM *lwgeom); +extern int lwgeom_getsrid(char *serialized); +extern PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID); + +//get bounding box of LWGEOM (automatically calls the sub-geometries bbox generators) +extern BOX3D *lw_geom_getBB(char *serialized_form); +extern BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected); + + +//------------------------------------------------------ +// other stuff + +// handle the double-to-float conversion. The results of this +// will usually be a slightly bigger box because of the difference +// between float8 and float4 representations. + +extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box); +extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res); + +extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box); +extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d); + +extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2); + + +// returns a real entity so it doesnt leak +// if this has a pre-built BOX2d, then we use it, +// otherwise we need to compute it. +// WARNING! the EMPTY geom will result in a random BOX2D returned +extern BOX2DFLOAT4 getbox2d(char *serialized_form); + +// this function writes to 'box' and returns 0 if serialized_form +// does not have a bounding box (empty geom) +extern int getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box); + +// this function returns a pointer to the 'internal' bounding +// box of a serialized-form geometry. If the geometry does +// not have an embedded bounding box the function returns NULL. +// READ-ONLY! +extern const BOX2DFLOAT4 * getbox2d_internal(char *serialized_form); + +// Expand given box of 'd' units in all directions +void expand_box2d(BOX2DFLOAT4 *box, double d); +void expand_box3d(BOX3D *box, double d); + +//**************************************************************** +// memory management -- these only delete the memory associated +// directly with the structure - NOT the stuff pointing into +// the original de-serialized info + +extern void pfree_inspected(LWGEOM_INSPECTED *inspected); +extern void pfree_point (LWPOINT *pt); +extern void pfree_line (LWLINE *line); +extern void pfree_polygon (LWPOLY *poly); +extern void pfree_POINTARRAY(POINTARRAY *pa); + + +//*********************************************************** +// utility + +extern uint32 get_uint32(const char *loc); +extern int32 get_int32(const char *loc); +extern void printPA(POINTARRAY *pa); +extern void printLWPOINT(LWPOINT *point); +extern void printLWLINE(LWLINE *line); +extern void printLWPOLY(LWPOLY *poly); +extern void printBYTES(unsigned char *a, int n); +extern void printMULTI(char *serialized); +extern void deparse_hex(unsigned char str, unsigned char *result); +extern void printType(unsigned char str); + + +//------------------------------------------------------------ +//------------------------------------------------------------ +// On serialized form (see top for the 8bit type implementation) + +// NOTE: contrary to the original proposal, bounding boxes are *never* +// included in the geometry. You must either refer to the index +// or compute it on demand. + + +// The serialized form is always a stream of bytes. The first four are always +// the memory size of the LWGEOM (including the 4 byte memory size). + +// The easiest way to describe the serialed form is with examples: +// (more examples are available in the postgis mailing list) + +//3D point w/o bounding box:: +// size = 29 bytes +// type: S=0,D=1, tttt= 1 +// X +// Y +// Z + +//2D line String +// size = ... +// type: S=0,D=0, tttt= 2 +// npoints +// X0 +// Y0 +// X1 +// Y1 +// X2 +// Y2 +//... + +//3D polygon w/o bounding box +// size = ... +// type: S=0,D=0, tttt= 3 +// nrings +// npoints in ring0 +// X0 +// Y0 +// X1 +// Y1 +// X2 +// Y2 +//... +// npoints in ring1 +// X0 +// Y0 +// X1 +// Y1 +// X2 +// Y2 +//... +//... + + +// the multi* representations are very simple + +// size = ... +// type: ... with tttt= +// ngeometries +// +// +// +// ... + + + +// see implementation for more exact details. + + +//---------------------------------------------------------------- +// example function (computes total length of the lines in a LWGEOM). +// This works for a LINESTRING, MULTILINESTRING, OR GEOMETRYCOLLECTION + + + +// char *serialized_form = (char *) [[get from database]] +// +// double total_length_so_far = 0; +// for (int t=0;t< lwgeom_getnumgeometries(serialized_form) ; t++) +// { +// LWLINE *line = lwgeom_getline(serialized_form, t); +// if (line != NULL) +// { +// double length = findlength( POINT_ARRAY(line->points) ); //2d/3d aware +// total_length_so_far + = length; +// } +// } +// return total_length_so_far; + + +// using the LWGEOM_INSPECTED way: + + +// char *serialized_form = (char *) [[get from datbase]] +// LWGEOM_INSPECTED inspected_geom = lwgeom_inspect(serialized_form); +// +// double total_length_so_far = 0; +// for (int t=0;t< lwgeom_getnumgeometries(inspected_geom) ; t++) +// { +// LWLINE *line = lwgeom_getline(inspected_geom, t); +// if (line != NULL) +// { +// double length = findlength( POINT_ARRAY(line->points) ); //2d/3d aware +// total_length_so_far + = length; +// } +// } +// return total_length_so_far; + + +// the findlength() function could be written like based on functions like: +// +// POINT3D getPoint3d(POINTARRAY pa, int n); (for a 2d/3d point and 3d length) +// POINT2D getPoint2d(POINTARRAY pa, int n); (for a 2d/3d point and 2d length) +// NOTE: make sure your findlength() function knows what to do with z=NaN. + + +extern float LWGEOM_Minf(float a, float b); +extern float LWGEOM_Maxf(float a, float b); +extern double LWGEOM_Mind(double a, double b); +extern double LWGEOM_Maxd(double a, double b); + +extern BOX3D *lw_geom_getBB_simple(char *serialized_form); + +extern float nextDown_f(double d); +extern float nextUp_f(double d); +extern double nextDown_d(float d); +extern double nextUp_d(float d); + + + +#if ! defined(__MINGW32__) +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) <= (b) ? (a) : (b)) +#endif +#define abs(a) ((a) < (0) ? (-a) : (a)) + + +// general utilities +extern double lwgeom_polygon_area(LWPOLY *poly); +extern double lwgeom_polygon_perimeter(LWPOLY *poly); +extern double lwgeom_polygon_perimeter2d(LWPOLY *poly); +extern double lwgeom_pointarray_length2d(POINTARRAY *pts); +extern double lwgeom_pointarray_length(POINTARRAY *pts); +extern void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize); +extern void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize); +extern void lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize); +extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2); +extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B); +extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D); +extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa); +extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2); +extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring); +extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly); +extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly); +extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2); +extern double distance2d_point_line(LWPOINT *point, LWLINE *line); +extern double distance2d_line_line(LWLINE *line1, LWLINE *line2); +extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly); +extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2); +extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly); +extern double lwgeom_mindistance2d_recursive(char *lw1, char *lw2); +extern void lwgeom_translate_recursive(char *serialized, double xoff, double yoff, double zoff); +extern void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff); +extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad); +extern POINTARRAY *segmentize2d_ptarray(POINTARRAY *ipa, double dist); +extern int32 lwgeom_npoints(char *serialized); +extern char ptarray_isccw(const POINTARRAY *pa); + +#endif // !defined _LIBLWGEOM_H diff --git a/lwgeom/lwcollection.c b/lwgeom/lwcollection.c new file mode 100644 index 000000000..dfdc618fd --- /dev/null +++ b/lwgeom/lwcollection.c @@ -0,0 +1,35 @@ +#include +#include +#include "liblwgeom.h" + +LWCOLLECTION * +lwcollection_deserialize(char *srl) +{ + LWCOLLECTION *result; + LWGEOM_INSPECTED *insp; + int type = lwgeom_getType(srl[0]); + int i; + + if ( type != COLLECTIONTYPE ) + { + lwerror("lwmpoly_deserialize called on NON multipoly: %d", + type); + return NULL; + } + + insp = lwgeom_inspect(srl); + + result = lwalloc(sizeof(LWCOLLECTION)); + result->SRID = insp->SRID; + result->ndims = lwgeom_ndims(insp->type); + result->ngeoms = insp->ngeometries; + result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries); + + for (i=0; ingeometries; i++) + { + result->geoms[i] = (struct LWGEOM *)lwgeom_deserialize(insp->sub_geoms[i]); + } + + return result; +} + diff --git a/lwgeom/lwgeom.c b/lwgeom/lwgeom.c new file mode 100644 index 000000000..c7b96334f --- /dev/null +++ b/lwgeom/lwgeom.c @@ -0,0 +1,134 @@ +#include +#include +#include + +#include "lwgeom_pg.h" +#include "liblwgeom.h" + +#define CONTEXT_PG 0 +#define CONTEXT_STANDALONE 1 + +/* Define this to the default context liblwgeom runs with */ +#define DEFAULT_CONTEXT CONTEXT_PG + + +/* globals */ +#if DEFAULT_CONTEXT == CONTEXT_PG +lwallocator lwalloc = pg_alloc; +lwreallocator lwrealloc = pg_realloc; +lwfreeor lwfree = pg_free; +lwreporter lwerror = pg_error; +lwreporter lwnotice = pg_notice; +#else +lwallocator lwalloc = default_allocator; +lwreallocator lwrealloc = default_reallocator; +lwfreeor lwfree = default_freeor; +lwreporter lwerror = default_errorreporter; +lwreporter lwnotice = default_noticereporter; +#endif + +LWGEOM * +lwgeom_deserialize(char *srl) +{ + LWGEOM *result; + int type = lwgeom_getType(srl[0]); + + result = lwalloc(sizeof(LWGEOM)); + result->type = type; + switch (type) + { + case POINTTYPE: + result->point = lwpoint_deserialize(srl); + break; + case LINETYPE: + result->line = lwline_deserialize(srl); + break; + case POLYGONTYPE: + result->poly = lwpoly_deserialize(srl); + break; + case MULTIPOINTTYPE: + result->mpoint = lwmpoint_deserialize(srl); + break; + case MULTILINETYPE: + result->mline = lwmline_deserialize(srl); + break; + case MULTIPOLYGONTYPE: + result->mpoly = lwmpoly_deserialize(srl); + break; + case COLLECTIONTYPE: + result->collection = lwcollection_deserialize(srl); + break; + default: + lwerror("Unknown geometry type: %d", type); + return NULL; + } + + return result; +} + +void * +default_allocator(size_t size) +{ + void * result; + result = malloc(size); + return result; +} + +void * +default_reallocator(void *mem, size_t size) +{ + void * result; + result = realloc(mem, size); + return result; +} + +void +default_errorreporter(const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start (ap, fmt); + + /* + * This is a GNU extension. + * Dunno how to handle errors here. + */ + if (!vasprintf (&msg, fmt, ap)) + { + va_end (ap); + return; + } + va_end(ap); + fprintf(stderr, "%s", msg); + free(msg); +} + +void +default_noticereporter(const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start (ap, fmt); + + /* + * This is a GNU extension. + * Dunno how to handle errors here. + */ + if (!vasprintf (&msg, fmt, ap)) + { + va_end (ap); + return; + } + va_end(ap); + fprintf(stderr, "%s", msg); + free(msg); +} + +void +default_freeor(void *ptr) +{ + free(ptr); +} + diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index 2848b1eff..2cb8d0d2a 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -265,7 +265,6 @@ extern int lwgeom_size_subgeom(const char *serialized_form, int geom_number); typedef struct { - int type; // POINTTYPE char ndims; // 2=2d, 3=3d, 4=4d, 5=undef int SRID; // spatial ref sys POINTARRAY *point; // hide 2d/3d (this will be an array of 1 point) @@ -303,7 +302,6 @@ extern POINT3D lwpoint_getPoint3d(const LWPOINT *point); typedef struct { - int type; // LINETYPE char ndims; // 2=2d, 3=3d, 4=4d, 5=undef int SRID; // spatial ref sys -1=none POINTARRAY *points; // array of POINT3D @@ -337,7 +335,6 @@ extern BOX3D *lwline_findbbox(LWLINE *line); typedef struct { - int type; // POLYGONTYPE int32 SRID; char ndims; int nrings; @@ -368,6 +365,64 @@ extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *size); // find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) extern BOX3D *lwpoly_findbbox(LWPOLY *poly); +//-------------------------------------------------------- + +// MULTIPOINTTYPE +typedef struct +{ + int32 SRID; + char ndims; + int npoints; + LWPOINT **points; +} LWMPOINT; + +// MULTILINETYPE +typedef struct +{ + int32 SRID; + char ndims; + int nlines; + LWLINE **lines; +} LWMLINE; + +// MULTIPOLYGONTYPE +typedef struct +{ + int32 SRID; + char ndims; + int npolys; + LWPOLY **polys; +} LWMPOLY; + +// COLLECTIONTYPE +typedef struct +{ + int32 SRID; + char ndims; + int ngeoms; + struct LWGEOM **geoms; +} LWCOLLECTION; + +// LWGEOM (any type) +typedef struct +{ + char type; + union { + LWPOINT *point; + LWMPOINT *mpoint; + LWLINE *line; + LWMLINE *mline; + LWPOLY *poly; + LWMPOLY *mpoly; + LWCOLLECTION *collection; + }; +} LWGEOM; + +LWGEOM *lwgeom_deserialize(char *serializedform); +LWMPOINT *lwmpoint_deserialize(char *serializedform); + +//------------------------------------------------------ + //------------------------------------------------------ // Multi-geometries // @@ -536,10 +591,10 @@ extern BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected); extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box); extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res); -extern BOX2DFLOAT4 *box_to_box2df(BOX *box); // postgresql standard type - extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box); extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d); + +extern BOX2DFLOAT4 *box_to_box2df(BOX *box); // postgresql standard type extern BOX box2df_to_box(BOX2DFLOAT4 *box); // postgresql standard type extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type @@ -716,26 +771,6 @@ extern void printType(unsigned char str); // other forwards (for indirect function calls) -Datum box2d_same(PG_FUNCTION_ARGS); -Datum box2d_overlap(PG_FUNCTION_ARGS); -Datum box2d_overleft(PG_FUNCTION_ARGS); -Datum box2d_left(PG_FUNCTION_ARGS); -Datum box2d_right(PG_FUNCTION_ARGS); -Datum box2d_overright(PG_FUNCTION_ARGS); -Datum box2d_contained(PG_FUNCTION_ARGS); -Datum box2d_contain(PG_FUNCTION_ARGS); -Datum box2d_inter(PG_FUNCTION_ARGS); -Datum box2d_union(PG_FUNCTION_ARGS); - -Datum gist_lwgeom_compress(PG_FUNCTION_ARGS); -Datum gist_lwgeom_consistent(PG_FUNCTION_ARGS); -Datum gist_rtree_decompress(PG_FUNCTION_ARGS); -Datum lwgeom_box_union(PG_FUNCTION_ARGS); -Datum lwgeom_box_penalty(PG_FUNCTION_ARGS); -Datum lwgeom_gbox_same(PG_FUNCTION_ARGS); -Datum lwgeom_gbox_picksplit(PG_FUNCTION_ARGS); - - extern float LWGEOM_Minf(float a, float b); extern float LWGEOM_Maxf(float a, float b); extern double LWGEOM_Mind(double a, double b); diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 9d39bd58c..887d42e42 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -1,4 +1,3 @@ -#include "postgres.h" #include #include @@ -6,15 +5,7 @@ #include #include -#include "access/gist.h" -#include "access/itup.h" -#include "access/rtree.h" - -#include "fmgr.h" -#include "utils/elog.h" - - -#include "lwgeom.h" +#include "liblwgeom.h" // this will change to NaN when I figure out how to // get NaN in a platform-independent way @@ -30,9 +21,6 @@ extern BOX3D *lw_geom_getBB_simple(char *serialized_form); #ifdef DEBUG_EXPLODED void checkexplodedsize(char *srl, LWGEOM_EXPLODED *exploded, int alloced, char wantbbox); #endif -static uint32 lwgeom_size_line(const char *serialized_line); -static uint32 lwgeom_size_point(const char *serialized_point); -static uint32 lwgeom_size_poly(const char *serialized_line); //********************************************************************* // BOX routines @@ -175,14 +163,14 @@ double nextUp_d(float d) // Convert BOX3D to BOX2D -// returned box2d is allocated with 'palloc' +// returned box2d is allocated with 'lwalloc' BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box) { - BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4)); + BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4)); if (box == NULL) { - elog(ERROR, "box3d_to_box2df got NUL box"); + lwerror("box3d_to_box2df got NUL box"); return result; } @@ -196,13 +184,13 @@ BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box) } // Convert BOX3D to BOX2D using pre-allocated BOX2D -// returned box2d is allocated with 'palloc' +// returned box2d is allocated with 'lwalloc' // return 0 on error (NULL input box) int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result) { if (box == NULL) { - elog(NOTICE, "box3d_to_box2df got NUL box"); + lwnotice("box3d_to_box2df got NUL box"); return 0; } @@ -216,22 +204,6 @@ int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result) } -//convert postgresql BOX to BOX2D -BOX2DFLOAT4 *box_to_box2df(BOX *box) -{ - BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4)); - - if (box == NULL) - return result; - - result->xmin = nextDown_f(box->low.x); - result->ymin = nextDown_f(box->low.y); - - result->xmax = nextUp_f(box->high.x); - result->ymax = nextUp_f(box->high.x); - - return result; -} // convert BOX2D to BOX3D // zmin and zmax are set to 0.0 @@ -269,36 +241,6 @@ void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out) } -// convert BOX2D to postgresql BOX -BOX box2df_to_box(BOX2DFLOAT4 *box) -{ - BOX result; - - if (box == NULL) - return result; - - result.low.x = nextDown_d(box->xmin); - result.low.y = nextDown_d(box->ymin); - - result.high.x = nextUp_d(box->xmax); - result.high.y = nextUp_d(box->ymax); - - return result; -} - -// convert BOX2D to postgresql BOX -void -box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out) -{ - if (box == NULL) return; - - out->low.x = nextDown_d(box->xmin); - out->low.y = nextDown_d(box->ymin); - - out->high.x = nextUp_d(box->xmax); - out->high.y = nextUp_d(box->ymax); -} - // returns a BOX3D that encloses b1 and b2 // combine_boxes(NULL,A) --> A @@ -308,7 +250,7 @@ BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2) { BOX3D *result; - result =(BOX3D*) palloc(sizeof(BOX3D)); + result =(BOX3D*) lwalloc(sizeof(BOX3D)); if ( (b1 == NULL) && (b2 == NULL) ) { @@ -372,32 +314,32 @@ BOX2DFLOAT4 getbox2d(char *serialized_form) loc = serialized_form+1; -//elog(NOTICE,"getbox2d: type is %d", type); +//lwnotice("getbox2d: type is %d", type); if (lwgeom_hasBBOX(type)) { //woot - this is easy -//elog(NOTICE,"getbox2d has box"); +//lwnotice("getbox2d has box"); memcpy(&result,loc, sizeof(BOX2DFLOAT4)); return result; } //we have to actually compute it! -//elog(NOTICE,"getbox2d -- computing bbox"); +//lwnotice("getbox2d -- computing bbox"); box3d = lw_geom_getBB_simple(serialized_form); -//elog(NOTICE,"lw_geom_getBB_simple got bbox3d(%.15g %.15g,%.15g %.15g)",box3d->xmin,box3d->ymin,box3d->xmax,box3d->ymax); +//lwnotice("lw_geom_getBB_simple got bbox3d(%.15g %.15g,%.15g %.15g)",box3d->xmin,box3d->ymin,box3d->xmax,box3d->ymax); if ( ! box3d_to_box2df_p(box3d, &result) ) { - elog(ERROR, "Error converting box3d to box2df"); + lwerror("Error converting box3d to box2df"); } //box = box3d_to_box2df(box3d); -//elog(NOTICE,"box3d made box2d(%.15g %.15g,%.15g %.15g)",box->xmin,box->ymin,box->xmax,box->ymax); +//lwnotice("box3d made box2d(%.15g %.15g,%.15g %.15g)",box->xmin,box->ymin,box->xmax,box->ymax); //memcpy(&result,box, sizeof(BOX2DFLOAT4)); - //pfree(box); + //lwfree(box); - pfree(box3d); + lwfree(box3d); return result; } @@ -411,7 +353,7 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box) BOX3D *box3d; #ifdef DEBUG - elog(NOTICE,"getbox2d_p call"); + lwnotice("getbox2d_p call"); #endif loc = serialized_form+1; @@ -420,22 +362,22 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box) { //woot - this is easy #ifdef DEBUG - elog(NOTICE,"getbox2d_p: has box"); + lwnotice("getbox2d_p: has box"); #endif memcpy(box, loc, sizeof(BOX2DFLOAT4)); return 1; } #ifdef DEBUG - elog(NOTICE,"getbox2d_p: has no box - computing"); + lwnotice("getbox2d_p: has no box - computing"); #endif //we have to actually compute it! -//elog(NOTICE,"getbox2d_p:: computing box"); +//lwnotice("getbox2d_p:: computing box"); box3d = lw_geom_getBB_simple(serialized_form); #ifdef DEBUG - elog(NOTICE, "getbox2d_p: lw_geom_getBB_simple returned %p", box3d); + lwnotice("getbox2d_p: lw_geom_getBB_simple returned %p", box3d); #endif if ( ! box3d ) @@ -449,14 +391,14 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box) } #ifdef DEBUG - elog(NOTICE, "getbox2d_p: box3d converted to box2d"); + lwnotice("getbox2d_p: box3d converted to box2d"); #endif //box2 = box3d_to_box2df(box3d); //memcpy(box,box2, sizeof(BOX2DFLOAT4)); - //pfree(box2); + //lwfree(box2); - pfree(box3d); + lwfree(box3d); return 1; } @@ -589,21 +531,21 @@ getPoint3d_p(const POINTARRAY *pa, int n, char *point) op = (POINT3D *)point; #ifdef DEBUG - elog(NOTICE, "getPoint3d_p called on array of %d-dimensions / %u pts", + lwnotice("getPoint3d_p called on array of %d-dimensions / %u pts", pa->ndims, pa->npoints); - if ( pa->npoints > 1000 ) elog(ERROR, "More then 1000 points in pointarray ??"); + if ( pa->npoints > 1000 ) lwerror("More then 1000 points in pointarray ??"); #endif if ( (n<0) || (n>=pa->npoints)) { - elog(NOTICE, "%d out of numpoint range (%d)", n, pa->npoints); + lwnotice("%d out of numpoint range (%d)", n, pa->npoints); return ; //error } size = pointArray_ptsize(pa); #ifdef DEBUG - elog(NOTICE, "getPoint3d_p: point size: %d", size); + lwnotice("getPoint3d_p: point size: %d", size); #endif ip = (POINT3D *)getPoint(pa, n); @@ -686,10 +628,10 @@ getPoint(const POINTARRAY *pa, int n) POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints) { POINTARRAY *pa; - pa = (POINTARRAY*)palloc(sizeof(POINTARRAY)); + pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY)); if (ndims>4) - elog(ERROR,"pointArray_construct:: called with dims = %i", (int) ndims); + lwerror("pointArray_construct:: called with dims = %i", (int) ndims); pa->ndims = ndims; pa->npoints = npoints; @@ -699,7 +641,7 @@ POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints) } // calculate the bounding box of a set of points -// returns a palloced BOX3D, or NULL on empty array. +// returns a lwalloced BOX3D, or NULL on empty array. // zmin/zmax values are set to NO_Z_VALUE if not available. BOX3D *pointArray_bbox(const POINTARRAY *pa) { @@ -709,35 +651,35 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa) int npoints = pa->npoints; #ifdef DEBUG - elog(NOTICE, "pointArray_bbox call (array has %d points)", pa->npoints); + lwnotice("pointArray_bbox call (array has %d points)", pa->npoints); #endif if (pa->npoints == 0) { #ifdef DEBUG - elog(NOTICE, "pointArray_bbox returning NULL"); + lwnotice("pointArray_bbox returning NULL"); #endif return NULL; } - if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__); + if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__); - result = (BOX3D*)palloc(sizeof(BOX3D)); + result = (BOX3D*)lwalloc(sizeof(BOX3D)); - if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__); + if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__); if ( ! result ) { - elog(NOTICE, "Out of virtual memory"); + lwnotice("Out of virtual memory"); return NULL; } //getPoint3d_p(pa, 0, (char*)pt); pt = (POINT3D *)getPoint(pa, 0); - if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__); + if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__); #ifdef DEBUG - elog(NOTICE, "pointArray_bbox: got point 0"); + lwnotice("pointArray_bbox: got point 0"); #endif result->xmin = pt->x; @@ -748,1102 +690,213 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa) if ( pa->ndims > 2 ) { result->zmin = pt->z; result->zmax = pt->z; - } else { - result->zmin = NO_Z_VALUE; - result->zmax = NO_Z_VALUE; - } - -#ifdef DEBUG - elog(NOTICE, "pointArray_bbox: scanning other %d points", pa->npoints); -#endif - for (t=1;tnpoints;t++) - { - //getPoint3d_p(pa,t,(char*)&pt); - pt = (POINT3D *)getPoint(pa, t); - if (pt->x < result->xmin) result->xmin = pt->x; - if (pt->y < result->ymin) result->ymin = pt->y; - if (pt->x > result->xmax) result->xmax = pt->x; - if (pt->y > result->ymax) result->ymax = pt->y; - - if ( pa->ndims > 2 ) { - if (pt->z > result->zmax) result->zmax = pt->z; - if (pt->z < result->zmax) result->zmax = pt->z; - } - } - -#ifdef DEBUG - elog(NOTICE, "pointArray_bbox returning box"); -#endif - - return result; -} - -//size of point represeneted in the POINTARRAY -// 16 for 2d, 24 for 3d, 32 for 4d -int -pointArray_ptsize(const POINTARRAY *pa) -{ - if ( pa->ndims < 2 || pa->ndims > 4 ) - { - elog(ERROR,"pointArray_ptsize:: ndims isnt 2,3, or 4"); - return 0; // never get here - } - - return sizeof(double)*pa->ndims; -} - - -//*************************************************************************** -// basic type handling - - -// returns true if this type says it has an SRID (S bit set) -bool lwgeom_hasSRID(unsigned char type) -{ - return (type & 0x40); -} - -// returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D -int lwgeom_ndims(unsigned char type) -{ - return ( (type & 0x30) >>4) +2; -} - - -// get base type (ie. POLYGONTYPE) -int lwgeom_getType(unsigned char type) -{ - return (type & 0x0F); -} - - -//construct a type (hasBOX=false) -unsigned char lwgeom_makeType(int ndims, char hasSRID, int type) -{ - unsigned char result = type; - - if (ndims == 3) - result = result | 0x10; - if (ndims == 4) - result = result | 0x20; - if (hasSRID) - result = result | 0x40; - - return result; -} - -//construct a type -unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, bool hasBBOX) -{ - unsigned char result = type; - - if (ndims == 3) - result = result | 0x10; - if (ndims == 4) - result = result | 0x20; - if (hasSRID) - result = result | 0x40; - if (hasBBOX) - result = result | 0x80; - - return result; -} - -//returns true if there's a bbox in this LWGEOM (B bit set) -bool lwgeom_hasBBOX(unsigned char type) -{ - return (type & 0x80); -} - -//***************************************************************************** -// basic sub-geometry types - -// handle missaligned unsigned int32 data -uint32 -get_uint32(const char *loc) -{ - uint32 result; - - memcpy(&result, loc, sizeof(uint32)); - return result; -} - -// handle missaligned signed int32 data -int32 -get_int32(const char *loc) -{ - int32 result; - - memcpy(&result,loc, sizeof(int32)); - return result; -} - -//****************************************************************************** -// basic LWLINE functions - - -// construct a new LWLINE. points will *NOT* be copied -// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points) -{ - LWLINE *result; - result = (LWLINE*) palloc( sizeof(LWLINE)); - - result->ndims =ndims; - result->SRID = SRID; - result->points = points; - - return result; -} - -// given the LWGEOM serialized form (or a pointer into a muli* one) -// construct a proper LWLINE. -// serialized_form should point to the 8bit type format (with type = 2) -// See serialized form doc -LWLINE *lwline_deserialize(char *serialized_form) -{ - unsigned char type; - LWLINE *result; - char *loc =NULL; - uint32 npoints; - POINTARRAY *pa; - - result = (LWLINE*) palloc(sizeof(LWLINE)) ; - - type = (unsigned char) serialized_form[0]; - if ( lwgeom_getType(type) != LINETYPE) - { - elog(ERROR,"lwline_deserialize: attempt to deserialize a line when its not really a line"); - return NULL; - } - - loc = serialized_form+1; - - if (lwgeom_hasBBOX(type)) - { - //elog(NOTICE, "line has bbox"); - loc += sizeof(BOX2DFLOAT4); - } - else - { - //elog(NOTICE, "line has NO bbox"); - } - - if ( lwgeom_hasSRID(type)) - { - //elog(NOTICE, "line has srid"); - result->SRID = get_int32(loc); - loc +=4; // type + SRID - } - else - { - //elog(NOTICE, "line has NO srid"); - result->SRID = -1; - } - - // we've read the type (1 byte) and SRID (4 bytes, if present) - - npoints = get_uint32(loc); - //elog(NOTICE, "line npoints = %d", npoints); - loc +=4; - pa = pointArray_construct( loc, lwgeom_ndims(type), npoints); - - result->points = pa; - result->ndims = lwgeom_ndims(type); - - return result; -} - -// convert this line into its serialize form -// result's first char will be the 8bit type. See serialized form doc -char *lwline_serialize(LWLINE *line) -{ - int size=1; // type byte - char hasSRID; - unsigned char * result; - int t; - char *loc; - -if (line == NULL) - elog(ERROR,"lwline_serialize:: given null line"); - - hasSRID = (line->SRID != -1); - - if (hasSRID) - size +=4; //4 byte SRID - - if (line->ndims == 3) - { - size += 24 * line->points->npoints; //x,y,z - } - else if (line->ndims == 2) - { - size += 16 * line->points->npoints; //x,y - } - else if (line->ndims == 4) - { - size += 32 * line->points->npoints; //x,y - } - - - size+=4; // npoints - - result = palloc(size); - - result[0] = (unsigned char) lwgeom_makeType(line->ndims,hasSRID, LINETYPE); - loc = result+1; - - if (hasSRID) - { - memcpy(loc, &line->SRID, sizeof(int32)); - loc += 4; - } - - memcpy(loc, &line->points->npoints, sizeof(int32)); - loc +=4; - //copy in points - -//elog(NOTICE," line serialize - size = %i", size); - - if (line->ndims == 3) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint3d_p(line->points, t, loc); - loc += 24; // size of a 3d point - } - } - else if (line->ndims == 2) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint2d_p(line->points, t, loc); - loc += 16; // size of a 2d point - } - } - else if (line->ndims == 4) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint4d_p(line->points, t, loc); - loc += 32; // size of a 2d point - } - } - //printBYTES((unsigned char *)result, size); - return result; -} - -// convert this line into its serialize form writing it into -// the given buffer, and returning number of bytes written into -// the given int pointer. -// result's first char will be the 8bit type. See serialized form doc -void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize) -{ - int size=1; // type byte - char hasSRID; - int t; - char *loc; - - if (line == NULL) - elog(ERROR,"lwline_serialize:: given null line"); - - hasSRID = (line->SRID != -1); - - if (hasSRID) size +=4; //4 byte SRID - - if (line->ndims == 3) - { - size += 24 * line->points->npoints; //x,y,z - } - else if (line->ndims == 2) - { - size += 16 * line->points->npoints; //x,y - } - else if (line->ndims == 4) - { - size += 32 * line->points->npoints; //x,y - } - - size+=4; // npoints - - buf[0] = (unsigned char) lwgeom_makeType(line->ndims, - hasSRID, LINETYPE); - loc = buf+1; - - if (hasSRID) - { - memcpy(loc, &line->SRID, sizeof(int32)); - loc += 4; - } - - memcpy(loc, &line->points->npoints, sizeof(int32)); - loc +=4; - //copy in points - -//elog(NOTICE," line serialize - size = %i", size); - - if (line->ndims == 3) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint3d_p(line->points, t, loc); - loc += 24; // size of a 3d point - } - } - else if (line->ndims == 2) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint2d_p(line->points, t, loc); - loc += 16; // size of a 2d point - } - } - else if (line->ndims == 4) - { - for (t=0; t< line->points->npoints;t++) - { - getPoint4d_p(line->points, t, loc); - loc += 32; // size of a 2d point - } - } - //printBYTES((unsigned char *)result, size); - - if (retsize) *retsize = size; -} - -// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) -BOX3D *lwline_findbbox(LWLINE *line) -{ - BOX3D *ret; - - if (line == NULL) - return NULL; - - ret = pointArray_bbox(line->points); - return ret; -} - -// find length of this serialized line -uint32 -lwgeom_size_line(const char *serialized_line) -{ - int type = (unsigned char) serialized_line[0]; - uint32 result =1; //type - const char *loc; - uint32 npoints; - - if ( lwgeom_getType(type) != LINETYPE) - elog(ERROR,"lwgeom_size_line::attempt to find the length of a non-line"); - - - loc = serialized_line+1; - - if (lwgeom_hasBBOX(type)) - { - loc += sizeof(BOX2DFLOAT4); - result +=sizeof(BOX2DFLOAT4); - } - - if ( lwgeom_hasSRID(type)) - { - loc += 4; // type + SRID - result +=4; - } - - // we've read the type (1 byte) and SRID (4 bytes, if present) - - npoints = get_uint32(loc); - result += 4; //npoints - - if (lwgeom_ndims(type) ==3) - { - return result + npoints * 24; - } - else if (lwgeom_ndims(type) ==2) - { - return result+ npoints * 16; - } - else if (lwgeom_ndims(type) ==4) - { - return result+ npoints * 32; - } - elog(ERROR,"lwgeom_size_line :: invalid ndims"); - return 0; //never get here -} - -// find length of this deserialized line -uint32 -lwline_size(LWLINE *line) -{ - uint32 size = 1; //type - - if ( line->SRID != -1 ) size += 4; // SRID - size += sizeof(double)*line->ndims*line->points->npoints; // points - - return size; -} - -//******************************************************************** -// support for the LWPOINT sub-type - -// construct a new point. point will not be copied -// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -LWPOINT * -lwpoint_construct(int ndims, int SRID, POINTARRAY *point) -{ - LWPOINT *result ; - - if (point == NULL) - return NULL; // error - - result = palloc(sizeof(LWPOINT)); - result->ndims = ndims; - result->SRID = SRID; - - result->point = point; - - return result; -} - -// given the LWPOINT serialized form (or a pointer into a muli* one) -// construct a proper LWPOINT. -// serialized_form should point to the 8bit type format (with type = 1) -// See serialized form doc -LWPOINT * -lwpoint_deserialize(char *serialized_form) -{ - unsigned char type; - LWPOINT *result; - char *loc = NULL; - POINTARRAY *pa; - -#ifdef DEBUG - elog(NOTICE, "lwpoint_deserialize called"); -#endif - - result = (LWPOINT*) palloc(sizeof(LWPOINT)) ; - - type = (unsigned char) serialized_form[0]; - - if ( lwgeom_getType(type) != POINTTYPE) return NULL; - - loc = serialized_form+1; - - if (lwgeom_hasBBOX(type)) - { -#ifdef DEBUG - elog(NOTICE, "lwpoint_deserialize: input has bbox"); -#endif - loc += sizeof(BOX2DFLOAT4); - } - - if ( lwgeom_hasSRID(type)) - { -#ifdef DEBUG - elog(NOTICE, "lwpoint_deserialize: input has SRID"); -#endif - result->SRID = get_int32(loc); - loc += 4; // type + SRID - } - else - { - result->SRID = -1; - } - - // we've read the type (1 byte) and SRID (4 bytes, if present) - - pa = pointArray_construct(loc, lwgeom_ndims(type), 1); - - result->point = pa; - result->ndims = lwgeom_ndims(type); - - return result; -} - -// convert this point into its serialize form -// result's first char will be the 8bit type. See serialized form doc -char * -lwpoint_serialize(LWPOINT *point) -{ - int size=1; - char hasSRID; - char *result; - char *loc; - - hasSRID = (point->SRID != -1); - - if (hasSRID) size +=4; //4 byte SRID - - if (point->ndims == 3) size += 24; //x,y,z - else if (point->ndims == 2) size += 16 ; //x,y,z - else if (point->ndims == 4) size += 32 ; //x,y,z,m - - result = palloc(size); - - result[0] = (unsigned char) lwgeom_makeType(point->ndims, - hasSRID, POINTTYPE); - loc = result+1; - - if (hasSRID) - { - memcpy(loc, &point->SRID, sizeof(int32)); - loc += 4; - } - - //copy in points - - if (point->ndims == 3) getPoint3d_p(point->point, 0, loc); - else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc); - else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc); - return result; -} - -// convert this point into its serialize form writing it into -// the given buffer, and returning number of bytes written into -// the given int pointer. -// result's first char will be the 8bit type. See serialized form doc -void -lwpoint_serialize_buf(LWPOINT *point, char *buf, int *retsize) -{ - int size=1; - char hasSRID; - char *loc; - - hasSRID = (point->SRID != -1); - - if (hasSRID) size +=4; //4 byte SRID - - if (point->ndims == 3) size += 24; //x,y,z - else if (point->ndims == 2) size += 16 ; //x,y,z - else if (point->ndims == 4) size += 32 ; //x,y,z,m - - buf[0] = (unsigned char) lwgeom_makeType(point->ndims, - hasSRID, POINTTYPE); - loc = buf+1; - - if (hasSRID) - { - memcpy(loc, &point->SRID, sizeof(int32)); - loc += 4; - } - - //copy in points - - if (point->ndims == 3) getPoint3d_p(point->point, 0, loc); - else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc); - else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc); - - if (retsize) *retsize = size; -} - -// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) -BOX3D * -lwpoint_findbbox(LWPOINT *point) -{ -#ifdef DEBUG - elog(NOTICE, "lwpoint_findbbox called with point %p", point); -#endif - if (point == NULL) - { -#ifdef DEBUG - elog(NOTICE, "lwpoint_findbbox returning NULL"); -#endif - return NULL; - } - -#ifdef DEBUG - elog(NOTICE, "lwpoint_findbbox returning pointArray_bbox return"); -#endif - - return pointArray_bbox(point->point); -} - -// convenience functions to hide the POINTARRAY -// TODO: obsolete this -POINT2D -lwpoint_getPoint2d(const LWPOINT *point) -{ - POINT2D result; - - if (point == NULL) - return result; - - return getPoint2d(point->point,0); -} - -// convenience functions to hide the POINTARRAY -POINT3D -lwpoint_getPoint3d(const LWPOINT *point) -{ - POINT3D result; - - if (point == NULL) - return result; - - return getPoint3d(point->point,0); -} - - -//find length of this serialized point -uint32 -lwgeom_size_point(const char *serialized_point) -{ - uint result = 1; - unsigned char type; - const char *loc; - - type = (unsigned char) serialized_point[0]; - - if ( lwgeom_getType(type) != POINTTYPE) return 0; - -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point called (%d)", result); -#endif - - loc = serialized_point+1; - - if (lwgeom_hasBBOX(type)) - { - loc += sizeof(BOX2DFLOAT4); - result +=sizeof(BOX2DFLOAT4); -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point: has bbox (%d)", result); -#endif - } - - if ( lwgeom_hasSRID(type)) - { -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point: has srid (%d)", result); -#endif - loc +=4; // type + SRID - result +=4; - } - - if (lwgeom_ndims(type) == 3) - { -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point: returning (%d)", result+24); -#endif - return result + 24; - } - else if (lwgeom_ndims(type) == 2) - { -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point: returning (%d)", result+16); -#endif - return result + 16; - } - else if (lwgeom_ndims(type) == 4) - { -#ifdef DEBUG -elog(NOTICE, "lwgeom_size_point: returning (%d)", result+32); -#endif - return result + 32; - } - - elog(ERROR,"lwgeom_size_point :: invalid ndims = %i", - lwgeom_ndims(type)); - return 0; //never get here -} - -// find length of this deserialized point -uint32 -lwpoint_size(LWPOINT *point) -{ - uint32 size = 1; // type - - if ( point->SRID != -1 ) size += 4; // SRID - size += point->ndims * sizeof(double); // point - - return size; -} - - -//******************************************************************** -// basic polygon manipulation - -// construct a new LWPOLY. arrays (points/points per ring) will NOT be copied -// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) -LWPOLY * -lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points) -{ - LWPOLY *result; - - result = (LWPOLY*) palloc(sizeof(LWPOLY)); - result->ndims = ndims; - result->SRID = SRID; - result->nrings = nrings; - result->rings = points; - - return result; -} - - -// given the LWPOLY serialized form (or a pointer into a muli* one) -// construct a proper LWPOLY. -// serialized_form should point to the 8bit type format (with type = 3) -// See serialized form doc -LWPOLY * -lwpoly_deserialize(char *serialized_form) -{ - - LWPOLY *result; - uint32 nrings; - int ndims; - uint32 npoints; - unsigned char type; - char *loc; - int t; - - if (serialized_form == NULL) - { - elog(ERROR, "lwpoly_deserialize called with NULL arg"); - return NULL; + } else { + result->zmin = NO_Z_VALUE; + result->zmax = NO_Z_VALUE; } - result = (LWPOLY*) palloc(sizeof(LWPOLY)); - - - type = (unsigned char) serialized_form[0]; - ndims = lwgeom_ndims(type); - loc = serialized_form; - - if ( lwgeom_getType(type) != POLYGONTYPE) +#ifdef DEBUG + lwnotice("pointArray_bbox: scanning other %d points", pa->npoints); +#endif + for (t=1;tnpoints;t++) { - elog(ERROR, "lwpoly_deserialize called with arg of type %d", - lwgeom_getType(type)); - return NULL; + //getPoint3d_p(pa,t,(char*)&pt); + pt = (POINT3D *)getPoint(pa, t); + if (pt->x < result->xmin) result->xmin = pt->x; + if (pt->y < result->ymin) result->ymin = pt->y; + if (pt->x > result->xmax) result->xmax = pt->x; + if (pt->y > result->ymax) result->ymax = pt->y; + + if ( pa->ndims > 2 ) { + if (pt->z > result->zmax) result->zmax = pt->z; + if (pt->z < result->zmax) result->zmax = pt->z; + } } +#ifdef DEBUG + lwnotice("pointArray_bbox returning box"); +#endif - loc = serialized_form+1; + return result; +} - if (lwgeom_hasBBOX(type)) +//size of point represeneted in the POINTARRAY +// 16 for 2d, 24 for 3d, 32 for 4d +int +pointArray_ptsize(const POINTARRAY *pa) +{ + if ( pa->ndims < 2 || pa->ndims > 4 ) { - loc += sizeof(BOX2DFLOAT4); + lwerror("pointArray_ptsize:: ndims isnt 2,3, or 4"); + return 0; // never get here } - if ( lwgeom_hasSRID(type)) - { - result->SRID = get_int32(loc); - loc +=4; // type + SRID - } - else - { - result->SRID = -1; - } + return sizeof(double)*pa->ndims; +} - nrings = get_uint32(loc); - result->nrings = nrings; - loc +=4; - result->rings = (POINTARRAY**) palloc(nrings* sizeof(POINTARRAY*)); - for (t =0;trings[t] = pointArray_construct(loc, ndims, npoints); - if (ndims == 3) - loc += 24*npoints; - else if (ndims == 2) - loc += 16*npoints; - else if (ndims == 4) - loc += 32*npoints; - } - result->ndims = ndims; - return result; +// returns true if this type says it has an SRID (S bit set) +char lwgeom_hasSRID(unsigned char type) +{ + return (type & 0x40); } -// create the serialized form of the polygon -// result's first char will be the 8bit type. See serialized form doc -// points copied -char * -lwpoly_serialize(LWPOLY *poly) +// returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D +int lwgeom_ndims(unsigned char type) { - int size=1; // type byte - char hasSRID; - char *result; - int t,u; - int total_points = 0; - int npoints; - char *loc; - - hasSRID = (poly->SRID != -1); - - if (hasSRID) - size +=4; //4 byte SRID - - size += 4; // nrings - size += 4*poly->nrings; //npoints/ring + return ( (type & 0x30) >>4) +2; +} - for (t=0;tnrings;t++) - { - total_points += poly->rings[t]->npoints; - } - if (poly->ndims == 3) - size += 24*total_points; - else if (poly->ndims == 2) - size += 16*total_points; - else if (poly->ndims == 4) - size += 32*total_points; +// get base type (ie. POLYGONTYPE) +int lwgeom_getType(unsigned char type) +{ + return (type & 0x0F); +} - result = palloc(size); - result[0] = (unsigned char) lwgeom_makeType(poly->ndims,hasSRID, POLYGONTYPE); - loc = result+1; +//construct a type (hasBOX=false) +unsigned char lwgeom_makeType(int ndims, char hasSRID, int type) +{ + unsigned char result = type; + if (ndims == 3) + result = result | 0x10; + if (ndims == 4) + result = result | 0x20; if (hasSRID) - { - memcpy(loc, &poly->SRID, sizeof(int32)); - loc += 4; - } - - memcpy(loc, &poly->nrings, sizeof(int32)); // nrings - loc+=4; + result = result | 0x40; + return result; +} +//construct a type +unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, char hasBBOX) +{ + unsigned char result = type; - for (t=0;tnrings;t++) - { - POINTARRAY *pa = poly->rings[t]; - npoints = poly->rings[t]->npoints; - memcpy(loc, &npoints, sizeof(int32)); //npoints this ring - loc+=4; - if (poly->ndims == 3) - { - for (u=0;undims == 2) - { - for (u=0;undims == 4) - { - for (u=0;uSRID != -1); - - if (hasSRID) size +=4; //4 byte SRID + return (type & 0x80); +} - size += 4; // nrings - size += 4*poly->nrings; //npoints/ring +//***************************************************************************** +// basic sub-geometry types - for (t=0;tnrings;t++) - { - total_points += poly->rings[t]->npoints; - } - if (poly->ndims == 3) size += 24*total_points; - else if (poly->ndims == 2) size += 16*total_points; - else if (poly->ndims == 4) size += 32*total_points; +// handle missaligned unsigned int32 data +uint32 +get_uint32(const char *loc) +{ + uint32 result; - buf[0] = (unsigned char) lwgeom_makeType(poly->ndims, - hasSRID, POLYGONTYPE); - loc = buf+1; + memcpy(&result, loc, sizeof(uint32)); + return result; +} - if (hasSRID) - { - memcpy(loc, &poly->SRID, sizeof(int32)); - loc += 4; - } +// handle missaligned signed int32 data +int32 +get_int32(const char *loc) +{ + int32 result; - memcpy(loc, &poly->nrings, sizeof(int32)); // nrings - loc+=4; + memcpy(&result,loc, sizeof(int32)); + return result; +} - for (t=0;tnrings;t++) - { - POINTARRAY *pa = poly->rings[t]; - npoints = poly->rings[t]->npoints; - memcpy(loc, &npoints, sizeof(int32)); //npoints this ring - loc+=4; - if (poly->ndims == 3) - { - for (u=0;undims == 2) - { - for (u=0;undims == 4) - { - for (u=0;urings[0]; // just need to check outer ring -- interior rings are inside - result = pointArray_bbox(pa); +//******************************************************************** +// support for the LWPOINT sub-type -// for (t=1;tnrings;t++) - //{ -// pa = poly->rings[t]; -// abox = pointArray_bbox(pa); -// abox2 = result; -// result = combine_boxes( abox, abox2); -// pfree(abox); -// pfree(abox2); - // } - return result; -} -//find length of this serialized polygon +//find length of this serialized point uint32 -lwgeom_size_poly(const char *serialized_poly) +lwgeom_size_point(const char *serialized_point) { - uint32 result = 1; // char type - uint32 nrings; - int ndims; - int t; + uint32 result = 1; unsigned char type; - uint32 npoints; const char *loc; - if (serialized_poly == NULL) - return -9999; - - - type = (unsigned char) serialized_poly[0]; - ndims = lwgeom_ndims(type); + type = (unsigned char) serialized_point[0]; - if ( lwgeom_getType(type) != POLYGONTYPE) - return -9999; + if ( lwgeom_getType(type) != POINTTYPE) return 0; +#ifdef DEBUG +lwnotice("lwgeom_size_point called (%d)", result); +#endif - loc = serialized_poly+1; + loc = serialized_point+1; if (lwgeom_hasBBOX(type)) { -#ifdef DEBUG - elog(NOTICE, "lwgeom_size_poly: has bbox"); -#endif loc += sizeof(BOX2DFLOAT4); result +=sizeof(BOX2DFLOAT4); +#ifdef DEBUG +lwnotice("lwgeom_size_point: has bbox (%d)", result); +#endif } - if ( lwgeom_hasSRID(type)) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size_poly: has srid"); +lwnotice("lwgeom_size_point: has srid (%d)", result); #endif loc +=4; // type + SRID - result += 4; + result +=4; } - - nrings = get_uint32(loc); - loc +=4; - result +=4; - - - for (t =0;tSRID != -1 ) size += 4; // SRID - - size += 4; // nrings - - for (i=0; inrings; i++) + else if (lwgeom_ndims(type) == 2) + { +#ifdef DEBUG +lwnotice("lwgeom_size_point: returning (%d)", result+16); +#endif + return result + 16; + } + else if (lwgeom_ndims(type) == 4) { - size += 4; // npoints - size += poly->rings[i]->npoints*poly->ndims*sizeof(double); +#ifdef DEBUG +lwnotice("lwgeom_size_point: returning (%d)", result+32); +#endif + return result + 32; } - return size; + lwerror("lwgeom_size_point :: invalid ndims = %i", + lwgeom_ndims(type)); + return 0; //never get here } + + //************************************************************************* // multi-geometry support // note - for a simple type (ie. point), this will have sub_geom[0] = serialized_form. @@ -1854,7 +907,7 @@ lwpoly_size(LWPOLY *poly) LWGEOM_INSPECTED * lwgeom_inspect(const char *serialized_form) { - LWGEOM_INSPECTED *result = palloc(sizeof(LWGEOM_INSPECTED)); + LWGEOM_INSPECTED *result = lwalloc(sizeof(LWGEOM_INSPECTED)); unsigned char type; char **sub_geoms; const char *loc; @@ -1885,7 +938,7 @@ lwgeom_inspect(const char *serialized_form) } //simple geometry (point/line/polygon)-- not multi! result->ngeometries = 1; - sub_geoms = (char**) palloc(sizeof(char*)); + sub_geoms = (char**) lwalloc(sizeof(char*)); sub_geoms[0] = serialized_form; result->sub_geoms = sub_geoms; return result; @@ -1902,24 +955,24 @@ lwgeom_inspect(const char *serialized_form) result->ngeometries = get_uint32(loc); loc +=4; #ifdef DEBUG - elog(NOTICE, "lwgeom_inspect: geometry is a collection of %d elements", + lwnotice("lwgeom_inspect: geometry is a collection of %d elements", result->ngeometries); #endif if ( ! result->ngeometries ) return result; - sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries ); + sub_geoms = (char**) lwalloc(sizeof(char*) * result->ngeometries ); result->sub_geoms = sub_geoms; sub_geoms[0] = loc; #ifdef DEBUG - elog(NOTICE, "subgeom[0] @ %p", sub_geoms[0]); + lwnotice("subgeom[0] @ %p", sub_geoms[0]); #endif for (t=1;tngeometries; t++) { int sub_length = lwgeom_size_subgeom(sub_geoms[t-1], -1);//-1 = entire object sub_geoms[t] = sub_geoms[t-1] + sub_length; #ifdef DEBUG - elog(NOTICE, "subgeom[%d] @ %p (sub_length: %d)", + lwnotice("subgeom[%d] @ %p (sub_length: %d)", t, sub_geoms[t], sub_length); #endif } @@ -2182,7 +1235,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri if (nsubgeometries == 0) return lwgeom_constructempty(SRID,ndims); - lengths = palloc(sizeof(int32) * nsubgeometries); + lengths = lwalloc(sizeof(int32) * nsubgeometries); for (t=0;t size of the point // take a geometry, and find its length -int +uint32 lwgeom_size(const char *serialized_form) { unsigned char type = lwgeom_getType((unsigned char) serialized_form[0]); @@ -2344,34 +1397,34 @@ lwgeom_size(const char *serialized_form) int result = 1; //"type" #ifdef DEBUG - elog(NOTICE, "lwgeom_size called"); + lwnotice("lwgeom_size called"); #endif if (type == POINTTYPE) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size: is a point"); + lwnotice("lwgeom_size: is a point"); #endif return lwgeom_size_point(serialized_form); } else if (type == LINETYPE) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size: is a line"); + lwnotice("lwgeom_size: is a line"); #endif return lwgeom_size_line(serialized_form); } else if (type == POLYGONTYPE) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size: is a polygon"); + lwnotice("lwgeom_size: is a polygon"); #endif return lwgeom_size_poly(serialized_form); } if ( type == 0 ) { - elog(ERROR, "lwgeom_size called with unknown-typed serialized geometry"); + lwerror("lwgeom_size called with unknown-typed serialized geometry"); return 0; } @@ -2379,7 +1432,7 @@ lwgeom_size(const char *serialized_form) //NOTE: for a geometry collection of GC of GC of GC we will be recursing... #ifdef DEBUG - elog(NOTICE, "lwgeom_size called on a geoemtry with type %d", type); + lwnotice("lwgeom_size called on a geoemtry with type %d", type); #endif loc = serialized_form+1; @@ -2387,7 +1440,7 @@ lwgeom_size(const char *serialized_form) if (lwgeom_hasBBOX((unsigned char) serialized_form[0])) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size: has bbox"); + lwnotice("lwgeom_size: has bbox"); #endif loc += sizeof(BOX2DFLOAT4); @@ -2397,7 +1450,7 @@ lwgeom_size(const char *serialized_form) if (lwgeom_hasSRID( (unsigned char) serialized_form[0]) ) { #ifdef DEBUG - elog(NOTICE, "lwgeom_size: has srid"); + lwnotice("lwgeom_size: has srid"); #endif result +=4; loc +=4; @@ -2409,26 +1462,26 @@ lwgeom_size(const char *serialized_form) result += 4; // numgeoms #ifdef DEBUG - elog(NOTICE, "lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result); + lwnotice("lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result); #endif for (t=0;tsub_geoms[t] ); - //elog(NOTICE,"%i has box :: BBOX3D(%g %g, %g %g)",t,b1->xmin, b1->ymin,b1->xmax, b1->ymax); + //lwnotice("%i has box :: BBOX3D(%g %g, %g %g)",t,b1->xmin, b1->ymin,b1->xmax, b1->ymax); if (result != NULL) { b2= result; result = combine_boxes(b2, b1); -// elog(NOTICE,"combined has :: BBOX3D(%g %g, %g %g)",result->xmin, result->ymin,result->xmax, result->ymax); +// lwnotice("combined has :: BBOX3D(%g %g, %g %g)",result->xmin, result->ymin,result->xmax, result->ymax); - pfree(b1); - pfree(b2); + lwfree(b1); + lwfree(b2); } else { @@ -2607,37 +1660,14 @@ BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected) void pfree_inspected(LWGEOM_INSPECTED *inspected) { if ( inspected->ngeometries ) - pfree(inspected->sub_geoms); - pfree(inspected); -} - -void pfree_point (LWPOINT *pt) -{ - pfree_POINTARRAY(pt->point); - pfree(pt); -} - -void pfree_line (LWLINE *line) -{ - pfree(line->points); - pfree(line); + lwfree(inspected->sub_geoms); + lwfree(inspected); } -void pfree_polygon (LWPOLY *poly) -{ - int t; - - for (t=0;tnrings;t++) - { - pfree_POINTARRAY(poly->rings[t]); - } - - pfree(poly); -} void pfree_POINTARRAY(POINTARRAY *pa) { - pfree(pa); + lwfree(pa); } @@ -2647,24 +1677,6 @@ void pfree_POINTARRAY(POINTARRAY *pa) //** debugging routines -void printLWLINE(LWLINE *line) -{ - elog(NOTICE,"LWLINE {"); - elog(NOTICE," ndims = %i", (int)line->ndims); - elog(NOTICE," SRID = %i", (int)line->SRID); - printPA(line->points); - elog(NOTICE,"}"); -} - -void printLWPOINT(LWPOINT *point) -{ - elog(NOTICE,"LWPOINT {"); - elog(NOTICE," ndims = %i", (int)point->ndims); - elog(NOTICE," SRID = %i", (int)point->SRID); - printPA(point->point); - elog(NOTICE,"}"); -} - void printPA(POINTARRAY *pa) { int t; @@ -2672,30 +1684,30 @@ void printPA(POINTARRAY *pa) POINT3D pt3; POINT4D pt4; - elog(NOTICE," POINTARRAY{"); - elog(NOTICE," ndims =%i, ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa)); - elog(NOTICE," npoints = %i", pa->npoints); + lwnotice(" POINTARRAY{"); + lwnotice(" ndims =%i, ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa)); + lwnotice(" npoints = %i", pa->npoints); for (t =0; tnpoints;t++) { if (pa->ndims == 2) { pt2 = getPoint2d(pa,t); - elog(NOTICE," %i : %lf,%lf",t,pt2.x,pt2.y); + lwnotice(" %i : %lf,%lf",t,pt2.x,pt2.y); } if (pa->ndims == 3) { pt3 = getPoint3d(pa,t); - elog(NOTICE," %i : %lf,%lf,%lf",t,pt3.x,pt3.y,pt3.z); + lwnotice(" %i : %lf,%lf,%lf",t,pt3.x,pt3.y,pt3.z); } if (pa->ndims == 4) { pt4 = getPoint4d(pa,t); - elog(NOTICE," %i : %lf,%lf,%lf,%lf",t,pt3.x,pt4.y,pt4.z,pt4.m); + lwnotice(" %i : %lf,%lf,%lf,%lf",t,pt3.x,pt4.y,pt4.z,pt4.m); } } - elog(NOTICE," }"); + lwnotice(" }"); } void printBYTES(unsigned char *a, int n) @@ -2705,31 +1717,16 @@ void printBYTES(unsigned char *a, int n) buff[2] = 0; //null terminate - elog(NOTICE," BYTE ARRAY (n=%i) IN HEX: {", n); + lwnotice(" BYTE ARRAY (n=%i) IN HEX: {", n); for (t=0;tndims); - elog(NOTICE," SRID = %i", (int)poly->SRID); - elog(NOTICE," nrings = %i", (int)poly->nrings); - for (t=0;tnrings;t++) - { - elog(NOTICE," RING # %i :",t); - printPA(poly->rings[t]); - } - elog(NOTICE,"}"); -} - void printMULTI(char *serialized) { @@ -2739,11 +1736,11 @@ printMULTI(char *serialized) LWPOLY *poly; int t; - elog(NOTICE,"MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((unsigned char)serialized[0]), inspected->ngeometries); + lwnotice("MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((unsigned char)serialized[0]), inspected->ngeometries); for (t=0;tngeometries;t++) { - elog(NOTICE," sub-geometry %i:", t); + lwnotice(" sub-geometry %i:", t); line = NULL; point = NULL; poly = NULL; line = lwgeom_getline_inspected(inspected,t); @@ -2763,14 +1760,14 @@ printMULTI(char *serialized) } } - elog(NOTICE,"end multi*"); + lwnotice("end multi*"); pfree_inspected(inspected); } void printType(unsigned char type) { - elog(NOTICE,"type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type)); + lwnotice("type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type)); } // get the SRID from the LWGEOM @@ -2809,7 +1806,7 @@ int lwgeom_getSRID(PG_LWGEOM *lwgeom) // Set the SRID of a LWGEOM // Returns a newly allocated LWGEOM object. -// Allocation will be done using the palloc. +// Allocation will be done using the lwalloc. PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) { unsigned char type = lwgeom->type; @@ -2826,16 +1823,16 @@ PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) if (lwgeom_hasSRID(type)) { //we create a new one and copy the SRID in - result = palloc(len); + result = lwalloc(len); memcpy(result, lwgeom, len); memcpy(result->data+bbox_offset, &newSRID,4); } else // need to add one { len_new = len + 4;//+4 for SRID - result = palloc(len_new); + result = lwalloc(len_new); memcpy(result, &len_new, 4); // size copy in - result->type = lwgeom_makeType_full(lwgeom_ndims(type), true, lwgeom_getType(type),lwgeom_hasBBOX(type)); + result->type = lwgeom_makeType_full(lwgeom_ndims(type), 1, lwgeom_getType(type),lwgeom_hasBBOX(type)); loc_new = result->data; loc_old = lwgeom->data; @@ -2900,7 +1897,7 @@ PG_LWGEOM_construct(char *ser, int SRID, int wantbbox) size+=4; // size header - result = palloc(size); + result = lwalloc(size); result->size = size; result->type = lwgeom_makeType_full(lwgeom_ndims(ser[0]), @@ -2925,12 +1922,12 @@ void pfree_exploded(LWGEOM_EXPLODED *exploded) { if ( exploded->npoints ) - pfree(exploded->points); + lwfree(exploded->points); if ( exploded->nlines ) - pfree(exploded->lines); + lwfree(exploded->lines); if ( exploded->npolys ) - pfree(exploded->polys); - pfree(exploded); + lwfree(exploded->polys); + lwfree(exploded); }; /* @@ -2945,33 +1942,33 @@ lwgeom_explode(char *serialized) int i; #ifdef DEBUG - elog(NOTICE, "lwgeom_explode called"); + lwnotice("lwgeom_explode called"); #endif inspected = lwgeom_inspect(serialized); #ifdef DEBUG -elog(NOTICE, "lwgeom_explode: serialized inspected"); +lwnotice("lwgeom_explode: serialized inspected"); #endif - result = palloc(sizeof(LWGEOM_EXPLODED)); - result->points = palloc(1); - result->lines = palloc(1); - result->polys = palloc(1); + result = lwalloc(sizeof(LWGEOM_EXPLODED)); + result->points = lwalloc(1); + result->lines = lwalloc(1); + result->polys = lwalloc(1); result->npoints = 0; result->nlines = 0; result->npolys = 0; if ( ! inspected->ngeometries ) { - pfree(result->points); - pfree(result->lines); - pfree(result->polys); + lwfree(result->points); + lwfree(result->lines); + lwfree(result->polys); result->SRID = -1; result->ndims = 0; pfree_inspected(inspected); - //elog(NOTICE, "lwgeom_explode: no geometries"); + //lwnotice("lwgeom_explode: no geometries"); return result; } @@ -2987,9 +1984,9 @@ elog(NOTICE, "lwgeom_explode: serialized inspected"); if ( type == POINTTYPE ) { #ifdef DEBUG -elog(NOTICE, "lwgeom_explode: it's a point"); +lwnotice("lwgeom_explode: it's a point"); #endif - result->points = repalloc(result->points, + result->points = lwrealloc(result->points, (result->npoints+1)*sizeof(char *)); result->points[result->npoints] = subgeom; result->npoints++; @@ -2999,9 +1996,9 @@ elog(NOTICE, "lwgeom_explode: it's a point"); if ( type == LINETYPE ) { #ifdef DEBUG -elog(NOTICE, "lwgeom_explode: it's a line"); +lwnotice("lwgeom_explode: it's a line"); #endif - result->lines = repalloc(result->lines, + result->lines = lwrealloc(result->lines, (result->nlines+1)*sizeof(char *)); result->lines[result->nlines] = subgeom; result->nlines++; @@ -3011,9 +2008,9 @@ elog(NOTICE, "lwgeom_explode: it's a line"); if ( type == POLYGONTYPE ) { #ifdef DEBUG -elog(NOTICE, "lwgeom_explode: it's a polygon"); +lwnotice("lwgeom_explode: it's a polygon"); #endif - result->polys = repalloc(result->polys, + result->polys = lwrealloc(result->polys, (result->npolys+1)*sizeof(char *)); result->polys[result->npolys] = subgeom; result->npolys++; @@ -3021,14 +2018,14 @@ elog(NOTICE, "lwgeom_explode: it's a polygon"); } #ifdef DEBUG - elog(NOTICE, "type of subgeom %d is %d, recursing", i, type); + lwnotice("type of subgeom %d is %d, recursing", i, type); #endif // it's a multi geometry, recurse subexploded = lwgeom_explode(subgeom); #ifdef DEBUG - elog(NOTICE, "subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys); + lwnotice("subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys); #endif // Re-allocate adding space for new exploded geoms @@ -3038,13 +2035,13 @@ elog(NOTICE, "lwgeom_explode: it's a polygon"); if ( subexploded->npoints ) { - result->points = repalloc(result->points, + result->points = lwrealloc(result->points, sizeof(char *)*(result->npoints+subexploded->npoints-1)); if ( ! result ) - elog(ERROR, "Out of virtual memory"); + lwerror("Out of virtual memory"); #ifdef DEBUG - elog(NOTICE, "repalloc'ed exploded->points"); + lwnotice("lwrealloc'ed exploded->points"); #endif memcpy(&(result->points[result->npoints]), @@ -3052,19 +2049,19 @@ elog(NOTICE, "lwgeom_explode: it's a polygon"); subexploded->npoints*sizeof(char *)); #ifdef DEBUG - elog(NOTICE, "memcpied exploded->points"); + lwnotice("memcpied exploded->points"); #endif result->npoints += subexploded->npoints; #ifdef DEBUG - elog(NOTICE, "memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints); + lwnotice("memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints); #endif } if ( subexploded->nlines ) { - result->lines = repalloc(result->lines, + result->lines = lwrealloc(result->lines, sizeof(char *)* (result->nlines+subexploded->nlines-1)); @@ -3077,7 +2074,7 @@ elog(NOTICE, "lwgeom_explode: it's a polygon"); if ( subexploded->npolys ) { - result->polys = repalloc(result->polys, + result->polys = lwrealloc(result->polys, sizeof(char *)* (result->npolys+subexploded->npolys-1)); @@ -3096,13 +2093,13 @@ elog(NOTICE, "lwgeom_explode: it's a polygon"); pfree_inspected(inspected); #ifdef DEBUG -elog(NOTICE, "lwgeom_explode: returning"); +lwnotice("lwgeom_explode: returning"); #endif return result; } -// Returns a 'palloced' union of the two input exploded geoms +// Returns a 'lwalloced' union of the two input exploded geoms // Returns NULL if SRID or ndims do not match. LWGEOM_EXPLODED * lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) @@ -3113,11 +2110,11 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) if ( exp1->ndims != exp2->ndims ) return NULL; if ( exp1->SRID != exp2->SRID ) return NULL; - expcoll = palloc(sizeof(LWGEOM_EXPLODED)); + expcoll = lwalloc(sizeof(LWGEOM_EXPLODED)); expcoll->npoints = exp1->npoints + exp2->npoints; if ( expcoll->npoints ) { - expcoll->points = (char **)palloc(expcoll->npoints*sizeof(char *)); + expcoll->points = (char **)lwalloc(expcoll->npoints*sizeof(char *)); loc = (char *)&(expcoll->points[0]); if ( exp1->npoints ) { memcpy(loc, exp1->points, @@ -3132,7 +2129,7 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) expcoll->nlines = exp1->nlines + exp2->nlines; if ( expcoll->nlines ) { - expcoll->lines = palloc(expcoll->nlines*sizeof(char *)); + expcoll->lines = lwalloc(expcoll->nlines*sizeof(char *)); loc = (char *)&(expcoll->lines[0]); if ( exp1->nlines ) { memcpy(loc, exp1->lines, @@ -3147,7 +2144,7 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) expcoll->npolys = exp1->npolys + exp2->npolys; if ( expcoll->npolys ) { - expcoll->polys = palloc(expcoll->npolys*sizeof(char *)); + expcoll->polys = lwalloc(expcoll->npolys*sizeof(char *)); loc = (char *)&(expcoll->polys[0]); if ( exp1->npolys ) { memcpy(loc, exp1->polys, @@ -3174,10 +2171,10 @@ lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox) { int sizecom = 0; int size = lwexploded_findlength(exploded, wantbbox); - char *result = palloc(size); + char *result = lwalloc(size); lwexploded_serialize_buf(exploded, wantbbox, result, &sizecom); #ifdef DEBUG - elog(NOTICE, "lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom); + lwnotice("lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom); #endif return result; } @@ -3291,7 +2288,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, } #ifdef DEBUG - elog(NOTICE, " computed outtype: %d, ngeoms: %d", outtype, ngeoms); + lwnotice(" computed outtype: %d, ngeoms: %d", outtype, ngeoms); #endif @@ -3346,7 +2343,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, line = lwline_deserialize(exploded->lines[i]); if ( line == NULL ) { - elog(ERROR, "Error deserializing %dnt line from exploded geom", i); + lwerror("Error deserializing %dnt line from exploded geom", i); return; } line->SRID = -1; @@ -3371,7 +2368,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, poly = lwpoly_deserialize(exploded->polys[i]); if ( poly == NULL ) { - elog(ERROR, "Error deserializing %dnt polygon from exploded geom", i); + lwerror("Error deserializing %dnt polygon from exploded geom", i); return; } poly->SRID = -1; @@ -3403,20 +2400,20 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, } #ifdef DEBUG - elog(NOTICE, "lwexploded_serialize finished"); - elog(NOTICE, " type: %d", lwgeom_getType(buf[0])); - elog(NOTICE, " SRID: %d", lwgeom_getsrid(buf)); + lwnotice("lwexploded_serialize finished"); + lwnotice(" type: %d", lwgeom_getType(buf[0])); + lwnotice(" SRID: %d", lwgeom_getsrid(buf)); if ( lwgeom_hasBBOX(buf[0]) ) { { BOX2DFLOAT4 boxbuf; getbox2d_p(buf, &boxbuf); - elog(NOTICE, " BBOX: %f,%f %f,%f", + lwnotice(" BBOX: %f,%f %f,%f", boxbuf.xmin, boxbuf.ymin, boxbuf.xmax, boxbuf.ymax); } } - elog(NOTICE, " numgeoms: %d", lwgeom_getnumgeometries(buf)); + lwnotice(" numgeoms: %d", lwgeom_getnumgeometries(buf)); #endif return; @@ -3426,7 +2423,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, void checkexplodedsize(char *srl, LWGEOM_EXPLODED *exp, int alloced, char wantbbox) { - elog(NOTICE, "exploded len: serialized:%d computed:%d alloced:%d", + lwnotice("exploded len: serialized:%d computed:%d alloced:%d", lwgeom_size(srl), lwexploded_findlength(exp, wantbbox), alloced); } @@ -3516,7 +2513,7 @@ lwexploded_findlength(LWGEOM_EXPLODED *exploded, int wantbbox) return size; } -bool +char ptarray_isccw(const POINTARRAY *pa) { int i; @@ -3532,3 +2529,4 @@ ptarray_isccw(const POINTARRAY *pa) if ( area > 0 ) return 0; else return 1; } + diff --git a/lwgeom/lwgeom_box.c b/lwgeom/lwgeom_box.c new file mode 100644 index 000000000..ffc8ae29d --- /dev/null +++ b/lwgeom/lwgeom_box.c @@ -0,0 +1,56 @@ +#include "postgres.h" +#include "utils/geo_decls.h" + +#include "lwgeom_pg.h" +#include "liblwgeom.h" + + + +//convert postgresql BOX to BOX2D +BOX2DFLOAT4 * +box_to_box2df(BOX *box) +{ + BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4)); + + if (box == NULL) + return result; + + result->xmin = nextDown_f(box->low.x); + result->ymin = nextDown_f(box->low.y); + + result->xmax = nextUp_f(box->high.x); + result->ymax = nextUp_f(box->high.x); + + return result; +} + +// convert BOX2D to postgresql BOX +BOX box2df_to_box(BOX2DFLOAT4 *box) +{ + BOX result; + + if (box == NULL) + return result; + + result.low.x = nextDown_d(box->xmin); + result.low.y = nextDown_d(box->ymin); + + result.high.x = nextUp_d(box->xmax); + result.high.y = nextUp_d(box->ymax); + + return result; +} + +// convert BOX2D to postgresql BOX +void +box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out) +{ + if (box == NULL) return; + + out->low.x = nextDown_d(box->xmin); + out->low.y = nextDown_d(box->ymin); + + out->high.x = nextUp_d(box->xmax); + out->high.y = nextUp_d(box->ymax); +} + diff --git a/lwgeom/lwgeom_box2dfloat4.c b/lwgeom/lwgeom_box2dfloat4.c index 5f2a1be86..48ba0ed7c 100644 --- a/lwgeom/lwgeom_box2dfloat4.c +++ b/lwgeom/lwgeom_box2dfloat4.c @@ -1,20 +1,19 @@ -#include "postgres.h" - #include #include #include #include #include +#include "postgres.h" #include "access/gist.h" #include "access/itup.h" #include "access/rtree.h" - #include "fmgr.h" #include "utils/elog.h" +#include "utils/geo_decls.h" - -#include "lwgeom.h" +#include "lwgeom_pg.h" +#include "liblwgeom.h" #include "stringBuffer.h" diff --git a/lwgeom/lwgeom_box3d.c b/lwgeom/lwgeom_box3d.c index 3d136843e..60c461d58 100644 --- a/lwgeom/lwgeom_box3d.c +++ b/lwgeom/lwgeom_box3d.c @@ -4,18 +4,19 @@ * **********************************************************************/ -#include "postgres.h" - #include #include #include #include #include +#include "postgres.h" #include "fmgr.h" #include "utils/elog.h" +#include "utils/geo_decls.h" -#include "lwgeom.h" +#include "lwgeom_pg.h" +#include "liblwgeom.h" //#define DEBUG diff --git a/lwgeom/lwgeom_btree.c b/lwgeom/lwgeom_btree.c index 0a582b8f4..fe962ff74 100644 --- a/lwgeom/lwgeom_btree.c +++ b/lwgeom/lwgeom_btree.c @@ -15,8 +15,10 @@ #include "postgres.h" #include "fmgr.h" +#include "utils/geo_decls.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" Datum lwgeom_lt(PG_FUNCTION_ARGS); Datum lwgeom_le(PG_FUNCTION_ARGS); @@ -447,6 +449,13 @@ Datum lwgeom_cmp(PG_FUNCTION_ARGS) /*********************************************************** * * $Log$ + * Revision 1.5 2004/09/29 10:50:30 strk + * Big layout change. + * lwgeom.h is public API + * liblwgeom.h is private header + * lwgeom_pg.h is for PG-links + * lw.c contains type-specific functions + * * Revision 1.4 2004/09/29 06:31:42 strk * Changed LWGEOM to PG_LWGEOM. * Changed LWGEOM_construct to PG_LWGEOM_construct. diff --git a/lwgeom/lwgeom_chip.c b/lwgeom/lwgeom_chip.c index 9d543929d..9fbaa4043 100644 --- a/lwgeom/lwgeom_chip.c +++ b/lwgeom/lwgeom_chip.c @@ -1,4 +1,3 @@ - #include #include #include @@ -12,7 +11,8 @@ #include "fmgr.h" #include "utils/elog.h" -#include "lwgeom.h" +#include "lwgeom_pg.h" +#include "liblwgeom.h" // External functions (what's again the reason for using explicit hex form ?) extern void deparse_hex(unsigned char str, unsigned char *result); diff --git a/lwgeom/lwgeom_estimate.c b/lwgeom/lwgeom_estimate.c index 4de2bab00..4f5f32e4d 100644 --- a/lwgeom/lwgeom_estimate.c +++ b/lwgeom/lwgeom_estimate.c @@ -10,6 +10,13 @@ * ********************************************************************** * $Log$ + * Revision 1.7 2004/09/29 10:50:30 strk + * Big layout change. + * lwgeom.h is public API + * liblwgeom.h is private header + * lwgeom_pg.h is for PG-links + * lw.c contains type-specific functions + * * Revision 1.6 2004/09/27 08:26:03 strk * Debugging defines set to NODEBUG. * @@ -28,8 +35,6 @@ * **********************************************************************/ -#include "postgres.h" - #include #include #include @@ -37,12 +42,14 @@ #include #include +#include "postgres.h" +#include "utils/geo_decls.h" #include "executor/spi.h" #include "fmgr.h" - #include "parser/parsetree.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" #if USE_VERSION >= 80 diff --git a/lwgeom/lwgeom_functions_analytic.c b/lwgeom/lwgeom_functions_analytic.c index 23d9418ca..d9adc1531 100644 --- a/lwgeom/lwgeom_functions_analytic.c +++ b/lwgeom/lwgeom_functions_analytic.c @@ -1,5 +1,7 @@ #include "postgres.h" -#include "lwgeom.h" +#include "fmgr.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" /*********************************************************************** * Simple Douglas-Peucker line simplification. diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 72fe7a508..fb993fb30 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -1,16 +1,17 @@ -#include "postgres.h" - #include #include #include #include #include +#include "postgres.h" #include "fmgr.h" #include "utils/elog.h" #include "utils/array.h" +#include "utils/geo_decls.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" #include "profile.h" //#define DEBUG diff --git a/lwgeom/lwgeom_geos.c b/lwgeom/lwgeom_geos.c index cce20d8f9..f963c05aa 100644 --- a/lwgeom/lwgeom_geos.c +++ b/lwgeom/lwgeom_geos.c @@ -2,8 +2,10 @@ #include "postgres.h" #include "utils/array.h" #include "utils/builtins.h" +#include "fmgr.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" #include "profile.h" #include "wktparse.h" diff --git a/lwgeom/lwgeom_gist.c b/lwgeom/lwgeom_gist.c index d7d6a4ef2..349a12517 100644 --- a/lwgeom/lwgeom_gist.c +++ b/lwgeom/lwgeom_gist.c @@ -1,19 +1,18 @@ -#include "postgres.h" - #include #include #include #include #include +#include "postgres.h" #include "access/gist.h" #include "access/itup.h" #include "access/rtree.h" - #include "fmgr.h" #include "utils/elog.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" #include "stringBuffer.h" // implementation GiST support and basic LWGEOM operations (like &&) diff --git a/lwgeom/lwgeom_gml.c b/lwgeom/lwgeom_gml.c index 9ac138d0d..1a34bba75 100644 --- a/lwgeom/lwgeom_gml.c +++ b/lwgeom/lwgeom_gml.c @@ -17,7 +17,9 @@ #include "postgres.h" #include "executor/spi.h" -#include "lwgeom.h" + +#include "lwgeom_pg.h" +#include "liblwgeom.h" Datum LWGEOM_asGML(PG_FUNCTION_ARGS); char *geometry_to_gml(char *lwgeom, char *srs); @@ -513,6 +515,13 @@ getSRSbySRID(int SRID) /********************************************************************** * $Log$ + * Revision 1.4 2004/09/29 10:50:30 strk + * Big layout change. + * lwgeom.h is public API + * liblwgeom.h is private header + * lwgeom_pg.h is for PG-links + * lw.c contains type-specific functions + * * Revision 1.3 2004/09/29 06:31:42 strk * Changed LWGEOM to PG_LWGEOM. * Changed LWGEOM_construct to PG_LWGEOM_construct. diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index 9445aa407..c008ae8e2 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -17,7 +17,7 @@ #endif -#include "lwgeom.h" +#include "liblwgeom.h" #include "stringBuffer.h" @@ -115,8 +115,13 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(LWGEOM_out); Datum LWGEOM_out(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result = unparse_WKB(lwgeom,palloc_fn,free_fn); + char *lwgeom; + char *result; + + init_pg_func(); + + lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + result = unparse_WKB(lwgeom,lwalloc,lwfree); PG_RETURN_CSTRING(result); } @@ -181,7 +186,7 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS) pfree(wkb_srid_hexized); #ifdef DEBUG - elog(NOTICE, "LWGEOMFromWKB returning %s", unparse_WKB(lwgeom, palloc_fn, free_fn)); + elog(NOTICE, "LWGEOMFromWKB returning %s", unparse_WKB(lwgeom, pg_alloc, pg_free)); #endif PG_RETURN_POINTER(lwgeom); @@ -192,10 +197,8 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(WKBFromLWGEOM); Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) { - char *lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - - // SRID=#; - char *hexized_wkb_srid = unparse_WKB(lwgeom_input, palloc_fn, free_fn); + char *lwgeom_input; // SRID=#; + char *hexized_wkb_srid; char *hexized_wkb; // hexized_wkb_srid w/o srid char *result; //wkb int len_hexized_wkb; @@ -203,6 +206,11 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) char *semicolonLoc; int t; + init_pg_func(); + + lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + hexized_wkb_srid = unparse_WKB(lwgeom_input, lwalloc, lwfree); + //elog(NOTICE, "in WKBFromLWGEOM with WKB = '%s'", hexized_wkb_srid); hexized_wkb = hexized_wkb_srid; @@ -535,6 +543,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS) int wkt_size ; + init_pg_func(); wkt_size = (*(int*) wkt_input) -4; // actual letters @@ -546,8 +555,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS) //elog(NOTICE,"in parse_WKT_lwgeom"); //elog(NOTICE,"in parse_WKT_lwgeom with input: '%s'",wkt); - //serialized_form = parse_WKT((const char *)wkt,(allocator) malloc, (report_error)elog_ERROR); - serialized_form = parse_lwg((const char *)wkt,(allocator) palloc_fn, (report_error)elog_ERROR); + serialized_form = parse_lwg((const char *)wkt, (allocator)lwalloc, (report_error)elog_ERROR); //elog(NOTICE,"parse_WKT_lwgeom:: finished parse"); pfree (wkt); @@ -571,7 +579,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS) char *parse_lwgeom_wkt(char *wkt_input) { - char *serialized_form = parse_lwg((const char *)wkt_input,(allocator) palloc_fn, (report_error)elog_ERROR); + char *serialized_form = parse_lwg((const char *)wkt_input,(allocator)pg_alloc, (report_error)elog_ERROR); #ifdef DEBUG @@ -622,7 +630,7 @@ Datum LWGEOM_recv(PG_FUNCTION_ARGS) #endif #ifdef DEBUG - elog(NOTICE, "LWGEOMFromWKB returned %s", unparse_WKB(result,palloc_fn,free_fn)); + elog(NOTICE, "LWGEOMFromWKB returned %s", unparse_WKB(result,pg_alloc,pg_free)); #endif diff --git a/lwgeom/lwgeom_ogc.c b/lwgeom/lwgeom_ogc.c index 23f8eb143..1afb6fa58 100644 --- a/lwgeom/lwgeom_ogc.c +++ b/lwgeom/lwgeom_ogc.c @@ -13,8 +13,7 @@ #include "fmgr.h" #include "utils/elog.h" - -#include "lwgeom.h" +#include "liblwgeom.h" #include "lwgeom_pg.h" @@ -95,12 +94,18 @@ Datum LWGEOM_setSRID(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(LWGEOM_getTYPE); Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS) { - PG_LWGEOM *lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *text_ob = palloc(20+4); - char *result = text_ob+4; + PG_LWGEOM *lwgeom; + char *text_ob; + char *result; int32 size; unsigned char type; + init_pg_func(); + + lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + text_ob = lwalloc(20+4); + result = text_ob+4; + //type = lwgeom_getType(*(lwgeom+4)); type = lwgeom_getType(lwgeom->type); @@ -706,10 +711,15 @@ Datum LWGEOM_from_text(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(LWGEOM_asText); Datum LWGEOM_asText(PG_FUNCTION_ARGS) { - char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - char *result_cstring = unparse_WKT(lwgeom,palloc_fn,free_fn); + char *lwgeom; + char *result_cstring; int len; + init_pg_func(); + + lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + result_cstring = unparse_WKT(lwgeom,lwalloc,lwfree); + char *result,*loc_wkt; char *semicolonLoc; diff --git a/lwgeom/lwgeom_pg.c b/lwgeom/lwgeom_pg.c index 792a7ab15..f5306398e 100644 --- a/lwgeom/lwgeom_pg.c +++ b/lwgeom/lwgeom_pg.c @@ -1,6 +1,12 @@ +#include +#include +#include #include "postgres.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" -void *palloc_fn(size_t size) +void * +pg_alloc(size_t size) { void * result; result = palloc(size); @@ -8,8 +14,70 @@ void *palloc_fn(size_t size) return result; } -void free_fn(void *ptr) +void * +pg_realloc(void *mem, size_t size) +{ + void * result; + result = repalloc(mem, size); + return result; +} + +void +pg_free(void *ptr) { - //elog(NOTICE," pfree(%p)", ptr); pfree(ptr); } + +void +pg_error(const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start (ap, fmt); + + /* + * This is a GNU extension. + * Dunno how to handle errors here. + */ + if (!vasprintf (&msg, fmt, ap)) + { + va_end (ap); + return; + } + va_end(ap); + elog(ERROR, "%s", msg); + free(msg); +} + +void +pg_notice(const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start (ap, fmt); + + /* + * This is a GNU extension. + * Dunno how to handle errors here. + */ + if (!vasprintf (&msg, fmt, ap)) + { + va_end (ap); + return; + } + va_end(ap); + elog(NOTICE, "%s", msg); + free(msg); +} + +void +init_pg_func() +{ + lwalloc = pg_alloc; + lwrealloc = pg_realloc; + lwfree = pg_free; + lwerror = pg_error; + lwnotice = pg_notice; +} diff --git a/lwgeom/lwgeom_pg.h b/lwgeom/lwgeom_pg.h index b95e7382f..8f04f47aa 100644 --- a/lwgeom/lwgeom_pg.h +++ b/lwgeom/lwgeom_pg.h @@ -1,3 +1,43 @@ -void *palloc_fn(size_t size); -void free_fn(void *ptr); +#ifndef _LWGEOM_PG_H +#define _LWGEOM_PG_H 1 +#include "postgres.h" +#include "utils/geo_decls.h" +#include "fmgr.h" +#include "liblwgeom.h" + +void *pg_alloc(size_t size); +void *pg_realloc(void *ptr, size_t size); +void pg_free(void *ptr); +void pg_error(const char *msg, ...); +void pg_notice(const char *msg, ...); + +// call this as first thing of any PG function +void init_pg_func(void); + +// PG-dependant +extern BOX2DFLOAT4 *box_to_box2df(BOX *box); // postgresql standard type +extern BOX box2df_to_box(BOX2DFLOAT4 *box); +extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type +// PG-exposed +Datum box2d_same(PG_FUNCTION_ARGS); +Datum box2d_overlap(PG_FUNCTION_ARGS); +Datum box2d_overleft(PG_FUNCTION_ARGS); +Datum box2d_left(PG_FUNCTION_ARGS); +Datum box2d_right(PG_FUNCTION_ARGS); +Datum box2d_overright(PG_FUNCTION_ARGS); +Datum box2d_contained(PG_FUNCTION_ARGS); +Datum box2d_contain(PG_FUNCTION_ARGS); +Datum box2d_inter(PG_FUNCTION_ARGS); +Datum box2d_union(PG_FUNCTION_ARGS); + +Datum gist_lwgeom_compress(PG_FUNCTION_ARGS); +Datum gist_lwgeom_consistent(PG_FUNCTION_ARGS); +Datum gist_rtree_decompress(PG_FUNCTION_ARGS); +Datum lwgeom_box_union(PG_FUNCTION_ARGS); +Datum lwgeom_box_penalty(PG_FUNCTION_ARGS); +Datum lwgeom_gbox_same(PG_FUNCTION_ARGS); +Datum lwgeom_gbox_picksplit(PG_FUNCTION_ARGS); + + +#endif // !defined _LWGEOM_PG_H 1 diff --git a/lwgeom/lwgeom_spheroid.c b/lwgeom/lwgeom_spheroid.c index fe33a7438..014b6212d 100644 --- a/lwgeom/lwgeom_spheroid.c +++ b/lwgeom/lwgeom_spheroid.c @@ -28,7 +28,8 @@ #include "utils/elog.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" #define SHOW_DIGS_DOUBLE 15 #define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1) diff --git a/lwgeom/lwgeom_svg.c b/lwgeom/lwgeom_svg.c index b6a4f1a23..b676cad54 100644 --- a/lwgeom/lwgeom_svg.c +++ b/lwgeom/lwgeom_svg.c @@ -18,7 +18,8 @@ #include "postgres.h" -#include "lwgeom.h" +#include "lwgeom_pg.h" +#include "liblwgeom.h" Datum assvg_geometry(PG_FUNCTION_ARGS); char *geometry_to_svg(PG_LWGEOM *geometry, int svgrel, int precision); @@ -251,6 +252,13 @@ print_svg_path_rel(char *result, POINTARRAY *pa, int precision) /********************************************************************** * $Log$ + * Revision 1.3 2004/09/29 10:50:30 strk + * Big layout change. + * lwgeom.h is public API + * liblwgeom.h is private header + * lwgeom_pg.h is for PG-links + * lw.c contains type-specific functions + * * Revision 1.2 2004/09/29 06:31:42 strk * Changed LWGEOM to PG_LWGEOM. * Changed LWGEOM_construct to PG_LWGEOM_construct. diff --git a/lwgeom/lwgeom_transform.c b/lwgeom/lwgeom_transform.c index 78443ee39..49700256a 100644 --- a/lwgeom/lwgeom_transform.c +++ b/lwgeom/lwgeom_transform.c @@ -8,7 +8,8 @@ #include "postgres.h" #include "fmgr.h" -#include "lwgeom.h" +#include "liblwgeom.h" +#include "lwgeom_pg.h" Datum transform_geom(PG_FUNCTION_ARGS); Datum postgis_proj_version(PG_FUNCTION_ARGS); diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c new file mode 100644 index 000000000..d5dd49c05 --- /dev/null +++ b/lwgeom/lwline.c @@ -0,0 +1,323 @@ +// basic LWLINE functions + +#include +#include +#include +#include "liblwgeom.h" + +// construct a new LWLINE. points will *NOT* be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points) +{ + LWLINE *result; + result = (LWLINE*) lwalloc( sizeof(LWLINE)); + + result->ndims =ndims; + result->SRID = SRID; + result->points = points; + + return result; +} + +// given the LWGEOM serialized form (or a pointer into a muli* one) +// construct a proper LWLINE. +// serialized_form should point to the 8bit type format (with type = 2) +// See serialized form doc +LWLINE *lwline_deserialize(char *serialized_form) +{ + unsigned char type; + LWLINE *result; + char *loc =NULL; + uint32 npoints; + POINTARRAY *pa; + + result = (LWLINE*) lwalloc(sizeof(LWLINE)) ; + + type = (unsigned char) serialized_form[0]; + if ( lwgeom_getType(type) != LINETYPE) + { + lwerror("lwline_deserialize: attempt to deserialize a line when its not really a line"); + return NULL; + } + + loc = serialized_form+1; + + if (lwgeom_hasBBOX(type)) + { + //lwnotice("line has bbox"); + loc += sizeof(BOX2DFLOAT4); + } + else + { + //lwnotice("line has NO bbox"); + } + + if ( lwgeom_hasSRID(type)) + { + //lwnotice("line has srid"); + result->SRID = get_int32(loc); + loc +=4; // type + SRID + } + else + { + //lwnotice("line has NO srid"); + result->SRID = -1; + } + + // we've read the type (1 byte) and SRID (4 bytes, if present) + + npoints = get_uint32(loc); + //lwnotice("line npoints = %d", npoints); + loc +=4; + pa = pointArray_construct( loc, lwgeom_ndims(type), npoints); + + result->points = pa; + result->ndims = lwgeom_ndims(type); + + return result; +} + +// convert this line into its serialize form +// result's first char will be the 8bit type. See serialized form doc +char *lwline_serialize(LWLINE *line) +{ + int size=1; // type byte + char hasSRID; + unsigned char * result; + int t; + char *loc; + +if (line == NULL) + lwerror("lwline_serialize:: given null line"); + + hasSRID = (line->SRID != -1); + + if (hasSRID) + size +=4; //4 byte SRID + + if (line->ndims == 3) + { + size += 24 * line->points->npoints; //x,y,z + } + else if (line->ndims == 2) + { + size += 16 * line->points->npoints; //x,y + } + else if (line->ndims == 4) + { + size += 32 * line->points->npoints; //x,y + } + + + size+=4; // npoints + + result = lwalloc(size); + + result[0] = (unsigned char) lwgeom_makeType(line->ndims,hasSRID, LINETYPE); + loc = result+1; + + if (hasSRID) + { + memcpy(loc, &line->SRID, sizeof(int32)); + loc += 4; + } + + memcpy(loc, &line->points->npoints, sizeof(int32)); + loc +=4; + //copy in points + +//lwnotice(" line serialize - size = %i", size); + + if (line->ndims == 3) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint3d_p(line->points, t, loc); + loc += 24; // size of a 3d point + } + } + else if (line->ndims == 2) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint2d_p(line->points, t, loc); + loc += 16; // size of a 2d point + } + } + else if (line->ndims == 4) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint4d_p(line->points, t, loc); + loc += 32; // size of a 2d point + } + } + //printBYTES((unsigned char *)result, size); + return result; +} + +// convert this line into its serialize form writing it into +// the given buffer, and returning number of bytes written into +// the given int pointer. +// result's first char will be the 8bit type. See serialized form doc +void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize) +{ + int size=1; // type byte + char hasSRID; + int t; + char *loc; + + if (line == NULL) + lwerror("lwline_serialize:: given null line"); + + hasSRID = (line->SRID != -1); + + if (hasSRID) size +=4; //4 byte SRID + + if (line->ndims == 3) + { + size += 24 * line->points->npoints; //x,y,z + } + else if (line->ndims == 2) + { + size += 16 * line->points->npoints; //x,y + } + else if (line->ndims == 4) + { + size += 32 * line->points->npoints; //x,y + } + + size+=4; // npoints + + buf[0] = (unsigned char) lwgeom_makeType(line->ndims, + hasSRID, LINETYPE); + loc = buf+1; + + if (hasSRID) + { + memcpy(loc, &line->SRID, sizeof(int32)); + loc += 4; + } + + memcpy(loc, &line->points->npoints, sizeof(int32)); + loc +=4; + //copy in points + +//lwnotice(" line serialize - size = %i", size); + + if (line->ndims == 3) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint3d_p(line->points, t, loc); + loc += 24; // size of a 3d point + } + } + else if (line->ndims == 2) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint2d_p(line->points, t, loc); + loc += 16; // size of a 2d point + } + } + else if (line->ndims == 4) + { + for (t=0; t< line->points->npoints;t++) + { + getPoint4d_p(line->points, t, loc); + loc += 32; // size of a 2d point + } + } + //printBYTES((unsigned char *)result, size); + + if (retsize) *retsize = size; +} + +// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) +BOX3D *lwline_findbbox(LWLINE *line) +{ + BOX3D *ret; + + if (line == NULL) + return NULL; + + ret = pointArray_bbox(line->points); + return ret; +} + +// find length of this deserialized line +uint32 +lwline_size(LWLINE *line) +{ + uint32 size = 1; //type + + if ( line->SRID != -1 ) size += 4; // SRID + size += sizeof(double)*line->ndims*line->points->npoints; // points + + return size; +} + +void pfree_line (LWLINE *line) +{ + lwfree(line->points); + lwfree(line); +} + +// find length of this serialized line +uint32 +lwgeom_size_line(const char *serialized_line) +{ + int type = (unsigned char) serialized_line[0]; + uint32 result =1; //type + const char *loc; + uint32 npoints; + + if ( lwgeom_getType(type) != LINETYPE) + lwerror("lwgeom_size_line::attempt to find the length of a non-line"); + + + loc = serialized_line+1; + + if (lwgeom_hasBBOX(type)) + { + loc += sizeof(BOX2DFLOAT4); + result +=sizeof(BOX2DFLOAT4); + } + + if ( lwgeom_hasSRID(type)) + { + loc += 4; // type + SRID + result +=4; + } + + // we've read the type (1 byte) and SRID (4 bytes, if present) + + npoints = get_uint32(loc); + result += 4; //npoints + + if (lwgeom_ndims(type) ==3) + { + return result + npoints * 24; + } + else if (lwgeom_ndims(type) ==2) + { + return result+ npoints * 16; + } + else if (lwgeom_ndims(type) ==4) + { + return result+ npoints * 32; + } + lwerror("lwgeom_size_line :: invalid ndims"); + return 0; //never get here +} + +void printLWLINE(LWLINE *line) +{ + lwnotice("LWLINE {"); + lwnotice(" ndims = %i", (int)line->ndims); + lwnotice(" SRID = %i", (int)line->SRID); + printPA(line->points); + lwnotice("}"); +} + diff --git a/lwgeom/lwmline.c b/lwgeom/lwmline.c new file mode 100644 index 000000000..c4cfd85e9 --- /dev/null +++ b/lwgeom/lwmline.c @@ -0,0 +1,41 @@ +#include +#include +#include "liblwgeom.h" + +LWMLINE * +lwmline_deserialize(char *srl) +{ + LWMLINE *result; + LWGEOM_INSPECTED *insp; + int type = lwgeom_getType(srl[0]); + int i; + + if ( type != MULTILINETYPE ) + { + lwerror("lwmline_deserialize called on NON multiline: %d", + type); + return NULL; + } + + insp = lwgeom_inspect(srl); + + result = lwalloc(sizeof(LWMLINE)); + result->SRID = insp->SRID; + result->ndims = lwgeom_ndims(insp->type); + result->nlines = insp->ngeometries; + result->lines = lwalloc(sizeof(LWLINE *)*insp->ngeometries); + + for (i=0; ingeometries; i++) + { + result->lines[i] = lwline_deserialize(insp->sub_geoms[i]); + if ( result->lines[i]->ndims != result->ndims ) + { + lwerror("Mixed dimensions (multiline:%d, line%d:%d)", + result->ndims, i, result->lines[i]->ndims); + return NULL; + } + } + + return result; +} + diff --git a/lwgeom/lwmpoint.c b/lwgeom/lwmpoint.c new file mode 100644 index 000000000..945d4dd01 --- /dev/null +++ b/lwgeom/lwmpoint.c @@ -0,0 +1,41 @@ +#include +#include +#include "liblwgeom.h" + +LWMPOINT * +lwmpoint_deserialize(char *srl) +{ + LWMPOINT *result; + LWGEOM_INSPECTED *insp; + int type = lwgeom_getType(srl[0]); + int i; + + if ( type != MULTIPOINTTYPE ) + { + lwerror("lwmpoint_deserialize called on NON multipoint: %d", + type); + return NULL; + } + + insp = lwgeom_inspect(srl); + + result = lwalloc(sizeof(LWMPOINT)); + result->SRID = insp->SRID; + result->ndims = lwgeom_ndims(insp->type); + result->npoints = insp->ngeometries; + result->points = lwalloc(sizeof(LWPOINT *)*result->npoints); + + for (i=0; ingeometries; i++) + { + result->points[i] = lwpoint_deserialize(insp->sub_geoms[i]); + if ( result->points[i]->ndims != result->ndims ) + { + lwerror("Mixed dimensions (multipoint:%d, point%d:%d)", + result->ndims, i, result->points[i]->ndims); + return NULL; + } + } + + return result; +} + diff --git a/lwgeom/lwmpoly.c b/lwgeom/lwmpoly.c new file mode 100644 index 000000000..97e01c297 --- /dev/null +++ b/lwgeom/lwmpoly.c @@ -0,0 +1,41 @@ +#include +#include +#include "liblwgeom.h" + +LWMPOLY * +lwmpoly_deserialize(char *srl) +{ + LWMPOLY *result; + LWGEOM_INSPECTED *insp; + int type = lwgeom_getType(srl[0]); + int i; + + if ( type != MULTIPOLYGONTYPE ) + { + lwerror("lwmpoly_deserialize called on NON multipoly: %d", + type); + return NULL; + } + + insp = lwgeom_inspect(srl); + + result = lwalloc(sizeof(LWMPOLY)); + result->SRID = insp->SRID; + result->ndims = lwgeom_ndims(insp->type); + result->npolys = insp->ngeometries; + result->polys = lwalloc(sizeof(LWPOLY *)*insp->ngeometries); + + for (i=0; ingeometries; i++) + { + result->polys[i] = lwpoly_deserialize(insp->sub_geoms[i]); + if ( result->polys[i]->ndims != result->ndims ) + { + lwerror("Mixed dimensions (multipoly:%d, poly%d:%d)", + result->ndims, i, result->polys[i]->ndims); + return NULL; + } + } + + return result; +} + diff --git a/lwgeom/lwpoint.c b/lwgeom/lwpoint.c new file mode 100644 index 000000000..3f6ca9cec --- /dev/null +++ b/lwgeom/lwpoint.c @@ -0,0 +1,229 @@ +#include +#include +#include +#include "liblwgeom.h" + +// convert this point into its serialize form +// result's first char will be the 8bit type. See serialized form doc +char * +lwpoint_serialize(LWPOINT *point) +{ + int size=1; + char hasSRID; + char *result; + char *loc; + + hasSRID = (point->SRID != -1); + + if (hasSRID) size +=4; //4 byte SRID + + if (point->ndims == 3) size += 24; //x,y,z + else if (point->ndims == 2) size += 16 ; //x,y,z + else if (point->ndims == 4) size += 32 ; //x,y,z,m + + result = lwalloc(size); + + result[0] = (unsigned char) lwgeom_makeType(point->ndims, + hasSRID, POINTTYPE); + loc = result+1; + + if (hasSRID) + { + memcpy(loc, &point->SRID, sizeof(int32)); + loc += 4; + } + + //copy in points + + if (point->ndims == 3) getPoint3d_p(point->point, 0, loc); + else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc); + else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc); + return result; +} + +// convert this point into its serialize form writing it into +// the given buffer, and returning number of bytes written into +// the given int pointer. +// result's first char will be the 8bit type. See serialized form doc +void +lwpoint_serialize_buf(LWPOINT *point, char *buf, int *retsize) +{ + int size=1; + char hasSRID; + char *loc; + + hasSRID = (point->SRID != -1); + + if (hasSRID) size +=4; //4 byte SRID + + if (point->ndims == 3) size += 24; //x,y,z + else if (point->ndims == 2) size += 16 ; //x,y,z + else if (point->ndims == 4) size += 32 ; //x,y,z,m + + buf[0] = (unsigned char) lwgeom_makeType(point->ndims, + hasSRID, POINTTYPE); + loc = buf+1; + + if (hasSRID) + { + memcpy(loc, &point->SRID, sizeof(int32)); + loc += 4; + } + + //copy in points + + if (point->ndims == 3) getPoint3d_p(point->point, 0, loc); + else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc); + else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc); + + if (retsize) *retsize = size; +} + +// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) +BOX3D * +lwpoint_findbbox(LWPOINT *point) +{ +#ifdef DEBUG + lwnotice("lwpoint_findbbox called with point %p", point); +#endif + if (point == NULL) + { +#ifdef DEBUG + lwnotice("lwpoint_findbbox returning NULL"); +#endif + return NULL; + } + +#ifdef DEBUG + lwnotice("lwpoint_findbbox returning pointArray_bbox return"); +#endif + + return pointArray_bbox(point->point); +} + +// convenience functions to hide the POINTARRAY +// TODO: obsolete this +POINT2D +lwpoint_getPoint2d(const LWPOINT *point) +{ + POINT2D result; + + if (point == NULL) + return result; + + return getPoint2d(point->point,0); +} + +// convenience functions to hide the POINTARRAY +POINT3D +lwpoint_getPoint3d(const LWPOINT *point) +{ + POINT3D result; + + if (point == NULL) + return result; + + return getPoint3d(point->point,0); +} + +// find length of this deserialized point +uint32 +lwpoint_size(LWPOINT *point) +{ + uint32 size = 1; // type + + if ( point->SRID != -1 ) size += 4; // SRID + size += point->ndims * sizeof(double); // point + + return size; +} + +// construct a new point. point will not be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +LWPOINT * +lwpoint_construct(int ndims, int SRID, POINTARRAY *point) +{ + LWPOINT *result ; + + if (point == NULL) + return NULL; // error + + result = lwalloc(sizeof(LWPOINT)); + result->ndims = ndims; + result->SRID = SRID; + + result->point = point; + + return result; +} + +// given the LWPOINT serialized form (or a pointer into a muli* one) +// construct a proper LWPOINT. +// serialized_form should point to the 8bit type format (with type = 1) +// See serialized form doc +LWPOINT * +lwpoint_deserialize(char *serialized_form) +{ + unsigned char type; + LWPOINT *result; + char *loc = NULL; + POINTARRAY *pa; + +#ifdef DEBUG + lwnotice("lwpoint_deserialize called"); +#endif + + result = (LWPOINT*) lwalloc(sizeof(LWPOINT)) ; + + type = (unsigned char) serialized_form[0]; + + if ( lwgeom_getType(type) != POINTTYPE) return NULL; + + loc = serialized_form+1; + + if (lwgeom_hasBBOX(type)) + { +#ifdef DEBUG + lwnotice("lwpoint_deserialize: input has bbox"); +#endif + loc += sizeof(BOX2DFLOAT4); + } + + if ( lwgeom_hasSRID(type)) + { +#ifdef DEBUG + lwnotice("lwpoint_deserialize: input has SRID"); +#endif + result->SRID = get_int32(loc); + loc += 4; // type + SRID + } + else + { + result->SRID = -1; + } + + // we've read the type (1 byte) and SRID (4 bytes, if present) + + pa = pointArray_construct(loc, lwgeom_ndims(type), 1); + + result->point = pa; + result->ndims = lwgeom_ndims(type); + + return result; +} + +void pfree_point (LWPOINT *pt) +{ + pfree_POINTARRAY(pt->point); + lwfree(pt); +} + +void printLWPOINT(LWPOINT *point) +{ + lwnotice("LWPOINT {"); + lwnotice(" ndims = %i", (int)point->ndims); + lwnotice(" SRID = %i", (int)point->SRID); + printPA(point->point); + lwnotice("}"); +} + diff --git a/lwgeom/lwpoly.c b/lwgeom/lwpoly.c new file mode 100644 index 000000000..e34549074 --- /dev/null +++ b/lwgeom/lwpoly.c @@ -0,0 +1,414 @@ +// basic LWPOLY manipulation + +#include +#include +#include +#include "liblwgeom.h" + +// construct a new LWPOLY. arrays (points/points per ring) will NOT be copied +// use SRID=-1 for unknown SRID (will have 8bit type's S = 0) +LWPOLY * +lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points) +{ + LWPOLY *result; + + result = (LWPOLY*) lwalloc(sizeof(LWPOLY)); + result->ndims = ndims; + result->SRID = SRID; + result->nrings = nrings; + result->rings = points; + + return result; +} + + +// given the LWPOLY serialized form (or a pointer into a muli* one) +// construct a proper LWPOLY. +// serialized_form should point to the 8bit type format (with type = 3) +// See serialized form doc +LWPOLY * +lwpoly_deserialize(char *serialized_form) +{ + + LWPOLY *result; + uint32 nrings; + int ndims; + uint32 npoints; + unsigned char type; + char *loc; + int t; + + if (serialized_form == NULL) + { + lwerror("lwpoly_deserialize called with NULL arg"); + return NULL; + } + + result = (LWPOLY*) lwalloc(sizeof(LWPOLY)); + + + type = (unsigned char) serialized_form[0]; + ndims = lwgeom_ndims(type); + loc = serialized_form; + + if ( lwgeom_getType(type) != POLYGONTYPE) + { + lwerror("lwpoly_deserialize called with arg of type %d", + lwgeom_getType(type)); + return NULL; + } + + + loc = serialized_form+1; + + if (lwgeom_hasBBOX(type)) + { + loc += sizeof(BOX2DFLOAT4); + } + + if ( lwgeom_hasSRID(type)) + { + result->SRID = get_int32(loc); + loc +=4; // type + SRID + } + else + { + result->SRID = -1; + } + + nrings = get_uint32(loc); + result->nrings = nrings; + loc +=4; + result->rings = (POINTARRAY**) lwalloc(nrings* sizeof(POINTARRAY*)); + + for (t =0;trings[t] = pointArray_construct(loc, ndims, npoints); + if (ndims == 3) + loc += 24*npoints; + else if (ndims == 2) + loc += 16*npoints; + else if (ndims == 4) + loc += 32*npoints; + } + result->ndims = ndims; + + return result; +} + +// create the serialized form of the polygon +// result's first char will be the 8bit type. See serialized form doc +// points copied +char * +lwpoly_serialize(LWPOLY *poly) +{ + int size=1; // type byte + char hasSRID; + char *result; + int t,u; + int total_points = 0; + int npoints; + char *loc; + + hasSRID = (poly->SRID != -1); + + if (hasSRID) + size +=4; //4 byte SRID + + size += 4; // nrings + size += 4*poly->nrings; //npoints/ring + + + for (t=0;tnrings;t++) + { + total_points += poly->rings[t]->npoints; + } + if (poly->ndims == 3) + size += 24*total_points; + else if (poly->ndims == 2) + size += 16*total_points; + else if (poly->ndims == 4) + size += 32*total_points; + + result = lwalloc(size); + + result[0] = (unsigned char) lwgeom_makeType(poly->ndims,hasSRID, POLYGONTYPE); + loc = result+1; + + if (hasSRID) + { + memcpy(loc, &poly->SRID, sizeof(int32)); + loc += 4; + } + + memcpy(loc, &poly->nrings, sizeof(int32)); // nrings + loc+=4; + + + + for (t=0;tnrings;t++) + { + POINTARRAY *pa = poly->rings[t]; + npoints = poly->rings[t]->npoints; + memcpy(loc, &npoints, sizeof(int32)); //npoints this ring + loc+=4; + if (poly->ndims == 3) + { + for (u=0;undims == 2) + { + for (u=0;undims == 4) + { + for (u=0;uSRID != -1); + + if (hasSRID) size +=4; //4 byte SRID + + size += 4; // nrings + size += 4*poly->nrings; //npoints/ring + + for (t=0;tnrings;t++) + { + total_points += poly->rings[t]->npoints; + } + if (poly->ndims == 3) size += 24*total_points; + else if (poly->ndims == 2) size += 16*total_points; + else if (poly->ndims == 4) size += 32*total_points; + + buf[0] = (unsigned char) lwgeom_makeType(poly->ndims, + hasSRID, POLYGONTYPE); + loc = buf+1; + + if (hasSRID) + { + memcpy(loc, &poly->SRID, sizeof(int32)); + loc += 4; + } + + memcpy(loc, &poly->nrings, sizeof(int32)); // nrings + loc+=4; + + for (t=0;tnrings;t++) + { + POINTARRAY *pa = poly->rings[t]; + npoints = poly->rings[t]->npoints; + memcpy(loc, &npoints, sizeof(int32)); //npoints this ring + loc+=4; + if (poly->ndims == 3) + { + for (u=0;undims == 2) + { + for (u=0;undims == 4) + { + for (u=0;urings[0]; // just need to check outer ring -- interior rings are inside + result = pointArray_bbox(pa); + +// for (t=1;tnrings;t++) + //{ +// pa = poly->rings[t]; +// abox = pointArray_bbox(pa); +// abox2 = result; +// result = combine_boxes( abox, abox2); +// lwfree(abox); +// lwfree(abox2); + // } + + return result; +} + +//find length of this serialized polygon +uint32 +lwgeom_size_poly(const char *serialized_poly) +{ + uint32 result = 1; // char type + uint32 nrings; + int ndims; + int t; + unsigned char type; + uint32 npoints; + const char *loc; + + if (serialized_poly == NULL) + return -9999; + + + type = (unsigned char) serialized_poly[0]; + ndims = lwgeom_ndims(type); + + if ( lwgeom_getType(type) != POLYGONTYPE) + return -9999; + + + loc = serialized_poly+1; + + if (lwgeom_hasBBOX(type)) + { +#ifdef DEBUG + lwnotice("lwgeom_size_poly: has bbox"); +#endif + loc += sizeof(BOX2DFLOAT4); + result +=sizeof(BOX2DFLOAT4); + } + + + if ( lwgeom_hasSRID(type)) + { +#ifdef DEBUG + lwnotice("lwgeom_size_poly: has srid"); +#endif + loc +=4; // type + SRID + result += 4; + } + + + nrings = get_uint32(loc); + loc +=4; + result +=4; + + + for (t =0;tSRID != -1 ) size += 4; // SRID + + size += 4; // nrings + + for (i=0; inrings; i++) + { + size += 4; // npoints + size += poly->rings[i]->npoints*poly->ndims*sizeof(double); + } + + return size; +} + +void pfree_polygon (LWPOLY *poly) +{ + int t; + + for (t=0;tnrings;t++) + { + pfree_POINTARRAY(poly->rings[t]); + } + + lwfree(poly); +} + +void printLWPOLY(LWPOLY *poly) +{ + int t; + lwnotice("LWPOLY {"); + lwnotice(" ndims = %i", (int)poly->ndims); + lwnotice(" SRID = %i", (int)poly->SRID); + lwnotice(" nrings = %i", (int)poly->nrings); + for (t=0;tnrings;t++) + { + lwnotice(" RING # %i :",t); + printPA(poly->rings[t]); + } + lwnotice("}"); +} +