]> granicus.if.org Git - postgis/commitdiff
Big layout change.
authorSandro Santilli <strk@keybit.net>
Wed, 29 Sep 2004 10:50:30 +0000 (10:50 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 29 Sep 2004 10:50:30 +0000 (10:50 +0000)
lwgeom.h is public API
liblwgeom.h is private header
lwgeom_pg.h is for PG-links
lw<type>.c contains type-specific functions

git-svn-id: http://svn.osgeo.org/postgis/trunk@909 b70326c6-7e19-0410-871a-916f4a2858ee

30 files changed:
lwgeom/Makefile
lwgeom/liblwgeom.h [new file with mode: 0644]
lwgeom/lwcollection.c [new file with mode: 0644]
lwgeom/lwgeom.c [new file with mode: 0644]
lwgeom/lwgeom.h
lwgeom/lwgeom_api.c
lwgeom/lwgeom_box.c [new file with mode: 0644]
lwgeom/lwgeom_box2dfloat4.c
lwgeom/lwgeom_box3d.c
lwgeom/lwgeom_btree.c
lwgeom/lwgeom_chip.c
lwgeom/lwgeom_estimate.c
lwgeom/lwgeom_functions_analytic.c
lwgeom/lwgeom_functions_basic.c
lwgeom/lwgeom_geos.c
lwgeom/lwgeom_gist.c
lwgeom/lwgeom_gml.c
lwgeom/lwgeom_inout.c
lwgeom/lwgeom_ogc.c
lwgeom/lwgeom_pg.c
lwgeom/lwgeom_pg.h
lwgeom/lwgeom_spheroid.c
lwgeom/lwgeom_svg.c
lwgeom/lwgeom_transform.c
lwgeom/lwline.c [new file with mode: 0644]
lwgeom/lwmline.c [new file with mode: 0644]
lwgeom/lwmpoint.c [new file with mode: 0644]
lwgeom/lwmpoly.c [new file with mode: 0644]
lwgeom/lwpoint.c [new file with mode: 0644]
lwgeom/lwpoly.c [new file with mode: 0644]

index 03258716d532622f9c7e9ccfa8fb6e244df9ce81..729ccefdded322b51c87d2d42ffb36a84ef3874a 100644 (file)
@@ -66,7 +66,7 @@ ifeq ($(USE_STATS),1)
        override CFLAGS += -DUSE_STATS
 endif
  
-OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o lwgeom_svg.o lwgeom_gml.o $(GEOS_WRAPPER)
+OBJS=lwgeom_pg.o lwgeom.o lwpoint.o lwline.o lwpoly.o lwmpoint.o lwmline.o lwmpoly.o lwcollection.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o lwgeom_svg.o lwgeom_gml.o $(GEOS_WRAPPER)
 
 OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwpostgis.sql
 
diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h
new file mode 100644 (file)
index 0000000..fbe3aab
--- /dev/null
@@ -0,0 +1,849 @@
+#ifndef _LIBLWGEOM_H
+#define _LIBLWGEOM_H 1
+
+//liblwgeom.h
+
+
+typedef void* (*lwallocator)(size_t size);
+typedef void* (*lwreallocator)(void *mem, size_t size);
+typedef void (*lwfreeor)(void* mem);
+typedef void (*lwreporter)(const char* fmt, ...);
+
+#ifndef C_H
+typedef unsigned int uint32;
+typedef int int32;
+#endif
+
+/* prototypes */
+void *default_allocator(size_t size);
+void *default_reallocator(void *mem, size_t size);
+void default_freeor(void *ptr);
+void default_errorreporter(const char *fmt, ...);
+void default_noticereporter(const char *fmt, ...);
+
+/* globals */
+extern lwreallocator lwrealloc;
+extern lwallocator lwalloc;
+extern lwfreeor lwfree;
+extern lwreporter lwerror;
+extern lwreporter lwnotice;
+
+//-----------------------------------------------------------------
+
+typedef struct
+{
+       float xmin;
+       float ymin;
+       float xmax;
+       float ymax;
+} BOX2DFLOAT4;
+
+typedef struct
+{
+        double xmin, ymin, zmin;
+        double xmax, ymax, zmax;
+} BOX3D;
+
+
+typedef struct chiptag
+{
+       int size; //unused (for use by postgresql)
+
+       int endian_hint;  // the number 1 in the endian of this datastruct
+
+       BOX3D bvol;
+       int SRID;
+       char future[4];
+       float factor;   // Usually 1.0.
+                       // Integer values are multiplied by this number
+                       // to get the actual height value
+                       // (for sub-meter accuracy height data).
+
+       int datatype;   // 1 = float32,
+                       // 5 = 24bit integer,
+                       // 6 = 16bit integer (short)
+                       // 101 = float32 (NDR),
+                       // 105 = 24bit integer (NDR),
+                       // 106=16bit int (NDR)
+
+       int height;
+       int width;
+       int compression;        // 0 = no compression, 1 = differencer
+                               // 0x80 = new value
+                               // 0x7F = nodata
+
+       // this is provided for convenience, it should be set to
+       //  sizeof(chip) bytes into the struct because the serialized form is:
+       //    <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 
diff --git a/lwgeom/lwcollection.c b/lwgeom/lwcollection.c
new file mode 100644 (file)
index 0000000..dfdc618
--- /dev/null
@@ -0,0 +1,35 @@
+#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;
+}
+
diff --git a/lwgeom/lwgeom.c b/lwgeom/lwgeom.c
new file mode 100644 (file)
index 0000000..c7b9633
--- /dev/null
@@ -0,0 +1,134 @@
+#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);
+}
+
index 2848b1effc4c062ef0c267c27a99cbc5ba1f1ab5..2cb8d0d2aca9d06711724a55c444a707b31ea788 100644 (file)
@@ -265,7 +265,6 @@ extern int lwgeom_size_subgeom(const char *serialized_form, int geom_number);
 
 typedef struct
 {
-       int type;       // POINTTYPE
        char ndims;     // 2=2d, 3=3d, 4=4d, 5=undef
        int SRID;       // spatial ref sys
        POINTARRAY *point;  // hide 2d/3d (this will be an array of 1 point)
@@ -303,7 +302,6 @@ extern POINT3D lwpoint_getPoint3d(const LWPOINT *point);
 
 typedef struct
 {
-       int type; // LINETYPE
        char  ndims; // 2=2d, 3=3d, 4=4d, 5=undef
        int  SRID;   // spatial ref sys -1=none
        POINTARRAY    *points; // array of POINT3D
@@ -337,7 +335,6 @@ extern BOX3D *lwline_findbbox(LWLINE *line);
 
 typedef struct
 {
-       int type; // POLYGONTYPE
        int32 SRID;
        char ndims;
        int  nrings;
@@ -368,6 +365,64 @@ extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *size);
 // find bounding box (standard one)  zmin=zmax=0 if 2d (might change to NaN)
 extern BOX3D *lwpoly_findbbox(LWPOLY *poly);
 
+//--------------------------------------------------------
+
+// MULTIPOINTTYPE
+typedef struct
+{
+       int32 SRID;
+       char ndims;
+       int  npoints;
+       LWPOINT **points;
+} LWMPOINT; 
+
+// MULTILINETYPE
+typedef struct
+{
+       int32 SRID;
+       char ndims;
+       int  nlines;
+       LWLINE **lines;
+} LWMLINE; 
+
+// MULTIPOLYGONTYPE
+typedef struct
+{
+       int32 SRID;
+       char ndims;
+       int  npolys;
+       LWPOLY **polys;
+} LWMPOLY; 
+
+// COLLECTIONTYPE
+typedef struct
+{
+       int32 SRID;
+       char ndims;
+       int  ngeoms;
+       struct LWGEOM **geoms;
+} LWCOLLECTION; 
+
+// LWGEOM (any type)
+typedef struct
+{
+       char type;
+       union {
+               LWPOINT *point;
+               LWMPOINT *mpoint;
+               LWLINE *line;
+               LWMLINE *mline;
+               LWPOLY *poly;
+               LWMPOLY *mpoly;
+               LWCOLLECTION *collection;
+       };
+} LWGEOM;
+
+LWGEOM *lwgeom_deserialize(char *serializedform);
+LWMPOINT *lwmpoint_deserialize(char *serializedform);
+
+//------------------------------------------------------
+
 //------------------------------------------------------
 // Multi-geometries
 //
@@ -536,10 +591,10 @@ extern BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected);
 
 extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box);
 extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res);
