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
--- /dev/null
+#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:
+ // <header><data>
+ // 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::
+//<int32> size = 29 bytes
+//<char> type: S=0,D=1, tttt= 1
+//<double> X
+//<double> Y
+//<double> Z
+
+//2D line String
+//<int32> size = ...
+//<char> type: S=0,D=0, tttt= 2
+//<uint32> npoints
+//<double> X0
+//<double> Y0
+//<double> X1
+//<double> Y1
+//<double> X2
+//<double> Y2
+//...
+
+//3D polygon w/o bounding box
+//<int32> size = ...
+//<char> type: S=0,D=0, tttt= 3
+//<uint32> nrings
+//<uint32> npoints in ring0
+//<double> X0
+//<double> Y0
+//<double> X1
+//<double> Y1
+//<double> X2
+//<double> Y2
+//...
+//<uint32> npoints in ring1
+//<double> X0
+//<double> Y0
+//<double> X1
+//<double> Y1
+//<double> X2
+//<double> Y2
+//...
+//...
+
+
+// the multi* representations are very simple
+
+//<int32> size = ...
+//<char> type: ... with tttt= <multi* or geometrycollection>
+//<int32> ngeometries
+// <geometry zero, serialized form>
+// <geometry one, serialized form>
+// <geometry two, serialzied form>
+// ...
+
+
+
+// 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
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#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; i<insp->ngeometries; i++)
+ {
+ result->geoms[i] = (struct LWGEOM *)lwgeom_deserialize(insp->sub_geoms[i]);
+ }
+
+ return result;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#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);
+}
+
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)
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
typedef struct
{
- int type; // POLYGONTYPE
int32 SRID;
char ndims;
int nrings;
// 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
//
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
// 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);
-#include "postgres.h"
#include <math.h>
#include <float.h>
#include <stdio.h>
#include <errno.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"
// this will change to NaN when I figure out how to
// get NaN in a platform-independent way
#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
// 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;
}
}
// 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;
}
}
-//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
}
-// 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
{
BOX3D *result;
- result =(BOX3D*) palloc(sizeof(BOX3D));
+ result =(BOX3D*) lwalloc(sizeof(BOX3D));
if ( (b1 == NULL) && (b2 == NULL) )
{
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;
}
BOX3D *box3d;
#ifdef DEBUG
- elog(NOTICE,"getbox2d_p call");
+ lwnotice("getbox2d_p call");
#endif
loc = serialized_form+1;
{
//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 )
}
#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;
}
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);
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;
}
// 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)
{
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;
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;t<pa->npoints;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;t<pa->npoints;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;t<nrings;t++)
- {
- //read in a single ring and make a PA
- npoints = get_uint32(loc);
- loc +=4;
+//***************************************************************************
+// basic type handling
- result->rings[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;t<poly->nrings;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;t<poly->nrings;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;u<npoints;u++)
- {
- getPoint3d_p(pa, u, loc);
- loc+= 24;
- }
- }
- else if (poly->ndims == 2)
- {
- for (u=0;u<npoints;u++)
- {
- getPoint2d_p(pa, u, loc);
- loc+= 16;
- }
- }
- else if (poly->ndims == 4)
- {
- for (u=0;u<npoints;u++)
- {
- getPoint4d_p(pa, u, loc);
- loc+= 32;
- }
- }
- }
+ if (ndims == 3)
+ result = result | 0x10;
+ if (ndims == 4)
+ result = result | 0x20;
+ if (hasSRID)
+ result = result | 0x40;
+ if (hasBBOX)
+ result = result | 0x80;
return result;
}
-// create the serialized form of the polygon 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
-// points copied
-void
-lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *retsize)
+//returns true if there's a bbox in this LWGEOM (B bit set)
+char lwgeom_hasBBOX(unsigned char type)
{
- int size=1; // type byte
- char hasSRID;
- int t,u;
- int total_points = 0;
- int npoints;
- char *loc;
-
- hasSRID = (poly->SRID != -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;t<poly->nrings;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;t<poly->nrings;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;u<npoints;u++)
- {
- getPoint3d_p(pa, u, loc);
- loc+= 24;
- }
- }
- else if (poly->ndims == 2)
- {
- for (u=0;u<npoints;u++)
- {
- getPoint2d_p(pa, u, loc);
- loc+= 16;
- }
- }
- else if (poly->ndims == 4)
- {
- for (u=0;u<npoints;u++)
- {
- getPoint4d_p(pa, u, loc);
- loc+= 32;
- }
- }
- }
+//******************************************************************************
- if (retsize) *retsize = size;
-}
-// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
-BOX3D *
-lwpoly_findbbox(LWPOLY *poly)
-{
-// int t;
- BOX3D *result;
-// BOX3D *abox,*abox2;
- POINTARRAY *pa = poly->rings[0]; // just need to check outer ring -- interior rings are inside
- result = pointArray_bbox(pa);
+//********************************************************************
+// support for the LWPOINT sub-type
-// for (t=1;t<poly->nrings;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;t<nrings;t++)
+ if (lwgeom_ndims(type) == 3)
{
- //read in a single ring and make a PA
- npoints = get_uint32(loc);
- loc +=4;
- result +=4;
-
- if (ndims == 3)
- {
- loc += 24*npoints;
- result += 24*npoints;
- }
- else if (ndims == 2)
- {
- loc += 16*npoints;
- result += 16*npoints;
- }
- else if (ndims == 4)
- {
- loc += 32*npoints;
- result += 32*npoints;
- }
+#ifdef DEBUG
+lwnotice("lwgeom_size_point: returning (%d)", result+24);
+#endif
+ return result + 24;
}
- return result;
-}
-
-// find length of this deserialized polygon
-uint32
-lwpoly_size(LWPOLY *poly)
-{
- uint32 size = 1; // type
- uint32 i;
-
- if ( poly->SRID != -1 ) size += 4; // SRID
-
- size += 4; // nrings
-
- for (i=0; i<poly->nrings; 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.
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;
}
//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;
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;t<result->ngeometries; 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
}
if (nsubgeometries == 0)
return lwgeom_constructempty(SRID,ndims);
- lengths = palloc(sizeof(int32) * nsubgeometries);
+ lengths = lwalloc(sizeof(int32) * nsubgeometries);
for (t=0;t<nsubgeometries;t++)
{
total_length +=1 ; // main type;
total_length +=4 ; // nsubgeometries
- result = palloc(total_length);
+ result = lwalloc(total_length);
result[0] = (unsigned char) lwgeom_makeType( ndims, SRID != -1, type);
if (SRID != -1)
{
loc += lengths[t] ;
}
- pfree(lengths);
+ lwfree(lengths);
return result;
}
size += 5;
- result = palloc(size);
+ result = lwalloc(size);
result[0] =(unsigned char) lwgeom_makeType( ndims, SRID != -1, COLLECTIONTYPE);
if (SRID != -1)
// --> 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]);
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;
}
//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;
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);
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;
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;t<ngeoms;t++)
{
sub_size = lwgeom_size(loc);
#ifdef DEBUG
- elog(NOTICE, " subsize %d", sub_size);
+ lwnotice(" subsize %d", sub_size);
#endif
loc += sub_size;
result += sub_size;
}
#ifdef DEBUG
- elog(NOTICE, "lwgeom_size returning %d", result);
+ lwnotice("lwgeom_size returning %d", result);
#endif
return result;
}
-int
+uint32
lwgeom_size_subgeom(const char *serialized_form, int geom_number)
{
if (geom_number == -1)
//get bounding box of LWGEOM (automatically calls the sub-geometries bbox generators)
-//dont forget to pfree() result
+//dont forget to lwfree() result
BOX3D *
lw_geom_getBB(char *serialized_form)
{
return result;
}
-//dont forget to pfree() result
+//dont forget to lwfree() result
BOX3D *lw_geom_getBB_simple(char *serialized_form)
{
int type = lwgeom_getType((unsigned char) serialized_form[0]);
int sub_size;
#ifdef DEBUG
-elog(NOTICE, "lw_geom_getBB_simple called on type %d", type);
+lwnotice("lw_geom_getBB_simple called on type %d", type);
#endif
if (type == POINTTYPE)
{
LWPOINT *pt = lwpoint_deserialize(serialized_form);
#ifdef DEBUG
-elog(NOTICE, "lw_geom_getBB_simple: lwpoint deserialized");
+lwnotice("lw_geom_getBB_simple: lwpoint deserialized");
#endif
result = lwpoint_findbbox(pt);
#ifdef DEBUG
-elog(NOTICE, "lw_geom_getBB_simple: bbox found");
+lwnotice("lw_geom_getBB_simple: bbox found");
#endif
pfree_point(pt);
return result;
/*
- result = palloc(sizeof(BOX3D));
+ result = lwalloc(sizeof(BOX3D));
memcpy(result, serialized_form+1, sizeof(BOX2DFLOAT4));
memcpy(( (char *)result)+24, serialized_form+1, sizeof(BOX2DFLOAT4));
return result;
if ( ! ( type == MULTIPOINTTYPE || type == MULTILINETYPE ||
type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) )
{
- elog(NOTICE, "lw_geom_getBB_simple called on unknown type %d", type);
+ lwnotice("lw_geom_getBB_simple called on unknown type %d", type);
return NULL;
}
{
b2= result;
result = combine_boxes(b2, b1);
- pfree(b1);
- pfree(b2);
+ lwfree(b1);
+ lwfree(b2);
}
else
{
}
-//dont forget to pfree() result
+//dont forget to lwfree() result
BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected)
{
int t;
{
b1 = lw_geom_getBB_simple( inspected->sub_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
{
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;t<poly->nrings;t++)
- {
- pfree_POINTARRAY(poly->rings[t]);
- }
-
- pfree(poly);
-}
void pfree_POINTARRAY(POINTARRAY *pa)
{
- pfree(pa);
+ lwfree(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;
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; t<pa->npoints;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)
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;t<n;t++)
{
deparse_hex(a[t], buff);
- elog(NOTICE, " %i : %s", t,buff );
+ lwnotice(" %i : %s", t,buff );
}
- elog(NOTICE, " }");
+ lwnotice(" }");
}
-void printLWPOLY(LWPOLY *poly)
-{
- int t;
- elog(NOTICE,"LWPOLY {");
- elog(NOTICE," ndims = %i", (int)poly->ndims);
- elog(NOTICE," SRID = %i", (int)poly->SRID);
- elog(NOTICE," nrings = %i", (int)poly->nrings);
- for (t=0;t<poly->nrings;t++)
- {
- elog(NOTICE," RING # %i :",t);
- printPA(poly->rings[t]);
- }
- elog(NOTICE,"}");
-}
-
void
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;t<inspected->ngeometries;t++)
{
- elog(NOTICE," sub-geometry %i:", t);
+ lwnotice(" sub-geometry %i:", t);
line = NULL; point = NULL; poly = NULL;
line = lwgeom_getline_inspected(inspected,t);
}
}
- 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
// 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;
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;
size+=4; // size header
- result = palloc(size);
+ result = lwalloc(size);
result->size = size;
result->type = lwgeom_makeType_full(lwgeom_ndims(ser[0]),
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);
};
/*
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;
}
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++;
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++;
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++;
}
#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
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]),
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));
if ( subexploded->npolys )
{
- result->polys = repalloc(result->polys,
+ result->polys = lwrealloc(result->polys,
sizeof(char *)*
(result->npolys+subexploded->npolys-1));
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)
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,
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,
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,
{
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;
}
}
#ifdef DEBUG
- elog(NOTICE, " computed outtype: %d, ngeoms: %d", outtype, ngeoms);
+ lwnotice(" computed outtype: %d, ngeoms: %d", outtype, ngeoms);
#endif
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;
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;
}
#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;
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);
}
return size;
}
-bool
+char
ptarray_isccw(const POINTARRAY *pa)
{
int i;
if ( area > 0 ) return 0;
else return 1;
}
+
--- /dev/null
+#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);
+}
+
-#include "postgres.h"
-
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#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"
*
**********************************************************************/
-#include "postgres.h"
-
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#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
#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);
/***********************************************************
*
* $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<type>.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.
-
#include <math.h>
#include <float.h>
#include <string.h>
#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);
*
**********************************************************************
* $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<type>.c contains type-specific functions
+ *
* Revision 1.6 2004/09/27 08:26:03 strk
* Debugging defines set to NODEBUG.
*
*
**********************************************************************/
-#include "postgres.h"
-
#include <math.h>
#include <float.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#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
#include "postgres.h"
-#include "lwgeom.h"
+#include "fmgr.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
/***********************************************************************
* Simple Douglas-Peucker line simplification.
-#include "postgres.h"
-
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#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
#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"
-#include "postgres.h"
-
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#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 &&)
#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);
/**********************************************************************
* $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<type>.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.
#endif
-#include "lwgeom.h"
+#include "liblwgeom.h"
#include "stringBuffer.h"
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);
}
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);
PG_FUNCTION_INFO_V1(WKBFromLWGEOM);
Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
{
- char *lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
- // SRID=#;<hexized wkb>
- char *hexized_wkb_srid = unparse_WKB(lwgeom_input, palloc_fn, free_fn);
+ char *lwgeom_input; // SRID=#;<hexized wkb>
+ char *hexized_wkb_srid;
char *hexized_wkb; // hexized_wkb_srid w/o srid
char *result; //wkb
int len_hexized_wkb;
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;
int wkt_size ;
+ init_pg_func();
wkt_size = (*(int*) wkt_input) -4; // actual letters
//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);
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
#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
#include "fmgr.h"
#include "utils/elog.h"
-
-#include "lwgeom.h"
+#include "liblwgeom.h"
#include "lwgeom_pg.h"
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);
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;
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
#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);
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;
+}
-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
#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)
#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);
/**********************************************************************
* $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<type>.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.
#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);
--- /dev/null
+// basic LWLINE functions
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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("}");
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#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; i<insp->ngeometries; 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;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#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; i<insp->ngeometries; 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;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#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; i<insp->ngeometries; 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;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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("}");
+}
+
--- /dev/null
+// basic LWPOLY manipulation
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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;t<nrings;t++)
+ {
+ //read in a single ring and make a PA
+ npoints = get_uint32(loc);
+ loc +=4;
+
+ result->rings[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;t<poly->nrings;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;t<poly->nrings;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;u<npoints;u++)
+ {
+ getPoint3d_p(pa, u, loc);
+ loc+= 24;
+ }
+ }
+ else if (poly->ndims == 2)
+ {
+ for (u=0;u<npoints;u++)
+ {
+ getPoint2d_p(pa, u, loc);
+ loc+= 16;
+ }
+ }
+ else if (poly->ndims == 4)
+ {
+ for (u=0;u<npoints;u++)
+ {
+ getPoint4d_p(pa, u, loc);
+ loc+= 32;
+ }
+ }
+ }
+
+ return result;
+}
+
+// create the serialized form of the polygon 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
+// points copied
+void
+lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *retsize)
+{
+ int size=1; // type byte
+ char hasSRID;
+ 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;t<poly->nrings;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;t<poly->nrings;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;u<npoints;u++)
+ {
+ getPoint3d_p(pa, u, loc);
+ loc+= 24;
+ }
+ }
+ else if (poly->ndims == 2)
+ {
+ for (u=0;u<npoints;u++)
+ {
+ getPoint2d_p(pa, u, loc);
+ loc+= 16;
+ }
+ }
+ else if (poly->ndims == 4)
+ {
+ for (u=0;u<npoints;u++)
+ {
+ getPoint4d_p(pa, u, loc);
+ loc+= 32;
+ }
+ }
+ }
+
+ if (retsize) *retsize = size;
+}
+
+
+// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
+BOX3D *
+lwpoly_findbbox(LWPOLY *poly)
+{
+// int t;
+
+ BOX3D *result;
+// BOX3D *abox,*abox2;
+
+ POINTARRAY *pa = poly->rings[0]; // just need to check outer ring -- interior rings are inside
+ result = pointArray_bbox(pa);
+
+// for (t=1;t<poly->nrings;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;t<nrings;t++)
+ {
+ //read in a single ring and make a PA
+ npoints = get_uint32(loc);
+ loc +=4;
+ result +=4;
+
+ if (ndims == 3)
+ {
+ loc += 24*npoints;
+ result += 24*npoints;
+ }
+ else if (ndims == 2)
+ {
+ loc += 16*npoints;
+ result += 16*npoints;
+ }
+ else if (ndims == 4)
+ {
+ loc += 32*npoints;
+ result += 32*npoints;
+ }
+ }
+ return result;
+}
+
+// find length of this deserialized polygon
+uint32
+lwpoly_size(LWPOLY *poly)
+{
+ uint32 size = 1; // type
+ uint32 i;
+
+ if ( poly->SRID != -1 ) size += 4; // SRID
+
+ size += 4; // nrings
+
+ for (i=0; i<poly->nrings; 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;t<poly->nrings;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;t<poly->nrings;t++)
+ {
+ lwnotice(" RING # %i :",t);
+ printPA(poly->rings[t]);
+ }
+ lwnotice("}");
+}
+