-extern BOX2DFLOAT4 *box_to_box2df(BOX *box);  // postgresql standard type
-
 extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box);
 extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d);
+
+extern BOX2DFLOAT4 *box_to_box2df(BOX *box);  // postgresql standard type
 extern BOX box2df_to_box(BOX2DFLOAT4 *box);  // postgresql standard type
 extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type
 
@@ -716,26 +771,6 @@ extern void printType(unsigned char str);
 
 // other forwards (for indirect function calls)
 
-Datum box2d_same(PG_FUNCTION_ARGS);
-Datum box2d_overlap(PG_FUNCTION_ARGS);
-Datum box2d_overleft(PG_FUNCTION_ARGS);
-Datum box2d_left(PG_FUNCTION_ARGS);
-Datum box2d_right(PG_FUNCTION_ARGS);
-Datum box2d_overright(PG_FUNCTION_ARGS);
-Datum box2d_contained(PG_FUNCTION_ARGS);
-Datum box2d_contain(PG_FUNCTION_ARGS);
-Datum box2d_inter(PG_FUNCTION_ARGS);
-Datum box2d_union(PG_FUNCTION_ARGS);
-
-Datum gist_lwgeom_compress(PG_FUNCTION_ARGS);
-Datum gist_lwgeom_consistent(PG_FUNCTION_ARGS);
-Datum gist_rtree_decompress(PG_FUNCTION_ARGS);
-Datum lwgeom_box_union(PG_FUNCTION_ARGS);
-Datum lwgeom_box_penalty(PG_FUNCTION_ARGS);
-Datum lwgeom_gbox_same(PG_FUNCTION_ARGS);
-Datum lwgeom_gbox_picksplit(PG_FUNCTION_ARGS);
-
-
 extern float LWGEOM_Minf(float a, float b);
 extern float LWGEOM_Maxf(float a, float b);
 extern double LWGEOM_Mind(double a, double b);
index 9d39bd58c4967d3f9713b5271a9d859870f7e735..887d42e42f3e940b79493449bdb004c3ccb9377e 100644 (file)
@@ -1,4 +1,3 @@
-#include "postgres.h"
 
 #include <math.h>
 #include <float.h>
@@ -6,15 +5,7 @@
 #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
@@ -30,9 +21,6 @@ extern  BOX3D *lw_geom_getBB_simple(char *serialized_form);
 #ifdef DEBUG_EXPLODED
 void checkexplodedsize(char *srl, LWGEOM_EXPLODED *exploded, int alloced, char wantbbox);
 #endif
-static uint32 lwgeom_size_line(const char *serialized_line);
-static uint32 lwgeom_size_point(const char *serialized_point);
-static uint32 lwgeom_size_poly(const char *serialized_line);
 
 //*********************************************************************
 // BOX routines
@@ -175,14 +163,14 @@ double nextUp_d(float d)
 
 
 // Convert BOX3D to BOX2D
-// returned box2d is allocated with 'palloc'
+// returned box2d is allocated with 'lwalloc'
 BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box)
 {
-       BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4));
+       BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4));
 
        if (box == NULL)
        {
-               elog(ERROR, "box3d_to_box2df got NUL box");
+               lwerror("box3d_to_box2df got NUL box");
                return result;
        }
 
@@ -196,13 +184,13 @@ BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box)
 }
 
 // Convert BOX3D to BOX2D using pre-allocated BOX2D
-// returned box2d is allocated with 'palloc'
+// returned box2d is allocated with 'lwalloc'
 // return 0 on error (NULL input box)
 int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result)
 {
        if (box == NULL)
        {
-               elog(NOTICE, "box3d_to_box2df got NUL box");
+               lwnotice("box3d_to_box2df got NUL box");
                return 0;
        }
 
@@ -216,22 +204,6 @@ int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result)
 }
 
 
-//convert postgresql BOX to BOX2D
-BOX2DFLOAT4 *box_to_box2df(BOX *box)
-{
-       BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4));
-
-       if (box == NULL)
-               return result;
-
-       result->xmin = nextDown_f(box->low.x);
-       result->ymin = nextDown_f(box->low.y);
-
-       result->xmax = nextUp_f(box->high.x);
-       result->ymax = nextUp_f(box->high.x);
-
-       return result;
-}
 
 // convert BOX2D to BOX3D
 // zmin and zmax are set to 0.0
@@ -269,36 +241,6 @@ void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
 }
 
 
-// convert BOX2D to postgresql BOX
-BOX   box2df_to_box(BOX2DFLOAT4 *box)
-{
-       BOX result;
-
-       if (box == NULL)
-               return result;
-
-       result.low.x = nextDown_d(box->xmin);
-       result.low.y = nextDown_d(box->ymin);
-
-       result.high.x = nextUp_d(box->xmax);
-       result.high.y = nextUp_d(box->ymax);
-
-       return result;
-}
-
-// convert BOX2D to postgresql BOX
-void
-box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out)
-{
-       if (box == NULL) return;
-
-       out->low.x = nextDown_d(box->xmin);
-       out->low.y = nextDown_d(box->ymin);
-
-       out->high.x = nextUp_d(box->xmax);
-       out->high.y = nextUp_d(box->ymax);
-}
-
 
 // returns a BOX3D that encloses b1 and b2
 // combine_boxes(NULL,A) --> A
@@ -308,7 +250,7 @@ BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2)
 {
        BOX3D *result;
 
-       result =(BOX3D*) palloc(sizeof(BOX3D));
+       result =(BOX3D*) lwalloc(sizeof(BOX3D));
 
        if ( (b1 == NULL) && (b2 == NULL) )
        {
@@ -372,32 +314,32 @@ BOX2DFLOAT4 getbox2d(char *serialized_form)
 
        loc = serialized_form+1;
 
-//elog(NOTICE,"getbox2d: type is %d", type);
+//lwnotice("getbox2d: type is %d", type);
 
        if (lwgeom_hasBBOX(type))
        {
                //woot - this is easy
-//elog(NOTICE,"getbox2d has box");
+//lwnotice("getbox2d has box");
                memcpy(&result,loc, sizeof(BOX2DFLOAT4));
                return result;
        }
 
        //we have to actually compute it!
-//elog(NOTICE,"getbox2d -- computing bbox");
+//lwnotice("getbox2d -- computing bbox");
        box3d = lw_geom_getBB_simple(serialized_form);
-//elog(NOTICE,"lw_geom_getBB_simple got bbox3d(%.15g %.15g,%.15g %.15g)",box3d->xmin,box3d->ymin,box3d->xmax,box3d->ymax);
+//lwnotice("lw_geom_getBB_simple got bbox3d(%.15g %.15g,%.15g %.15g)",box3d->xmin,box3d->ymin,box3d->xmax,box3d->ymax);
 
        if ( ! box3d_to_box2df_p(box3d, &result) )
        {
-               elog(ERROR, "Error converting box3d to box2df");
+               lwerror("Error converting box3d to box2df");
        }
 
        //box = box3d_to_box2df(box3d);
-//elog(NOTICE,"box3d made box2d(%.15g %.15g,%.15g %.15g)",box->xmin,box->ymin,box->xmax,box->ymax);
+//lwnotice("box3d made box2d(%.15g %.15g,%.15g %.15g)",box->xmin,box->ymin,box->xmax,box->ymax);
        //memcpy(&result,box, sizeof(BOX2DFLOAT4));
-       //pfree(box);
+       //lwfree(box);
 
-       pfree(box3d);
+       lwfree(box3d);
 
        return result;
 }
@@ -411,7 +353,7 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
        BOX3D *box3d;
 
 #ifdef DEBUG
-       elog(NOTICE,"getbox2d_p call");
+       lwnotice("getbox2d_p call");
 #endif
 
        loc = serialized_form+1;
@@ -420,22 +362,22 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
        {
                //woot - this is easy
 #ifdef DEBUG
-               elog(NOTICE,"getbox2d_p: has box");
+               lwnotice("getbox2d_p: has box");
 #endif
                memcpy(box, loc, sizeof(BOX2DFLOAT4));
                return 1;
        }
 
 #ifdef DEBUG
-       elog(NOTICE,"getbox2d_p: has no box - computing");
+       lwnotice("getbox2d_p: has no box - computing");
 #endif
 
        //we have to actually compute it!
-//elog(NOTICE,"getbox2d_p:: computing box");
+//lwnotice("getbox2d_p:: computing box");
        box3d = lw_geom_getBB_simple(serialized_form);
 
 #ifdef DEBUG
-       elog(NOTICE, "getbox2d_p: lw_geom_getBB_simple returned %p", box3d);
+       lwnotice("getbox2d_p: lw_geom_getBB_simple returned %p", box3d);
 #endif
 
        if ( ! box3d )
@@ -449,14 +391,14 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
        }
 
 #ifdef DEBUG
-       elog(NOTICE, "getbox2d_p: box3d converted to box2d");
+       lwnotice("getbox2d_p: box3d converted to box2d");
 #endif
 
        //box2 = box3d_to_box2df(box3d);
        //memcpy(box,box2, sizeof(BOX2DFLOAT4));
-       //pfree(box2);
+       //lwfree(box2);
 
-       pfree(box3d);
+       lwfree(box3d);
 
        return 1;
 }
@@ -589,21 +531,21 @@ getPoint3d_p(const POINTARRAY *pa, int n, char *point)
        op = (POINT3D *)point;
 
 #ifdef DEBUG
-       elog(NOTICE, "getPoint3d_p called on array of %d-dimensions / %u pts",
+       lwnotice("getPoint3d_p called on array of %d-dimensions / %u pts",
                pa->ndims, pa->npoints);
-       if ( pa->npoints > 1000 ) elog(ERROR, "More then 1000 points in pointarray ??");
+       if ( pa->npoints > 1000 ) lwerror("More then 1000 points in pointarray ??");
 #endif
 
        if ( (n<0) || (n>=pa->npoints))
        {
-               elog(NOTICE, "%d out of numpoint range (%d)", n, pa->npoints);
+               lwnotice("%d out of numpoint range (%d)", n, pa->npoints);
                return ; //error
        }
 
        size = pointArray_ptsize(pa);
 
 #ifdef DEBUG
-       elog(NOTICE, "getPoint3d_p: point size: %d", size);
+       lwnotice("getPoint3d_p: point size: %d", size);
 #endif
 
        ip = (POINT3D *)getPoint(pa, n);
@@ -686,10 +628,10 @@ getPoint(const POINTARRAY *pa, int n)
 POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints)
 {
        POINTARRAY  *pa;
-       pa = (POINTARRAY*)palloc(sizeof(POINTARRAY));
+       pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY));
 
        if (ndims>4)
-               elog(ERROR,"pointArray_construct:: called with dims = %i", (int) ndims);
+               lwerror("pointArray_construct:: called with dims = %i", (int) ndims);
 
        pa->ndims = ndims;
        pa->npoints = npoints;
@@ -699,7 +641,7 @@ POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints)
 }
 
 // calculate the bounding box of a set of points
-// returns a palloced BOX3D, or NULL on empty array.
+// returns a lwalloced BOX3D, or NULL on empty array.
 // zmin/zmax values are set to NO_Z_VALUE if not available.
 BOX3D *pointArray_bbox(const POINTARRAY *pa)
 {
@@ -709,35 +651,35 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa)
        int npoints = pa->npoints;
 
 #ifdef DEBUG
-       elog(NOTICE, "pointArray_bbox call (array has %d points)", pa->npoints);
+       lwnotice("pointArray_bbox call (array has %d points)", pa->npoints);
 #endif
        if (pa->npoints == 0)
        {
 #ifdef DEBUG
-               elog(NOTICE, "pointArray_bbox returning NULL");
+               lwnotice("pointArray_bbox returning NULL");
 #endif
                return NULL;
        }
 
-       if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__);
+       if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__);
 
-       result = (BOX3D*)palloc(sizeof(BOX3D));
+       result = (BOX3D*)lwalloc(sizeof(BOX3D));
 
-       if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__);
+       if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__);
 
        if ( ! result )
        {
-               elog(NOTICE, "Out of virtual memory");
+               lwnotice("Out of virtual memory");
                return NULL;
        }
 
        //getPoint3d_p(pa, 0, (char*)pt);
        pt = (POINT3D *)getPoint(pa, 0);
 
-       if ( npoints != pa->npoints) elog(ERROR, "Messed up at %s:%d", __FILE__, __LINE__);
+       if ( npoints != pa->npoints) lwerror("Messed up at %s:%d", __FILE__, __LINE__);
 
 #ifdef DEBUG
-       elog(NOTICE, "pointArray_bbox: got point 0");
+       lwnotice("pointArray_bbox: got point 0");
 #endif
 
        result->xmin = pt->x;
@@ -748,1102 +690,213 @@ BOX3D *pointArray_bbox(const POINTARRAY *pa)
        if ( pa->ndims > 2 ) {
                result->zmin = pt->z;
                result->zmax = pt->z;
-       } else {
-               result->zmin = NO_Z_VALUE;
-               result->zmax = NO_Z_VALUE;
-       }
-
-#ifdef DEBUG
-       elog(NOTICE, "pointArray_bbox: scanning other %d points", pa->npoints);
-#endif
-       for (t=1;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.
@@ -1854,7 +907,7 @@ lwpoly_size(LWPOLY *poly)
 LWGEOM_INSPECTED *
 lwgeom_inspect(const char *serialized_form)
 {
-       LWGEOM_INSPECTED *result = palloc(sizeof(LWGEOM_INSPECTED));
+       LWGEOM_INSPECTED *result = lwalloc(sizeof(LWGEOM_INSPECTED));
        unsigned char type;
        char **sub_geoms;
        const char *loc;
@@ -1885,7 +938,7 @@ lwgeom_inspect(const char *serialized_form)
                }
                //simple geometry (point/line/polygon)-- not multi!
                result->ngeometries = 1;
-               sub_geoms = (char**) palloc(sizeof(char*));
+               sub_geoms = (char**) lwalloc(sizeof(char*));
                sub_geoms[0] = serialized_form;
                result->sub_geoms = sub_geoms;
                return result;
@@ -1902,24 +955,24 @@ lwgeom_inspect(const char *serialized_form)
        result->ngeometries = get_uint32(loc);
        loc +=4;
 #ifdef DEBUG
-       elog(NOTICE, "lwgeom_inspect: geometry is a collection of %d elements",
+       lwnotice("lwgeom_inspect: geometry is a collection of %d elements",
                result->ngeometries);
 #endif
 
        if ( ! result->ngeometries ) return result;
 
-       sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries );
+       sub_geoms = (char**) lwalloc(sizeof(char*) * result->ngeometries );
        result->sub_geoms = sub_geoms;
        sub_geoms[0] = loc;
 #ifdef DEBUG
-       elog(NOTICE, "subgeom[0] @ %p", sub_geoms[0]);
+       lwnotice("subgeom[0] @ %p", sub_geoms[0]);
 #endif
        for (t=1;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
        }
@@ -2182,7 +1235,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri
        if (nsubgeometries == 0)
                return lwgeom_constructempty(SRID,ndims);
 
-       lengths = palloc(sizeof(int32) * nsubgeometries);
+       lengths = lwalloc(sizeof(int32) * nsubgeometries);
 
        for (t=0;t<nsubgeometries;t++)
        {
@@ -2241,7 +1294,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri
        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)
        {
@@ -2260,7 +1313,7 @@ extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometri
                loc += lengths[t] ;
        }
 
-       pfree(lengths);
+       lwfree(lengths);
        return result;
 }
 
@@ -2279,7 +1332,7 @@ char *lwgeom_constructempty(int SRID,int ndims)
 
        size += 5;
 
-       result = palloc(size);
+       result = lwalloc(size);
 
        result[0] =(unsigned char) lwgeom_makeType( ndims, SRID != -1,  COLLECTIONTYPE);
        if (SRID != -1)
@@ -2333,7 +1386,7 @@ lwgeom_constructempty_buf(int SRID, int ndims, char *buf, int *retsize)
 //         --> size of the point
 
 // take a geometry, and find its length
-int
+uint32
 lwgeom_size(const char *serialized_form)
 {
        unsigned char type = lwgeom_getType((unsigned char) serialized_form[0]);
@@ -2344,34 +1397,34 @@ lwgeom_size(const char *serialized_form)
        int result = 1; //"type"
 
 #ifdef DEBUG
-       elog(NOTICE, "lwgeom_size called");
+       lwnotice("lwgeom_size called");
 #endif
 
        if (type == POINTTYPE)
        {
 #ifdef DEBUG
-               elog(NOTICE, "lwgeom_size: is a point");
+               lwnotice("lwgeom_size: is a point");
 #endif
                return lwgeom_size_point(serialized_form);
        }
        else if (type == LINETYPE)
        {
 #ifdef DEBUG
-               elog(NOTICE, "lwgeom_size: is a line");
+               lwnotice("lwgeom_size: is a line");
 #endif
                return lwgeom_size_line(serialized_form);
        }
        else if (type == POLYGONTYPE)
        {
 #ifdef DEBUG
-               elog(NOTICE, "lwgeom_size: is a polygon");
+               lwnotice("lwgeom_size: is a polygon");
 #endif
                return lwgeom_size_poly(serialized_form);
        }
 
        if ( type == 0 )
        {
-               elog(ERROR, "lwgeom_size called with unknown-typed serialized geometry");
+               lwerror("lwgeom_size called with unknown-typed serialized geometry");
                return 0;
        }
 
@@ -2379,7 +1432,7 @@ lwgeom_size(const char *serialized_form)
        //NOTE: for a geometry collection of GC of GC of GC we will be recursing...
 
 #ifdef DEBUG
-       elog(NOTICE, "lwgeom_size called on a geoemtry with type %d", type);
+       lwnotice("lwgeom_size called on a geoemtry with type %d", type);
 #endif
 
        loc = serialized_form+1;
@@ -2387,7 +1440,7 @@ lwgeom_size(const char *serialized_form)
        if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
        {
 #ifdef DEBUG
-               elog(NOTICE, "lwgeom_size: has bbox");
+               lwnotice("lwgeom_size: has bbox");
 #endif
 
                loc += sizeof(BOX2DFLOAT4);
@@ -2397,7 +1450,7 @@ lwgeom_size(const char *serialized_form)
        if (lwgeom_hasSRID( (unsigned char) serialized_form[0]) )
        {
 #ifdef DEBUG
-               elog(NOTICE, "lwgeom_size: has srid");
+               lwnotice("lwgeom_size: has srid");
 #endif
                result +=4;
                loc +=4;
@@ -2409,26 +1462,26 @@ lwgeom_size(const char *serialized_form)
        result += 4; // numgeoms
 
 #ifdef DEBUG
-       elog(NOTICE, "lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
+       lwnotice("lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
 #endif
 
        for (t=0;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)
@@ -2448,7 +1501,7 @@ lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number)
 
 
 //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)
 {
@@ -2460,7 +1513,7 @@ 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]);
@@ -2472,23 +1525,23 @@ BOX3D *lw_geom_getBB_simple(char *serialized_form)
        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;
@@ -2514,7 +1567,7 @@ elog(NOTICE, "lw_geom_getBB_simple: bbox found");
        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;
        }
 
@@ -2544,8 +1597,8 @@ elog(NOTICE, "lw_geom_getBB_simple: bbox found");
                {
                        b2= result;
                        result = combine_boxes(b2, b1);
-                       pfree(b1);
-                       pfree(b2);
+                       lwfree(b1);
+                       lwfree(b2);
                }
                else
                {
@@ -2558,7 +1611,7 @@ elog(NOTICE, "lw_geom_getBB_simple: bbox found");
 }
 
 
-//dont forget to pfree() result
+//dont forget to lwfree() result
 BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected)
 {
        int t;
@@ -2573,16 +1626,16 @@ BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected)
        {
                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
                {
@@ -2607,37 +1660,14 @@ BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected)
 void pfree_inspected(LWGEOM_INSPECTED *inspected)
 {
        if ( inspected->ngeometries )
-               pfree(inspected->sub_geoms);
-       pfree(inspected);
-}
-
-void pfree_point    (LWPOINT *pt)
-{
-       pfree_POINTARRAY(pt->point);
-       pfree(pt);
-}
-
-void pfree_line     (LWLINE  *line)
-{
-       pfree(line->points);
-       pfree(line);
+               lwfree(inspected->sub_geoms);
+       lwfree(inspected);
 }
 
-void pfree_polygon  (LWPOLY  *poly)
-{
-       int t;
-
-       for (t=0;t<poly->nrings;t++)
-       {
-               pfree_POINTARRAY(poly->rings[t]);
-       }
-
-       pfree(poly);
-}
 
 void pfree_POINTARRAY(POINTARRAY *pa)
 {
-       pfree(pa);
+       lwfree(pa);
 }
 
 
@@ -2647,24 +1677,6 @@ void pfree_POINTARRAY(POINTARRAY *pa)
 //** debugging routines
 
 
-void printLWLINE(LWLINE *line)
-{
-       elog(NOTICE,"LWLINE {");
-       elog(NOTICE,"    ndims = %i", (int)line->ndims);
-       elog(NOTICE,"    SRID = %i", (int)line->SRID);
-       printPA(line->points);
-       elog(NOTICE,"}");
-}
-
-void printLWPOINT(LWPOINT *point)
-{
-       elog(NOTICE,"LWPOINT {");
-       elog(NOTICE,"    ndims = %i", (int)point->ndims);
-       elog(NOTICE,"    SRID = %i", (int)point->SRID);
-       printPA(point->point);
-       elog(NOTICE,"}");
-}
-
 void printPA(POINTARRAY *pa)
 {
        int t;
@@ -2672,30 +1684,30 @@ void printPA(POINTARRAY *pa)
        POINT3D pt3;
        POINT4D pt4;
 
-       elog(NOTICE,"      POINTARRAY{");
-       elog(NOTICE,"                 ndims =%i,   ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa));
-       elog(NOTICE,"                 npoints = %i", pa->npoints);
+       lwnotice("      POINTARRAY{");
+       lwnotice("                 ndims =%i,   ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa));
+       lwnotice("                 npoints = %i", pa->npoints);
 
        for (t =0; 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)
@@ -2705,31 +1717,16 @@ void printBYTES(unsigned char *a, int n)
 
        buff[2] = 0; //null terminate
 
-       elog(NOTICE," BYTE ARRAY (n=%i) IN HEX: {", n);
+       lwnotice(" BYTE ARRAY (n=%i) IN HEX: {", n);
        for (t=0;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)
 {
@@ -2739,11 +1736,11 @@ printMULTI(char *serialized)
        LWPOLY  *poly;
        int t;
 
-       elog(NOTICE,"MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((unsigned char)serialized[0]), inspected->ngeometries);
+       lwnotice("MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((unsigned char)serialized[0]), inspected->ngeometries);
 
        for (t=0;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);
@@ -2763,14 +1760,14 @@ printMULTI(char *serialized)
                }
     }
 
-    elog(NOTICE,"end multi*");
+    lwnotice("end multi*");
 
        pfree_inspected(inspected);
 }
 
 void printType(unsigned char type)
 {
-       elog(NOTICE,"type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type));
+       lwnotice("type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type));
 }
 
 // get the SRID from the LWGEOM
@@ -2809,7 +1806,7 @@ int lwgeom_getSRID(PG_LWGEOM *lwgeom)
 
 // Set the SRID of a LWGEOM
 // Returns a newly allocated LWGEOM object.
-// Allocation will be done using the palloc.
+// Allocation will be done using the lwalloc.
 PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID)
 {
        unsigned char type = lwgeom->type;
@@ -2826,16 +1823,16 @@ PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID)
        if (lwgeom_hasSRID(type))
        {
                //we create a new one and copy the SRID in
-               result = palloc(len);
+               result = lwalloc(len);
                memcpy(result, lwgeom, len);
                memcpy(result->data+bbox_offset, &newSRID,4);
        }
        else  // need to add one
        {
                len_new = len + 4;//+4 for SRID
-               result = palloc(len_new);
+               result = lwalloc(len_new);
                memcpy(result, &len_new, 4); // size copy in
-               result->type = lwgeom_makeType_full(lwgeom_ndims(type), true, lwgeom_getType(type),lwgeom_hasBBOX(type));
+               result->type = lwgeom_makeType_full(lwgeom_ndims(type), 1, lwgeom_getType(type),lwgeom_hasBBOX(type));
 
                loc_new = result->data;
                loc_old = lwgeom->data;
@@ -2900,7 +1897,7 @@ PG_LWGEOM_construct(char *ser, int SRID, int wantbbox)
 
        size+=4; // size header
 
-       result = palloc(size);
+       result = lwalloc(size);
        result->size = size;
 
        result->type = lwgeom_makeType_full(lwgeom_ndims(ser[0]),
@@ -2925,12 +1922,12 @@ void
 pfree_exploded(LWGEOM_EXPLODED *exploded)
 {
        if ( exploded->npoints )
-               pfree(exploded->points);
+               lwfree(exploded->points);
        if ( exploded->nlines )
-               pfree(exploded->lines);
+               lwfree(exploded->lines);
        if ( exploded->npolys )
-               pfree(exploded->polys);
-       pfree(exploded);
+               lwfree(exploded->polys);
+       lwfree(exploded);
 };
 
 /*
@@ -2945,33 +1942,33 @@ lwgeom_explode(char *serialized)
        int i;
 
 #ifdef DEBUG
-       elog(NOTICE, "lwgeom_explode called");
+       lwnotice("lwgeom_explode called");
 #endif
 
        inspected = lwgeom_inspect(serialized);
 
 
 #ifdef DEBUG
-elog(NOTICE, "lwgeom_explode: serialized inspected");
+lwnotice("lwgeom_explode: serialized inspected");
 #endif
 
-       result = palloc(sizeof(LWGEOM_EXPLODED));
-       result->points = palloc(1);
-       result->lines = palloc(1);
-       result->polys = palloc(1);
+       result = lwalloc(sizeof(LWGEOM_EXPLODED));
+       result->points = lwalloc(1);
+       result->lines = lwalloc(1);
+       result->polys = lwalloc(1);
        result->npoints = 0;
        result->nlines = 0;
        result->npolys = 0;
 
        if ( ! inspected->ngeometries )
        {
-               pfree(result->points);
-               pfree(result->lines);
-               pfree(result->polys);
+               lwfree(result->points);
+               lwfree(result->lines);
+               lwfree(result->polys);
                result->SRID = -1;
                result->ndims = 0;
                pfree_inspected(inspected);
-               //elog(NOTICE, "lwgeom_explode: no geometries");
+               //lwnotice("lwgeom_explode: no geometries");
                return result;
        }
 
@@ -2987,9 +1984,9 @@ elog(NOTICE, "lwgeom_explode: serialized inspected");
                if ( type == POINTTYPE )
                {
 #ifdef DEBUG
-elog(NOTICE, "lwgeom_explode: it's a point");
+lwnotice("lwgeom_explode: it's a point");
 #endif
-                       result->points = repalloc(result->points,
+                       result->points = lwrealloc(result->points,
                                (result->npoints+1)*sizeof(char *));
                        result->points[result->npoints] = subgeom;
                        result->npoints++;
@@ -2999,9 +1996,9 @@ elog(NOTICE, "lwgeom_explode: it's a point");
                if ( type == LINETYPE )
                {
 #ifdef DEBUG
-elog(NOTICE, "lwgeom_explode: it's a line");
+lwnotice("lwgeom_explode: it's a line");
 #endif
-                       result->lines = repalloc(result->lines,
+                       result->lines = lwrealloc(result->lines,
                                (result->nlines+1)*sizeof(char *));
                        result->lines[result->nlines] = subgeom;
                        result->nlines++;
@@ -3011,9 +2008,9 @@ elog(NOTICE, "lwgeom_explode: it's a line");
                if ( type == POLYGONTYPE )
                {
 #ifdef DEBUG
-elog(NOTICE, "lwgeom_explode: it's a polygon");
+lwnotice("lwgeom_explode: it's a polygon");
 #endif
-                       result->polys = repalloc(result->polys,
+                       result->polys = lwrealloc(result->polys,
                                (result->npolys+1)*sizeof(char *));
                        result->polys[result->npolys] = subgeom;
                        result->npolys++;
@@ -3021,14 +2018,14 @@ elog(NOTICE, "lwgeom_explode: it's a polygon");
                }
 
 #ifdef DEBUG
-               elog(NOTICE, "type of subgeom %d is %d, recursing", i, type);
+               lwnotice("type of subgeom %d is %d, recursing", i, type);
 #endif
 
                // it's a multi geometry, recurse
                subexploded = lwgeom_explode(subgeom);
 
 #ifdef DEBUG
-               elog(NOTICE, "subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys);
+               lwnotice("subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys);
 #endif
 
                // Re-allocate adding space for new exploded geoms
@@ -3038,13 +2035,13 @@ elog(NOTICE, "lwgeom_explode: it's a polygon");
 
                if ( subexploded->npoints )
                {
-                       result->points = repalloc(result->points,
+                       result->points = lwrealloc(result->points,
                                sizeof(char *)*(result->npoints+subexploded->npoints-1));
                        if ( ! result )
-                               elog(ERROR, "Out of virtual memory");
+                               lwerror("Out of virtual memory");
 
 #ifdef DEBUG
-                       elog(NOTICE, "repalloc'ed exploded->points");
+                       lwnotice("lwrealloc'ed exploded->points");
 #endif
 
                        memcpy(&(result->points[result->npoints]),
@@ -3052,19 +2049,19 @@ elog(NOTICE, "lwgeom_explode: it's a polygon");
                                subexploded->npoints*sizeof(char *));
 
 #ifdef DEBUG
-                       elog(NOTICE, "memcpied exploded->points");
+                       lwnotice("memcpied exploded->points");
 #endif
 
                        result->npoints += subexploded->npoints;
 
 #ifdef DEBUG
-                       elog(NOTICE, "memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints);
+                       lwnotice("memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints);
 #endif
                }
 
                if ( subexploded->nlines )
                {
-                       result->lines = repalloc(result->lines,
+                       result->lines = lwrealloc(result->lines,
                                sizeof(char *)*
                                (result->nlines+subexploded->nlines-1));
 
@@ -3077,7 +2074,7 @@ elog(NOTICE, "lwgeom_explode: it's a polygon");
 
                if ( subexploded->npolys )
                {
-                       result->polys = repalloc(result->polys,
+                       result->polys = lwrealloc(result->polys,
                                sizeof(char *)*
                                (result->npolys+subexploded->npolys-1));
 
@@ -3096,13 +2093,13 @@ elog(NOTICE, "lwgeom_explode: it's a polygon");
        pfree_inspected(inspected);
 
 #ifdef DEBUG
-elog(NOTICE, "lwgeom_explode: returning");
+lwnotice("lwgeom_explode: returning");
 #endif
 
        return result;
 }
 
-// Returns a 'palloced' union of the two input exploded geoms
+// Returns a 'lwalloced' union of the two input exploded geoms
 // Returns NULL if SRID or ndims do not match.
 LWGEOM_EXPLODED *
 lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
@@ -3113,11 +2110,11 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
        if ( exp1->ndims != exp2->ndims ) return NULL;
        if ( exp1->SRID != exp2->SRID ) return NULL;
 
-       expcoll = palloc(sizeof(LWGEOM_EXPLODED));
+       expcoll = lwalloc(sizeof(LWGEOM_EXPLODED));
 
        expcoll->npoints = exp1->npoints + exp2->npoints;
        if ( expcoll->npoints ) {
-               expcoll->points = (char **)palloc(expcoll->npoints*sizeof(char *));
+               expcoll->points = (char **)lwalloc(expcoll->npoints*sizeof(char *));
                loc = (char *)&(expcoll->points[0]);
                if ( exp1->npoints ) {
                        memcpy(loc, exp1->points,
@@ -3132,7 +2129,7 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
 
        expcoll->nlines = exp1->nlines + exp2->nlines;
        if ( expcoll->nlines ) {
-               expcoll->lines = palloc(expcoll->nlines*sizeof(char *));
+               expcoll->lines = lwalloc(expcoll->nlines*sizeof(char *));
                loc = (char *)&(expcoll->lines[0]);
                if ( exp1->nlines ) {
                        memcpy(loc, exp1->lines,
@@ -3147,7 +2144,7 @@ lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
 
        expcoll->npolys = exp1->npolys + exp2->npolys;
        if ( expcoll->npolys ) {
-               expcoll->polys = palloc(expcoll->npolys*sizeof(char *));
+               expcoll->polys = lwalloc(expcoll->npolys*sizeof(char *));
                loc = (char *)&(expcoll->polys[0]);
                if ( exp1->npolys ) {
                        memcpy(loc, exp1->polys,
@@ -3174,10 +2171,10 @@ lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox)
 {
        int sizecom = 0;
        int size = lwexploded_findlength(exploded, wantbbox);
-       char *result = palloc(size);
+       char *result = lwalloc(size);
        lwexploded_serialize_buf(exploded, wantbbox, result, &sizecom);
 #ifdef DEBUG
-       elog(NOTICE, "lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom);
+       lwnotice("lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom);
 #endif
        return result;
 }
@@ -3291,7 +2288,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
        }
 
 #ifdef DEBUG
-       elog(NOTICE, " computed outtype: %d, ngeoms: %d", outtype, ngeoms);
+       lwnotice(" computed outtype: %d, ngeoms: %d", outtype, ngeoms);
 #endif
 
 
@@ -3346,7 +2343,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
                line = lwline_deserialize(exploded->lines[i]);
                if ( line == NULL )
                {
-       elog(ERROR, "Error deserializing %dnt line from exploded geom", i);
+       lwerror("Error deserializing %dnt line from exploded geom", i);
        return;
                }
                line->SRID = -1;
@@ -3371,7 +2368,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
                poly = lwpoly_deserialize(exploded->polys[i]);
                if ( poly == NULL )
                {
-       elog(ERROR, "Error deserializing %dnt polygon from exploded geom", i);
+       lwerror("Error deserializing %dnt polygon from exploded geom", i);
        return;
                }
                poly->SRID = -1;
@@ -3403,20 +2400,20 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
        }
 
 #ifdef DEBUG
-       elog(NOTICE, "lwexploded_serialize finished");
-       elog(NOTICE, " type: %d", lwgeom_getType(buf[0]));
-       elog(NOTICE, " SRID: %d", lwgeom_getsrid(buf));
+       lwnotice("lwexploded_serialize finished");
+       lwnotice(" type: %d", lwgeom_getType(buf[0]));
+       lwnotice(" SRID: %d", lwgeom_getsrid(buf));
        if ( lwgeom_hasBBOX(buf[0]) )
        {
                {
                        BOX2DFLOAT4 boxbuf;
                        getbox2d_p(buf, &boxbuf);
-                       elog(NOTICE, " BBOX: %f,%f %f,%f",
+                       lwnotice(" BBOX: %f,%f %f,%f",
                                boxbuf.xmin, boxbuf.ymin,
                                boxbuf.xmax, boxbuf.ymax);
                }
        }
-       elog(NOTICE, " numgeoms: %d", lwgeom_getnumgeometries(buf));
+       lwnotice(" numgeoms: %d", lwgeom_getnumgeometries(buf));
 #endif
 
        return;
@@ -3426,7 +2423,7 @@ lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
 void
 checkexplodedsize(char *srl, LWGEOM_EXPLODED *exp, int alloced, char wantbbox)
 {
-       elog(NOTICE, "exploded len: serialized:%d computed:%d alloced:%d",
+       lwnotice("exploded len: serialized:%d computed:%d alloced:%d",
                lwgeom_size(srl), lwexploded_findlength(exp, wantbbox),
                alloced);
 }
@@ -3516,7 +2513,7 @@ lwexploded_findlength(LWGEOM_EXPLODED *exploded, int wantbbox)
        return size;
 }
 
-bool
+char
 ptarray_isccw(const POINTARRAY *pa)
 {
        int i;
@@ -3532,3 +2529,4 @@ ptarray_isccw(const POINTARRAY *pa)
        if ( area > 0 ) return 0;
        else return 1;
 }
+
diff --git a/lwgeom/lwgeom_box.c b/lwgeom/lwgeom_box.c
new file mode 100644 (file)
index 0000000..ffc8ae2
--- /dev/null
@@ -0,0 +1,56 @@
+#include "postgres.h"
+#include "utils/geo_decls.h"
+
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
+
+
+
+//convert postgresql BOX to BOX2D
+BOX2DFLOAT4 *
+box_to_box2df(BOX *box)
+{
+       BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4));
+
+       if (box == NULL)
+               return result;
+
+       result->xmin = nextDown_f(box->low.x);
+       result->ymin = nextDown_f(box->low.y);
+
+       result->xmax = nextUp_f(box->high.x);
+       result->ymax = nextUp_f(box->high.x);
+
+       return result;
+}
+
+// convert BOX2D to postgresql BOX
+BOX   box2df_to_box(BOX2DFLOAT4 *box)
+{
+       BOX result;
+
+       if (box == NULL)
+               return result;
+
+       result.low.x = nextDown_d(box->xmin);
+       result.low.y = nextDown_d(box->ymin);
+
+       result.high.x = nextUp_d(box->xmax);
+       result.high.y = nextUp_d(box->ymax);
+
+       return result;
+}
+
+// convert BOX2D to postgresql BOX
+void
+box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out)
+{
+       if (box == NULL) return;
+
+       out->low.x = nextDown_d(box->xmin);
+       out->low.y = nextDown_d(box->ymin);
+
+       out->high.x = nextUp_d(box->xmax);
+       out->high.y = nextUp_d(box->ymax);
+}
+
index 5f2a1be86fe70586ac85d59fdc2ca3c017367449..48ba0ed7cca5c611500c9baf5b3acbdb734749c4 100644 (file)
@@ -1,20 +1,19 @@
-#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"
 
 
index 3d136843e13ea54d493c4eccaa4c901c21cfa536..60c461d58f38b58ef68f4fc6db523e65db510ce2 100644 (file)
@@ -4,18 +4,19 @@
  *
  **********************************************************************/
 
-#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
index 0a582b8f4394ff4a56813b1e72f6a81881197f7d..fe962ff74bbf1268820194ec314cd8e74ece0abb 100644 (file)
 
 #include "postgres.h"
 #include "fmgr.h"
+#include "utils/geo_decls.h"
 
-#include "lwgeom.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
 
 Datum lwgeom_lt(PG_FUNCTION_ARGS);
 Datum lwgeom_le(PG_FUNCTION_ARGS);
@@ -447,6 +449,13 @@ Datum lwgeom_cmp(PG_FUNCTION_ARGS)
 /***********************************************************
  *
  * $Log$
+ * Revision 1.5  2004/09/29 10:50:30  strk
+ * Big layout change.
+ * lwgeom.h is public API
+ * liblwgeom.h is private header
+ * lwgeom_pg.h is for PG-links
+ * lw<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.
index 9d543929d515cc263679e20d105ad0bcd1f792a5..9fbaa4043646a2be19087babc64cce916ef959f4 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <math.h>
 #include <float.h>
 #include <string.h>
@@ -12,7 +11,8 @@
 #include "fmgr.h"
 #include "utils/elog.h"
 
-#include "lwgeom.h"
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
 
 // External functions (what's again the reason for using explicit hex form ?)
 extern void deparse_hex(unsigned char str, unsigned char *result);
index 4de2bab00b80b3d2c79f81897a91d7bb50c99064..4f5f32e4d6d7118600294abc2a290e25be3200ff 100644 (file)
  * 
  **********************************************************************
  * $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.
  *
@@ -28,8 +35,6 @@
  *
  **********************************************************************/
 
-#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
 
index 23d9418ca911a145de25b43fee6bebf6bb656cf9..d9adc1531f8817d9459f65493d958b667d429a06 100644 (file)
@@ -1,5 +1,7 @@
 #include "postgres.h"
-#include "lwgeom.h"
+#include "fmgr.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
 
 /***********************************************************************
  * Simple Douglas-Peucker line simplification. 
index 72fe7a5085475418157c63e498271d9dddbc58e8..fb993fb30396c980bbd659e06ec5327d5f402821 100644 (file)
@@ -1,16 +1,17 @@
-#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
index cce20d8f94870cce41cd6f6e8d264e9c4428ce9b..f963c05aa6d3d3df04e6f11b9e28849dfea598f9 100644 (file)
@@ -2,8 +2,10 @@
 #include "postgres.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "fmgr.h"
 
-#include "lwgeom.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
 #include "profile.h"
 #include "wktparse.h"
 
index d7d6a4ef25acd37ed9626d7753589836b24f4b8d..349a12517d9d23001612af0aed710c01badd0fdf 100644 (file)
@@ -1,19 +1,18 @@
-#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 &&)
index 9ac138d0d10451b5249de6cdb82e191a356ccb57..1a34bba754956ab97c7bf67b320aeaed51f55ac9 100644 (file)
@@ -17,7 +17,9 @@
 
 #include "postgres.h"
 #include "executor/spi.h"
-#include "lwgeom.h"
+
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
 
 Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
 char *geometry_to_gml(char *lwgeom, char *srs);
@@ -513,6 +515,13 @@ getSRSbySRID(int SRID)
 
 /**********************************************************************
  * $Log$
+ * Revision 1.4  2004/09/29 10:50:30  strk
+ * Big layout change.
+ * lwgeom.h is public API
+ * liblwgeom.h is private header
+ * lwgeom_pg.h is for PG-links
+ * lw<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.
index 9445aa407b6ef75b54cbcd50b38f65c0a1d024f1..c008ae8e2bac1ba5cfd1abff72ef9803a5e495eb 100644 (file)
@@ -17,7 +17,7 @@
 #endif
 
 
-#include "lwgeom.h"
+#include "liblwgeom.h"
 #include "stringBuffer.h"
 
 
@@ -115,8 +115,13 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOM_out);
 Datum LWGEOM_out(PG_FUNCTION_ARGS)
 {
-       char *lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char *result = unparse_WKB(lwgeom,palloc_fn,free_fn);
+       char *lwgeom;
+       char *result;
+
+       init_pg_func();
+
+       lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       result = unparse_WKB(lwgeom,lwalloc,lwfree);
 
        PG_RETURN_CSTRING(result);
 }
@@ -181,7 +186,7 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS)
        pfree(wkb_srid_hexized);
 
 #ifdef DEBUG
-       elog(NOTICE, "LWGEOMFromWKB returning %s", unparse_WKB(lwgeom, palloc_fn, free_fn));
+       elog(NOTICE, "LWGEOMFromWKB returning %s", unparse_WKB(lwgeom, pg_alloc, pg_free));
 #endif
 
        PG_RETURN_POINTER(lwgeom);
@@ -192,10 +197,8 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(WKBFromLWGEOM);
 Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
 {
-       char *lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       // SRID=#;<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;
@@ -203,6 +206,11 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
        char *semicolonLoc;
        int t;
 
+       init_pg_func();
+
+       lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       hexized_wkb_srid = unparse_WKB(lwgeom_input, lwalloc, lwfree);
+
 //elog(NOTICE, "in WKBFromLWGEOM with WKB = '%s'", hexized_wkb_srid);
 
        hexized_wkb = hexized_wkb_srid;
@@ -535,6 +543,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS)
                int                       wkt_size ;
 
 
+               init_pg_func();
 
                wkt_size = (*(int*) wkt_input) -4;  // actual letters
 
@@ -546,8 +555,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS)
 //elog(NOTICE,"in parse_WKT_lwgeom");
 //elog(NOTICE,"in parse_WKT_lwgeom with input: '%s'",wkt);
 
-               //serialized_form = parse_WKT((const char *)wkt,(allocator) malloc, (report_error)elog_ERROR);
-               serialized_form = parse_lwg((const char *)wkt,(allocator) palloc_fn, (report_error)elog_ERROR);
+               serialized_form = parse_lwg((const char *)wkt, (allocator)lwalloc, (report_error)elog_ERROR);
 //elog(NOTICE,"parse_WKT_lwgeom:: finished parse");
                pfree (wkt);
 
@@ -571,7 +579,7 @@ Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS)
 
 char *parse_lwgeom_wkt(char *wkt_input)
 {
-       char *serialized_form = parse_lwg((const char *)wkt_input,(allocator) palloc_fn, (report_error)elog_ERROR);
+       char *serialized_form = parse_lwg((const char *)wkt_input,(allocator)pg_alloc, (report_error)elog_ERROR);
 
 
 #ifdef DEBUG
@@ -622,7 +630,7 @@ Datum LWGEOM_recv(PG_FUNCTION_ARGS)
 #endif
 
 #ifdef DEBUG
-       elog(NOTICE, "LWGEOMFromWKB returned %s", unparse_WKB(result,palloc_fn,free_fn));
+       elog(NOTICE, "LWGEOMFromWKB returned %s", unparse_WKB(result,pg_alloc,pg_free));
 #endif
 
 
index 23f8eb14369cd34801ace94f7e2ba13ed37e1a36..1afb6fa5853f2ef58dc3974d87934c4e6c6208c7 100644 (file)
@@ -13,8 +13,7 @@
 #include "fmgr.h"
 #include "utils/elog.h"
 
-
-#include "lwgeom.h"
+#include "liblwgeom.h"
 #include "lwgeom_pg.h"
 
 
@@ -95,12 +94,18 @@ Datum LWGEOM_setSRID(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOM_getTYPE);
 Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS)
 {
-       PG_LWGEOM *lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char *text_ob = palloc(20+4);
-       char *result = text_ob+4;
+       PG_LWGEOM *lwgeom;
+       char *text_ob;
+       char *result;
        int32 size;
        unsigned char type;
 
+       init_pg_func();
+
+       lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       text_ob = lwalloc(20+4);
+       result = text_ob+4;
+
        //type = lwgeom_getType(*(lwgeom+4));
        type = lwgeom_getType(lwgeom->type);
 
@@ -706,10 +711,15 @@ Datum LWGEOM_from_text(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOM_asText);
 Datum LWGEOM_asText(PG_FUNCTION_ARGS)
 {
-       char *lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char *result_cstring =  unparse_WKT(lwgeom,palloc_fn,free_fn);
+       char *lwgeom;
+       char *result_cstring;
        int len;
 
+       init_pg_func();
+
+       lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       result_cstring =  unparse_WKT(lwgeom,lwalloc,lwfree);
+
         char *result,*loc_wkt;
        char *semicolonLoc;
 
index 792a7ab15c7a3fcb1ee125f88f0341b15252458e..f5306398e4a9d003e92c9242f1d9517c710bc6cc 100644 (file)
@@ -1,6 +1,12 @@
+#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);
@@ -8,8 +14,70 @@ void *palloc_fn(size_t size)
        return result;
 }
 
-void free_fn(void *ptr)
+void *
+pg_realloc(void *mem, size_t size)
+{
+       void * result;
+       result = repalloc(mem, size);
+       return result;
+}
+
+void
+pg_free(void *ptr)
 {
-       //elog(NOTICE,"  pfree(%p)", ptr);
        pfree(ptr);
 }
+
+void
+pg_error(const char *fmt, ...)
+{
+       char *msg;
+       va_list ap;
+
+       va_start (ap, fmt);
+
+       /*
+       * This is a GNU extension.
+       * Dunno how to handle errors here.
+       */
+       if (!vasprintf (&msg, fmt, ap))
+       {
+               va_end (ap);
+               return;
+       }
+       va_end(ap);
+       elog(ERROR, "%s", msg);
+       free(msg);
+}
+
+void
+pg_notice(const char *fmt, ...)
+{
+       char *msg;
+       va_list ap;
+
+       va_start (ap, fmt);
+
+       /*
+       * This is a GNU extension.
+       * Dunno how to handle errors here.
+       */
+       if (!vasprintf (&msg, fmt, ap))
+       {
+               va_end (ap);
+               return;
+       }
+       va_end(ap);
+       elog(NOTICE, "%s", msg);
+       free(msg);
+}
+
+void
+init_pg_func()
+{
+       lwalloc = pg_alloc;
+       lwrealloc = pg_realloc;
+       lwfree = pg_free;
+       lwerror = pg_error;
+       lwnotice = pg_notice;
+}
index b95e7382f511ab8bfb6e5b8e4b3731d6403afa79..8f04f47aa52d675fc98ff188f3fad9ae5ffdfedc 100644 (file)
@@ -1,3 +1,43 @@
-void *palloc_fn(size_t size);
-void free_fn(void *ptr);
+#ifndef _LWGEOM_PG_H
+#define _LWGEOM_PG_H 1
 
+#include "postgres.h"
+#include "utils/geo_decls.h"
+#include "fmgr.h"
+#include "liblwgeom.h"
+
+void *pg_alloc(size_t size);
+void *pg_realloc(void *ptr, size_t size);
+void pg_free(void *ptr);
+void pg_error(const char *msg, ...);
+void pg_notice(const char *msg, ...);
+
+// call this as first thing of any PG function
+void init_pg_func(void);
+
+// PG-dependant
+extern BOX2DFLOAT4 *box_to_box2df(BOX *box);  // postgresql standard type
+extern BOX box2df_to_box(BOX2DFLOAT4 *box);
+extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type
+// PG-exposed
+Datum box2d_same(PG_FUNCTION_ARGS);
+Datum box2d_overlap(PG_FUNCTION_ARGS);
+Datum box2d_overleft(PG_FUNCTION_ARGS);
+Datum box2d_left(PG_FUNCTION_ARGS);
+Datum box2d_right(PG_FUNCTION_ARGS);
+Datum box2d_overright(PG_FUNCTION_ARGS);
+Datum box2d_contained(PG_FUNCTION_ARGS);
+Datum box2d_contain(PG_FUNCTION_ARGS);
+Datum box2d_inter(PG_FUNCTION_ARGS);
+Datum box2d_union(PG_FUNCTION_ARGS);
+
+Datum gist_lwgeom_compress(PG_FUNCTION_ARGS);
+Datum gist_lwgeom_consistent(PG_FUNCTION_ARGS);
+Datum gist_rtree_decompress(PG_FUNCTION_ARGS);
+Datum lwgeom_box_union(PG_FUNCTION_ARGS);
+Datum lwgeom_box_penalty(PG_FUNCTION_ARGS);
+Datum lwgeom_gbox_same(PG_FUNCTION_ARGS);
+Datum lwgeom_gbox_picksplit(PG_FUNCTION_ARGS);
+
+
+#endif // !defined _LWGEOM_PG_H 1
index fe33a74380d084d71d83c50601b8d37eec107c56..014b6212df9d116aa755bd7001c3f08c9ab035b6 100644 (file)
@@ -28,7 +28,8 @@
 #include "utils/elog.h"
 
 
-#include "lwgeom.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
 
 #define SHOW_DIGS_DOUBLE 15
 #define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
index b6a4f1a23157f0bf77187a4a44c7022b00380996..b676cad54ce4826736750a12d4b3648cfa0ac703 100644 (file)
@@ -18,7 +18,8 @@
 
 
 #include "postgres.h"
-#include "lwgeom.h"
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
 
 Datum assvg_geometry(PG_FUNCTION_ARGS);
 char *geometry_to_svg(PG_LWGEOM *geometry, int svgrel, int precision);
@@ -251,6 +252,13 @@ print_svg_path_rel(char *result, POINTARRAY *pa, int precision)
 
 /**********************************************************************
  * $Log$
+ * Revision 1.3  2004/09/29 10:50:30  strk
+ * Big layout change.
+ * lwgeom.h is public API
+ * liblwgeom.h is private header
+ * lwgeom_pg.h is for PG-links
+ * lw<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.
index 78443ee396410ec989f42fa2604b6425fe80274f..49700256a16b305e917a34227a31824626522981 100644 (file)
@@ -8,7 +8,8 @@
 #include "postgres.h"
 #include "fmgr.h"
 
-#include "lwgeom.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
 
 Datum transform_geom(PG_FUNCTION_ARGS);
 Datum postgis_proj_version(PG_FUNCTION_ARGS);
diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c
new file mode 100644 (file)
index 0000000..d5dd49c
--- /dev/null
@@ -0,0 +1,323 @@
+// 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("}");
+}
+
diff --git a/lwgeom/lwmline.c b/lwgeom/lwmline.c
new file mode 100644 (file)
index 0000000..c4cfd85
--- /dev/null
@@ -0,0 +1,41 @@
+#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;
+}
+
diff --git a/lwgeom/lwmpoint.c b/lwgeom/lwmpoint.c
new file mode 100644 (file)
index 0000000..945d4dd
--- /dev/null
@@ -0,0 +1,41 @@
+#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;
+}
+
diff --git a/lwgeom/lwmpoly.c b/lwgeom/lwmpoly.c
new file mode 100644 (file)
index 0000000..97e01c2
--- /dev/null
@@ -0,0 +1,41 @@
+#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;
+}
+
diff --git a/lwgeom/lwpoint.c b/lwgeom/lwpoint.c
new file mode 100644 (file)
index 0000000..3f6ca9c
--- /dev/null
@@ -0,0 +1,229 @@
+#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("}");
+}
+
diff --git a/lwgeom/lwpoly.c b/lwgeom/lwpoly.c
new file mode 100644 (file)
index 0000000..e345490
--- /dev/null
@@ -0,0 +1,414 @@
+// 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("}");
+}
+