]> granicus.if.org Git - postgis/commitdiff
Dropped HWGEOM from this branch.
authorSandro Santilli <strk@keybit.net>
Fri, 8 Oct 2004 07:01:43 +0000 (07:01 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 8 Oct 2004 07:01:43 +0000 (07:01 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@962 b70326c6-7e19-0410-871a-916f4a2858ee

17 files changed:
hwgeom/Makefile [deleted file]
hwgeom/postgis.h [deleted file]
hwgeom/postgis.sql.in [deleted file]
hwgeom/postgis_algo.c [deleted file]
hwgeom/postgis_chip.c [deleted file]
hwgeom/postgis_debug.c [deleted file]
hwgeom/postgis_estimate.c [deleted file]
hwgeom/postgis_fn.c [deleted file]
hwgeom/postgis_geos.c [deleted file]
hwgeom/postgis_geos_wrapper.cpp [deleted file]
hwgeom/postgis_gist_71.c [deleted file]
hwgeom/postgis_gist_72.c [deleted file]
hwgeom/postgis_inout.c [deleted file]
hwgeom/postgis_ops.c [deleted file]
hwgeom/postgis_proj.c [deleted file]
hwgeom/postgis_svg.c [deleted file]
hwgeom/postgis_transform.c [deleted file]

diff --git a/hwgeom/Makefile b/hwgeom/Makefile
deleted file mode 100644 (file)
index d7ad5a3..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-include ../Makefile.config
-
-#---------------------------------------------------------------
-# Configuration Directives
-#
-
-#---------------------------------------------------------------
-subdir=contrib/postgis
-#---------------------------------------------------------------
-# Default the root of the PostgreSQL source tree 
-# To use a non-standard location set the PGSQL_SRC environment
-# variable to the appropriate location.
-#
-ifeq (${PGSQL_SRC},) 
-       PGSQL_SRC = ../..
-endif
-
-#---------------------------------------------------------------
-# Path to library (to be specified in CREATE FUNCTION queries)
-# Defaults to $libdir.
-# Set LPATH environment variable to change it.
-#
-ifeq (${LPATH},)
-       LPATH := \$$libdir
-endif
-
-#---------------------------------------------------------------
-#top_builddir = ${PGSQL_SRC}
-#include $(top_builddir)/src/Makefile.global
-
-#---------------------------------------------------------------
-# Default missing CXX variable to c++
-# 
-ifeq ($(CXX),) 
-       CXX = c++
-endif
-
-#---------------------------------------------------------------
-# Test the version string and set the USE_VERSION macro
-# appropriately.
-#
-ifneq ($(findstring 7.1,$(VERSION)),)
-       USE_VERSION=71
-else
-       ifneq ($(findstring 7.2,$(VERSION)),)
-               USE_VERSION=72
-       else
-               ifneq ($(findstring 7.3,$(VERSION)),)
-                       USE_VERSION=73
-               else
-                       ifneq ($(findstring 7.4,$(VERSION)),)
-                               USE_VERSION=74
-                       else
-                               USE_VERSION=80
-                       endif
-               endif
-       endif
-endif
-
-#---------------------------------------------------------------
-# Shared library parameters.
-#
-NAME=postgis
-SO_MAJOR_VERSION=0
-SO_MINOR_VERSION=9
-SO_MICRO_VERSION=0
-SCRIPTS_VERSION=0.0.1
-ifeq (${USE_VERSION}, 71) 
-       MODULE_FILENAME = $(LPATH)/$(shlib)
-       MODULE_INSTALLDIR = $(libdir)
-else
-       MODULE_FILENAME = $(LPATH)/$(shlib)
-       MODULE_INSTALLDIR = $(pkglibdir)
-endif
-
-#---------------------------------------------------------------
-# Postgis version
-#---------------------------------------------------------------
-
-POSTGIS_LIB_VERSION = $(SO_MAJOR_VERSION).$(SO_MINOR_VERSION).$(SO_MICRO_VERSION)
-POSTGIS_VERSION = $(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) USE_GEOS=$(USE_GEOS) USE_PROJ=$(USE_PROJ) USE_STATS=$(USE_STATS)
-
-#---------------------------------------------------------------
-
-override CFLAGS += -g -fexceptions 
-override CFLAGS += -I$(srcdir) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"' 
-override CFLAGS += -DUSE_VERSION=$(USE_VERSION)
-override CFLAGS += -DPOSTGIS_LIB_VERSION='"$(POSTGIS_LIB_VERSION)"'
-override CFLAGS += -DPOSTGIS_SCRIPTS_VERSION='"$(SCRIPTS_VERSION)"'
-
-ifeq ($(USE_GEOS),1)
-       override CFLAGS += -I$(GEOS_DIR)/include -DUSE_GEOS
-       GEOS_RULES=detect_geos_version
-endif
-ifeq ($(USE_PROJ),1)
-       override CFLAGS += -I$(PROJ_DIR)/include -DUSE_PROJ 
-endif
-
-override DLLLIBS += $(BE_DLLLIBS) 
-
-override CXXFLAGS := $(CFLAGS)
-# memory debug for gcc 2.91, 2.95, 3.0 and 3.1
-# for gcc >= 3.2.2 set GLIBCPP_FORCE_NEW at runtime instead
-#override CXXFLAGS += -D__USE_MALLOC
-
-# this seems to be needed by gcc3.3.2 / Solaris7 combination
-# as reported by  Havard Tveite <havard.tveite@nlh.no>
-override CXXFLAGS += -fPIC
-
-#---------------------------------------------------------------
-# Add index selectivity to C flags
-#
-ifeq ($(USE_STATS),1)
-       override CFLAGS += -DUSE_STATS
-endif
-#---------------------------------------------------------------
-# Select proper GiST support C file
-#
-ifeq ($(USE_VERSION),71) 
-       GIST_SUPPORT=71
-       GIST_ESTIMATE=
-else
-       GIST_SUPPORT=72
-       GIST_ESTIMATE=postgis_estimate.o
-endif
-
-ifeq ($(USE_GEOS),1)
-       GEOS_WRAPPER=postgis_geos_wrapper.o
-endif
-
-OBJS=postgis_debug.o postgis_ops.o postgis_fn.o postgis_inout.o postgis_proj.o postgis_chip.o postgis_transform.o postgis_svg.o postgis_gist_$(GIST_SUPPORT).o $(GIST_ESTIMATE) postgis_geos.o $(GEOS_WRAPPER) postgis_algo.o
-
-#---------------------------------------------------------------
-# Add libraries that libpq depends (or might depend) on into the
-# shared library link.  (The order in which you list them here doesn't
-# matter.)
-
-SHLIB_LINK = $(filter -L%, $(LDFLAGS)) 
-ifeq ($(USE_GEOS),1)
-       SHLIB_LINK += -lstdc++ -L$(GEOS_DIR)/lib -lgeos
-endif
-ifeq ($(USE_PROJ),1)
-       SHLIB_LINK += -L$(PROJ_DIR)/lib -lproj
-endif
-SHLIB_LINK += $(BE_DLLLIBS) 
-
-#---------------------------------------------------------------
-# Makefile targets
-
-include $(top_srcdir)/src/Makefile.shlib
-
-postgis_geos_wrapper.o: postgis_geos_wrapper.cpp
-
-all: $(GEOS_RULES) all-lib postgis.sql postgis_undef.sql 
-
-# Shared library stuff
-
-postgis_old.sql: postgis_sql_common.sql.in postgis_sql_$(USE_VERSION)_end.sql.in postgis_sql_$(USE_VERSION)_start.sql.in 
-       cat postgis_sql_$(USE_VERSION)_start.sql.in postgis_sql_common.sql.in postgis_sql_$(USE_VERSION)_end.sql.in | sed -e 's:@MODULE_FILENAME@:$(MODULE_FILENAME):g;s:@POSTGIS_VERSION@:$(POSTGIS_VERSION):g'  > $@ 
-
-postgis.sql: postgis.sql.in
-       cpp -P -traditional-cpp -DUSE_VERSION=$(USE_VERSION) $< | sed -e 's:@MODULE_FILENAME@:$(MODULE_FILENAME):g;s:@POSTGIS_VERSION@:$(POSTGIS_VERSION):g;s:@POSTGIS_SCRIPTS_VERSION@:$(SCRIPTS_VERSION):g' > $@
-
-postgis_undef.sql: postgis.sql ../create_undef.pl
-       perl ../create_undef.pl $< $(USE_VERSION) > $@ 
-
-install: all installdirs install-postgis-lib
-       $(INSTALL_DATA) postgis.sql $(DESTDIR)$(datadir)
-       $(INSTALL_DATA) postgis_undef.sql $(DESTDIR)$(datadir)
-       $(INSTALL_DATA) spatial_ref_sys.sql $(DESTDIR)$(datadir)
-       $(INSTALL_DATA) README.postgis $(DESTDIR)$(datadir)
-
-#- This has been copied from postgresql and adapted
-install-postgis-lib: $(shlib)
-       $(INSTALL_SHLIB) $< $(DESTDIR)$(MODULE_INSTALLDIR)/$(shlib)
-ifneq ($(PORTNAME), win)
-ifneq ($(shlib), lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION))
-       cd $(DESTDIR)$(MODULE_INSTALLDIR) && \
-       rm -f lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION) && \
-       $(LN_S) $(shlib) lib$(NAME)$(DLSUFFIX).$(SO_MAJOR_VERSION)
-endif
-ifneq ($(shlib), lib$(NAME)$(DLSUFFIX))
-       cd $(DESTDIR)$(MODULE_INSTALLDIR) && \
-       rm -f lib$(NAME)$(DLSUFFIX) && \
-       $(LN_S) $(shlib) lib$(NAME)$(DLSUFFIX)
-endif
-
-endif # not win
-#----------------------------------------------------------
-
-detect_geos_version: 
-       ../geos_version.sh $(GEOS_DIR) > postgis_geos_version.h
-
-installdirs:
-       $(mkinstalldirs) $(datadir)/contrib $(libdir)
-
-uninstall: uninstall-lib
-       @rm -f $(docdir)/contrib/README.postgis $(datadir)/contrib/postgis.sql
-
-clean distclean maintainer-clean: clean-lib
-       @rm -f $(OBJS) postgis.sql postgis_undef.sql postgis_geos_version.h
-
diff --git a/hwgeom/postgis.h b/hwgeom/postgis.h
deleted file mode 100644 (file)
index ed1671f..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of hte GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.51  2004/09/16 15:50:59  mleslie
- * Added the distance_sphere function to calculate the distance between two points
- * on an earth-sized sphere using an algorithm implemented by Bruno Wolff III.
- * Added the postgresql loader function.
- *
- * Revision 1.50  2004/08/19 06:15:58  strk
- * USE_VERSION gets 80 where it got 75
- *
- * Revision 1.49  2004/07/28 13:37:43  strk
- * Added postgis_uses_stats and postgis_scripts_version.
- * Experimented with PIP short-circuit in within/contains functions.
- * Documented new version functions.
- *
- * Revision 1.48  2004/07/23 21:24:33  strk
- * Added postgis_proj_version()
- *
- * Revision 1.47  2004/07/22 16:20:09  strk
- * Added postgis_lib_version() and postgis_geos_version()
- *
- * Revision 1.46  2004/06/09 09:06:55  strk
- * Added Romi's Win32 patches.
- *
- * Revision 1.45  2004/06/08 15:18:12  strk
- * Deleted prototype for isspace() in postgis.h
- * and included <ctype.h> in postgis_inout.c,
- * which is the only module calling isspace().
- * This was needed to compile postgis against PG75(CVS).
- *
- * Revision 1.44  2004/06/03 16:44:56  strk
- * Added expand_geometry - expand(geometry, int8)
- *
- * Revision 1.43  2004/03/26 00:54:09  dblasby
- * added full support for fluffType(<geom>)
- * postgis09=# select fluffType('POINT(0 0)');
- *         flufftype
- *             -------------------------
- *              SRID=-1;MULTIPOINT(0 0)
- *
- * Revision 1.42  2004/02/23 12:18:55  strk
- * added skeleton functions for pg75 stats integration
- *
- * Revision 1.41  2004/01/25 19:33:00  pramsey
- * Test commit on new CVS archive.
- *
- * Revision 1.40  2004/01/21 19:04:03  strk
- * Added line_interpolate_point function by jsunday@rochgrp.com
- *
- * Revision 1.39  2003/11/28 11:06:49  strk
- * Added WKB_recv function for binary WKB input
- *
- * Revision 1.38  2003/11/19 15:44:51  strk
- * added prototypes for geometry_{le,ge,cmp}
- *
- * Revision 1.37  2003/10/28 16:57:35  strk
- * Added collect_garray() function.
- *
- * Revision 1.36  2003/10/28 15:16:17  strk
- * unite_sfunc() from postgis_geos.c renamed to geom_accum() and moved in postgis_fn.c
- *
- * Revision 1.35  2003/10/28 11:16:46  strk
- * Added postgis_algo.c prototypes
- *
- * Revision 1.34  2003/10/16 16:35:42  dblasby
- * added #include <sys/types.h> for people using freeBSD (strk@keybit.net patch)
- *
- * Revision 1.33  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.32  2003/08/06 19:31:18  dblasby
- * Added the WKB parser.  Added all the functions like
- * PolyFromWKB(<WKB>,[<SRID>]).
- *
- * Added all the functions like PolyFromText(<WKT>,[<SRID>])
- *
- * Minor problem in GEOS library fixed.
- *
- * Revision 1.31  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.30  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-/*
- * Everything is stored in a geometry3d, which is just a conglomeration
- * of the base types (and a little bit of other info).
- */
-
-#include <sys/types.h>
-#include "utils/geo_decls.h"
-
-#define        POINTTYPE       1
-#define        LINETYPE        2
-#define        POLYGONTYPE     3
-#define        MULTIPOINTTYPE  4
-#define        MULTILINETYPE   5
-#define        MULTIPOLYGONTYPE        6
-#define        COLLECTIONTYPE  7
-#define        BBOXONLYTYPE    99
-
-/*
- * Norman Vine found this problem for compiling under cygwin
- * it defines BYTE_ORDER and LITTLE_ENDIAN
- */
-
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-#include <sys/param.h>       // FOR ENDIAN DEFINES
-#endif
-
-
-/*
- * 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 - (x,y,z)
- *            Base type for all geometries
- *               Also used for POINT type and MULTIPOINT type
- *-------------------------------------------------------------------*/
-typedef struct
-{
-       double          x,y,z;  //for lat/long   x=long, y=lat
-} POINT3D;
-
-/*---------------------------------------------------------------------
- * BOX3D       - Specified by two corner points, which are
- *              sorted to save calculation time later.
- *
- *           LLB -- lower right bottom point (ie. South West, Z low)
- *           URT -- upper right top point    (ie. North East, Z high)
- *
- *           this is the long diagonal
- *
- * example:
- *   BOX([0.0,0.0,0.0],[10.0,10.0,10.0])
- *
- *     NOTE:  You CAN make columns in your database of this type
- *              IT IS NOT A TRUE GEOMETRY!
- *-------------------------------------------------------------------*/
-typedef struct
-{
-       POINT3D         LLB,URT; /* corner POINT3Ds on long diagonal */
-} BOX3D;
-
-
-
-
-/*---------------------------------------------------------------------
- * LINE  - set of points (directed arcs)
- *             P1->P2->P3->P4...->Pn
- *-------------------------------------------------------------------*/
-typedef struct
-{
-       int32   npoints; // how many points in the line
-       int32   junk;      // double-word alignment
-       POINT3D         points[1]; // array of actual points
-} LINE3D;
-
-/*---------------------------------------------------------------------
- * POLYGON  - set of closed rings.  First ring in outer boundary
- *                                             other rings are "holes"
- *
- * NOTE: this is acually stored a bit differently.  It is more like:
- *             int32 nrings
- *             char    filler[]
- *
- *  where the 1st 4 byes of filler[] is npoints[0] the next 4 bytes
- *  are npoints[1], etc...
- *
- *  points[0] is either at filler[ 4 * nrings]
- *            or at filler [ 4* nrings + 4]
- *               Which ever one is double-word-aligned
- *-------------------------------------------------------------------*/
-typedef struct
-{
-       int32   nrings;  // how many rings in this polygon
-       int32           npoints[1]; //how many points in each ring
-       /* could be 4 byes of filler here to make sure points[] is
-         double-word aligned*/
-       POINT3D         points[1]; // array of actual points
-} POLYGON3D;
-
-
-/*---------------------------------------------------------------------
- * Geometry - all columns in postgres are of this type
- *
- *             Geometries are collections of simple geometry types
- *             (point, line, polygon).
- *
- *             A Point is a geometry with a single point in it.
- *             A MultiPoint is a geometry with a list of 'point' in it.
- *             A Line is a geometry with a single line in it.
- *             A MultiLine is a geometry with a list of 'line' in it.
- *             A Polygon is a geometry with a single polygon in it.
- *             A MultiPolygon is a geometry with a list of 'polygon' in it.
- *             A Collection is a geometry with a (mixed) list of
- *                             point, line, and polygon.
- *
- *             The bvol is the bounding volume of all the subobjects.
- *
- *             is3d is true if the original data was sent in a 3d data.
- *             2d data is 3d data with z=0.0.
- *
- *     'type' has values:
- *             Point                   -> POINTTYPE
- *             MultiPoint              -> MULTIPOINTTYPE
- *             Line                    -> LINETYPE
- *             MultiLine               -> MULTILINETYPE
- *             Polygon         -> POLYGONTYPE
- *             MultiPolygon    -> MULTIPOLYGONTYPE
- *             Collection              -> COLLECTIOMTYPE
- *
- *     'objType' has values:
- *             Point                   -> POINTTYPE
- *             Line                    -> LINETYPE
- *             Polygon         -> POLYGONTYPE
- *
- *     'objOffset' is an offset (in bytes) into this structure of where
- *     the subobject is defined.  THESE ARE ALWAYS DOUBLE-WORD ALIGNED.
- *
- *
- *     In reality the structure looks like:
- *             int32   size;
- *             int32           type;
- *             bool            is3d;
- *             <there is almost certainly some type of padding here>
- *             BOX3D           bvol;
- *             int32           nobjs;
- *             char            data[...];
- *
- *     AND:
- *             &objType[0] = &data[0]
- *             &objType[1] = &data[4]
- *                     ...
- *             &obgOffset[0] = &data[ 4* nobjs]
- *             &obgOffset[1] = &data[ 4* nobjs + 4]
- *                     ...
- *             &objData[0] = &GEOMETRY + objOffset[0]  //always double-word aligned
- *             &objData[1] = &GEOMETRY + objOffset[1]  //always double-word aligned
- *                     ...
- *
- *     ALL GEOMETRY COLUMNS IN YOUR DATABASE SHOULD BE OF THIS TYPE
- *-------------------------------------------------------------------*/
-typedef struct
-{
-       int32           size;           // postgres variable-length type requirement
-       int32           SRID;           // spatial reference system id
-       double  offsetX;        // for precision grid (future improvement)
-       double  offsetY;        // for precision grid (future improvement)
-       double  scale;  // for precision grid (future improvement)
-       int32           type;           // this type of geometry
-       bool            is3d;           // true if the points are 3d (only for output)
-       BOX3D           bvol;           // bounding volume of all the geo objects
-       int32           nobjs;  // how many sub-objects in this object
-       int32           objType[1];     // type of object
-       int32           objOffset[1];// offset (in bytes) into this structure where
-                                        // the object is located
-       char            objData[1];  // store for actual objects
-
-} GEOMETRY;
-
-
-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;
-
-
-//for GiST indexing
-
-//This is the BOX type from geo_decls.h
-// Its included here for the GiST index.
-//  Originally, we used BOXONLYTYPE geometries as our keys, but after
-//   Oleg and teodor (http://www.sai.msu.su/~megera/postgres/gist/)
-//   have released a more generic rtree/gist index for geo_decls.h polygon
-//   type.  I am using a slightly modified version of this, so
-//   it will be easier to maintain.
-//
-//   Their indexing is based on the BOX object, so we include it here.
-
-
-// ONLY FOR INDEXING
-typedef struct geomkey {
-       int32 size; /* size in varlena terms */
-       BOX     key;
-       int32   SRID; //spatial reference system identifier
-} GEOMETRYKEY;
-
-
-// WKB structure  -- exactly the same as TEXT
-typedef struct Well_known_bin {
-       int32 size;    // total size of this structure
-       unsigned char  data[1]; //THIS HOLD VARIABLE LENGTH DATA
-} WellKnownBinary;
-
-// --------------------------------------------
-// histogram2d type
-
-// 2d histogram is a bounding box with a bunch of cells in it.
-// The cells will have width (xmax-xmin)/boxesPerSide
-//                 and height(ymax-ymin)/boxesPerSide
-// The first box is the ll corner's box, the send is directly to the right
-//   (row-major).
-//
-//  Size of structure is:
-//        4 (size) + 32 (box) + 4 (boxesPerSide) +
-//                 boxesPerSide*boxesPerSide*4 (data)
-typedef struct histotag
-{
-       int32           size;           // postgres variable-length type requirement
-       int                     boxesPerSide;   //boxesPerSide * boxesPerSide = total boxes in grid
-       double          avgFeatureArea; // average bbox area of features in this histogram
-               // double will be correctly aligned
-       double      xmin,ymin, xmax, ymax; // BOX of area
-       unsigned int value[1]; // variable length # of ints for histogram
-} HISTOGRAM2D;
-
-
-
-//prototypes
-
-
-/* constructors*/
-POLYGON3D      *make_polygon(int nrings, int *pts_per_ring, POINT3D *pts, int npoints, int *size);
-void set_point( POINT3D *pt,double x, double y, double z);
-GEOMETRY       *make_oneobj_geometry(int sub_obj_size, char *sub_obj, int type, bool is3d, int SRID,double scale, double offx,double offy);
-
-
-void print_point(char *result, POINT3D *pt,bool is3d);
-void print_many_points(char *result, POINT3D *pt ,int npoints, bool is3d);
-void swap(double *d1, double *d2);
-int    numb_points_in_list(char        *str);
-bool   parse_points_in_list(char       *str, POINT3D   *points, int32  max_points, bool *is3d);
-bool   parse_points_in_list_exact(char *str, POINT3D   *points, int32  max_points, bool *is3d);
-int    find_outer_list_length(char *str);
-bool   points_per_sublist( char *str, int32 *npoints, int32 max_lists);
-char   *scan_to_same_level(char        *str);
-int objects_inside_point(char *str);
-int objects_inside_line(char *str);
-int objects_inside_polygon(char *str);
-int objects_inside_multipoint(char *str);
-int objects_inside_multiline(char *str);
-int objects_inside_multipolygon(char *str);
-int objects_inside_collection(char *str);
-int objects_inside(char *str);
-bool parse_objects_inside_point(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects_inside_multipoint(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects_inside_line(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects_inside_multiline(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects_inside_polygon(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects_inside_multipolygon(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-bool parse_objects(int32 *obj_size,char **objs,int32   *obj_types,int32 nobjs,char *str, int *offset, bool *is3d);
-bool parse_objects_inside_collection(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d);
-BOX3D  *bbox_of_point(POINT3D *pt);
-BOX3D  *bbox_of_polygon(POLYGON3D *polygon);
-BOX3D  *bbox_of_line(LINE3D *line);
-BOX3D *union_box3d(BOX3D *a, BOX3D *b);
-BOX3D  *bbox_of_geometry(GEOMETRY *geom);
-GEOMETRY *make_bvol_geometry(BOX3D *box);
- bool box3d_ov(BOX3D *box1, BOX3D *box2);
-bool is_same_point(POINT3D     *p1, POINT3D    *p2);
-bool is_same_line(LINE3D       *l1, LINE3D     *l2);
-bool is_same_polygon(POLYGON3D *poly1, POLYGON3D       *poly2);
-BOX    *convert_box3d_to_box(BOX3D *in);
-double line_length2d(LINE3D *line);
-double line_length3d(LINE3D *line);
-double polygon_area2d_old(POLYGON3D *poly1);
-double         polygon_perimeter3d(POLYGON3D   *poly1);
-double         polygon_perimeter2d(POLYGON3D   *poly1);
-int PIP( POINT3D *P, POINT3D *V, int n );
-bool point_truely_inside(POINT3D       *point, BOX3D   *box);
-int    compute_outcode( POINT3D *p, BOX3D *box);
-bool lineseg_inside_box( POINT3D *P1, POINT3D *P2, BOX3D *box);
-bool   linestring_inside_box(POINT3D *pts, int npoints, BOX3D *box);
-bool polygon_truely_inside(POLYGON3D   *poly, BOX3D *box);
-bool line_truely_inside( LINE3D *line, BOX3D   *box);
-void   translate_points(POINT3D *pt, int npoints,double x_off, double y_off, double z_off);
-int    size_subobject (char *sub_obj, int type);
-GEOMETRY       *add_to_geometry(GEOMETRY *geom,int sub_obj_size, char *sub_obj, int type);
-LINE3D *make_line(int  npoints, POINT3D        *pts, int       *size);
-//bool point_within_polygon(POINT3D *, POLYGON3D *);
-
-void  swap_char(char *a, char*b);
-void   flip_endian_double(char *dd);
-void           flip_endian_int32(char  *ii);
-
-char   *to_wkb(GEOMETRY *geom, bool flip_endian);
-char   *wkb_multipolygon(POLYGON3D     **polys,int numb_polys,int32 *size, bool flipbytes, char byte_order,bool use3d);
-char   *wkb_polygon(POLYGON3D  *poly,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem);
-char   *wkb_multiline(LINE3D **lines,int32 *size, int numb_lines, bool flipbytes, char byte_order,bool use3d);
-char   *wkb_line(LINE3D *line,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem);
-char   *wkb_point(POINT3D *pt,int32 *size, bool flipbytes, char byte_order, bool use3d);
-char   *wkb_multipoint(POINT3D *pt,int32 numb_points,int32 *size, bool flipbytes, char byte_order,bool use3d);
-
-char *to_wkb_collection(GEOMETRY *geom, bool flip_endian, int32 *size);
-char   *to_wkb_sub(GEOMETRY *geom, bool flip_endian, int32 *wkb_size);
-
-
-
-double deltaLongitude(double azimuth, double sigma, double tsm,SPHEROID *sphere);
-double bigA(double u2);
-double bigB(double u2);
-double distance_ellipse(double lat1, double long1,
-                                       double lat2, double long2,
-                                       SPHEROID *sphere);
-double mu2(double azimuth,SPHEROID *sphere);
-
-double length2d_ellipse_linestring(LINE3D      *line, SPHEROID         *sphere);
-double length3d_ellipse_linestring(LINE3D      *line, SPHEROID         *sphere);
-
-double distance_pt_pt(POINT3D *p1, POINT3D *p2);
-double distance_pt_line(POINT3D *p1, LINE3D *l2);
-double distance_pt_poly(POINT3D *p1, POLYGON3D *poly2);
-double distance_line_line(LINE3D *l1, LINE3D *l2);
-double distance_line_poly(LINE3D *l1, POLYGON3D *poly2);
-double distance_poly_poly(POLYGON3D *poly1, POLYGON3D *poly2);
-double distance_pt_seg(POINT3D *p, POINT3D *A, POINT3D *B);
-double distance_seg_seg(POINT3D *A, POINT3D *B, POINT3D *C, POINT3D *D);
-bool point_in_poly(POINT3D *p, POLYGON3D *poly);
-
-POINT3D        *segmentize_ring(POINT3D        *points, double dist, int num_points_in, int *num_points_out);
-
-
-Datum optimistic_overlap(PG_FUNCTION_ARGS);
-
-
-
-unsigned char  parse_hex(char *str);
-void deparse_hex(unsigned char str, unsigned char *result);
-
-
-char *geometry_to_text(GEOMETRY  *geometry);
-
-BOX3D  *parse_box3d(char *str);
-
-int getint(char *c);
-double getdouble(char *c);
-GEOMETRY *WKBtoGeometry(char *WKB, int length, int *bytes_read);
-
-POINT3D *wkb_linearring(char *WKB,char is3d, char flip_endian, int *numbPoints, int *bytes,int bytes_in_stream);
-
-GEOMETRY *makeNullGeometry(int SRID);
-
-void compressType(GEOMETRY *g);
-
-void DP_findsplit(POINT3D *, int, int, int, int *, double *);
-void DP_simplify(POINT3D *, int, POINT3D **, int *, double);
-char *simplify_line3d(LINE3D *, double);
-char *simplify_polygon3d(POLYGON3D *, double);
-char *simplify_point3d(POINT3D *, double);
-
-//exposed to psql
-
-Datum box3d_in(PG_FUNCTION_ARGS);
-Datum box3d_out(PG_FUNCTION_ARGS);
-Datum geometry_in(PG_FUNCTION_ARGS);
-Datum geometry_out(PG_FUNCTION_ARGS);
-
-Datum astext_geometry(PG_FUNCTION_ARGS);
-
-Datum geometry_text(PG_FUNCTION_ARGS);
-
-
-Datum get_bbox_of_geometry(PG_FUNCTION_ARGS);
-Datum get_geometry_of_bbox(PG_FUNCTION_ARGS);
-Datum box3d_same(PG_FUNCTION_ARGS);
-Datum geometry_overleft(PG_FUNCTION_ARGS);
-Datum geometry_left(PG_FUNCTION_ARGS);
-Datum geometry_right(PG_FUNCTION_ARGS);
-Datum geometry_overright(PG_FUNCTION_ARGS);
-Datum geometry_contained(PG_FUNCTION_ARGS);
-Datum geometry_contain(PG_FUNCTION_ARGS);
-Datum geometry_overlap(PG_FUNCTION_ARGS);
-Datum geometry_same(PG_FUNCTION_ARGS);
-Datum box3d_overlap(PG_FUNCTION_ARGS);
-Datum box3d_overleft(PG_FUNCTION_ARGS);
-Datum box3d_right(PG_FUNCTION_ARGS);
-Datum box3d_contain(PG_FUNCTION_ARGS);
-Datum geometry_union(PG_FUNCTION_ARGS);
-Datum geometry_inter(PG_FUNCTION_ARGS);
-Datum geometry_size(PG_FUNCTION_ARGS);
-Datum length3d(PG_FUNCTION_ARGS);
-Datum length2d(PG_FUNCTION_ARGS);
-Datum area2d(PG_FUNCTION_ARGS);
-Datum perimeter3d(PG_FUNCTION_ARGS);
-Datum perimeter2d(PG_FUNCTION_ARGS);
-Datum truly_inside(PG_FUNCTION_ARGS);
-
-Datum geometry_lt(PG_FUNCTION_ARGS);
-Datum geometry_le(PG_FUNCTION_ARGS);
-Datum geometry_eq(PG_FUNCTION_ARGS);
-Datum geometry_gt(PG_FUNCTION_ARGS);
-Datum geometry_ge(PG_FUNCTION_ARGS);
-Datum geometry_cmp(PG_FUNCTION_ARGS);
-
-Datum npoints(PG_FUNCTION_ARGS);
-Datum nrings(PG_FUNCTION_ARGS);
-Datum mem_size(PG_FUNCTION_ARGS);
-Datum summary(PG_FUNCTION_ARGS);
-Datum translate(PG_FUNCTION_ARGS);
-
-Datum asbinary_specify(PG_FUNCTION_ARGS);
-Datum asbinary_simple(PG_FUNCTION_ARGS);
-
-Datum force_2d(PG_FUNCTION_ARGS);
-Datum force_3d(PG_FUNCTION_ARGS);
-Datum force_collection(PG_FUNCTION_ARGS);
-
-Datum combine_bbox(PG_FUNCTION_ARGS);
-
-Datum dimension(PG_FUNCTION_ARGS);
-Datum geometrytype(PG_FUNCTION_ARGS);
-Datum envelope(PG_FUNCTION_ARGS);
-
-Datum x_point(PG_FUNCTION_ARGS);
-Datum y_point(PG_FUNCTION_ARGS);
-Datum z_point(PG_FUNCTION_ARGS);
-
-Datum numpoints_linestring(PG_FUNCTION_ARGS);
-Datum pointn_linestring(PG_FUNCTION_ARGS);
-
-Datum exteriorring_polygon(PG_FUNCTION_ARGS);
-Datum numinteriorrings_polygon(PG_FUNCTION_ARGS);
-Datum interiorringn_polygon(PG_FUNCTION_ARGS);
-
-Datum numgeometries_collection(PG_FUNCTION_ARGS);
-Datum geometryn_collection(PG_FUNCTION_ARGS);
-
-Datum ellipsoid_out(PG_FUNCTION_ARGS);
-Datum ellipsoid_in(PG_FUNCTION_ARGS);
-Datum length_ellipsoid(PG_FUNCTION_ARGS);
-Datum length3d_ellipsoid(PG_FUNCTION_ARGS);
-Datum distance_ellipsoid(PG_FUNCTION_ARGS);
-Datum distance_sphere(PG_FUNCTION_ARGS);
-
-Datum point_inside_circle(PG_FUNCTION_ARGS);
-Datum distance(PG_FUNCTION_ARGS);
-
-Datum expand_bbox(PG_FUNCTION_ARGS);
-Datum expand_geometry(PG_FUNCTION_ARGS);
-Datum srid_geom(PG_FUNCTION_ARGS);
-Datum geometry_from_text(PG_FUNCTION_ARGS);
-
-Datum startpoint(PG_FUNCTION_ARGS);
-
-Datum endpoint(PG_FUNCTION_ARGS);
-Datum isclosed(PG_FUNCTION_ARGS);
-
-Datum centroid(PG_FUNCTION_ARGS);
-
-Datum postgis_gist_sel(PG_FUNCTION_ARGS);
-
-Datum WKB_in(PG_FUNCTION_ARGS);
-Datum WKB_out(PG_FUNCTION_ARGS);
-
-Datum WKB_recv(PG_FUNCTION_ARGS);
-
-Datum CHIP_in(PG_FUNCTION_ARGS);
-Datum CHIP_out(PG_FUNCTION_ARGS);
-Datum CHIP_to_geom(PG_FUNCTION_ARGS);
-Datum srid_chip(PG_FUNCTION_ARGS);
-Datum setsrid_chip(PG_FUNCTION_ARGS);
-Datum width_chip(PG_FUNCTION_ARGS);
-Datum height_chip(PG_FUNCTION_ARGS);
-Datum datatype_chip(PG_FUNCTION_ARGS);
-Datum compression_chip(PG_FUNCTION_ARGS);
-Datum setfactor_chip(PG_FUNCTION_ARGS);
-Datum factor_chip(PG_FUNCTION_ARGS);
-
-
-Datum segmentize(PG_FUNCTION_ARGS);
-
-Datum box3d_xmin(PG_FUNCTION_ARGS);
-Datum box3d_ymin(PG_FUNCTION_ARGS);
-Datum box3d_zmin(PG_FUNCTION_ARGS);
-
-Datum box3d_xmax(PG_FUNCTION_ARGS);
-Datum box3d_ymax(PG_FUNCTION_ARGS);
-Datum box3d_zmax(PG_FUNCTION_ARGS);
-Datum box3dtobox(PG_FUNCTION_ARGS);
-
-
-
-Datum transform_geom(PG_FUNCTION_ARGS);
-
-Datum max_distance(PG_FUNCTION_ARGS);
-Datum geom_accum(PG_FUNCTION_ARGS);
-Datum collect_garray(PG_FUNCTION_ARGS);
-Datum collector(PG_FUNCTION_ARGS);
-
-Datum WKBtoBYTEA(PG_FUNCTION_ARGS);
-
-Datum histogram2d_in(PG_FUNCTION_ARGS);
-Datum histogram2d_out(PG_FUNCTION_ARGS);
-Datum create_histogram2d(PG_FUNCTION_ARGS);
-
-Datum build_histogram2d(PG_FUNCTION_ARGS);
-
-Datum geometry2box(PG_FUNCTION_ARGS);
-
-Datum explode_histogram2d(PG_FUNCTION_ARGS);
-Datum estimate_histogram2d(PG_FUNCTION_ARGS);
-#if USE_VERSION >= 80
-Datum geometry_analyze(PG_FUNCTION_ARGS);
-#endif
-
-Datum postgisgistcostestimate(PG_FUNCTION_ARGS);
-
-Datum geometryfromWKB(PG_FUNCTION_ARGS);
-Datum geometryfromWKB_SRID(PG_FUNCTION_ARGS);
-
-Datum PointfromWKB_SRID(PG_FUNCTION_ARGS);
-Datum LinefromWKB_SRID(PG_FUNCTION_ARGS);
-Datum PolyfromWKB_SRID(PG_FUNCTION_ARGS);
-Datum MPointfromWKB_SRID(PG_FUNCTION_ARGS);
-Datum MLinefromWKB_SRID(PG_FUNCTION_ARGS);
-Datum MPolyfromWKB_SRID(PG_FUNCTION_ARGS);
-Datum GCfromWKB_SRID(PG_FUNCTION_ARGS);
-
-
-Datum geometry_from_text_poly(PG_FUNCTION_ARGS);
-Datum geometry_from_text_mpoly(PG_FUNCTION_ARGS);
-Datum geometry_from_text_point(PG_FUNCTION_ARGS);
-Datum geometry_from_text_mpoint(PG_FUNCTION_ARGS);
-Datum geometry_from_text_line(PG_FUNCTION_ARGS);
-Datum geometry_from_text_mline(PG_FUNCTION_ARGS);
-Datum geometry_from_text_gc(PG_FUNCTION_ARGS);
-Datum isempty(PG_FUNCTION_ARGS);
-Datum simplify(PG_FUNCTION_ARGS);
-Datum line_interpolate_point(PG_FUNCTION_ARGS);
-
-Datum fluffType(PG_FUNCTION_ARGS);
-Datum postgis_uses_stats(PG_FUNCTION_ARGS);
-Datum postgis_lib_version(PG_FUNCTION_ARGS);
-Datum postgis_geos_version(PG_FUNCTION_ARGS);
-Datum postgis_proj_version(PG_FUNCTION_ARGS);
-
-/*--------------------------------------------------------------------
- * Useful floating point utilities and constants.
- * from postgres geo_decls.c
- * EPSILON modified to be more "double" friendly
- *-------------------------------------------------------------------*/
-
-
-
-// from contrib/cube/cube.c
-
-#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))
-
-
diff --git a/hwgeom/postgis.sql.in b/hwgeom/postgis.sql.in
deleted file mode 100644 (file)
index c6fb431..0000000
+++ /dev/null
@@ -1,2801 +0,0 @@
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--- 
--- $Id$
---
--- PostGIS - Spatial Types for PostgreSQL
--- http://postgis.refractions.net
--- Copyright 2001-2003 Refractions Research Inc.
---
--- This is free software; you can redistribute and/or modify it under
--- the terms of the GNU General Public Licence. See the COPYING file.
---  
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-#if USE_VERSION > 71
-#define CREATEFUNCTION CREATE OR REPLACE FUNCTION
-#else
-#define CREATEFUNCTION CREATE FUNCTION
-#endif
-
-BEGIN TRANSACTION;
-
--- You might have to define the PL/PgSQL language usually done with the
--- changelang script.
-
--- Here's some hokey code to test to see if PL/PgSQL is installed
--- if it is, you get a message "PL/PgSQL is installed" 
--- otherwise it will give a big error message.
-
-(select 'PL/PgSQL is installed.' as message from pg_language where lanname='plpgsql') union (select 'You must install PL/PgSQL before running this SQL file,\nor you will get an error. To install PL/PgSQL run:\n\tcreatelang plpgsql <dbname>'::text as message) order by message limit 1;
-
-
--------------------------------------------------------------------
---  HISTOGRAM2D TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define HISTOGRAM_IN_REP opaque
-# define HISTOGRAM_OUT_REP opaque
-#else
-# define HISTOGRAM_IN_REP histogram2d
-# define HISTOGRAM_OUT_REP cstring
-#endif
-
-CREATEFUNCTION histogram2d_in(HISTOGRAM_OUT_REP)
-       RETURNS HISTOGRAM_IN_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION histogram2d_out(HISTOGRAM_IN_REP)
-       RETURNS HISTOGRAM_OUT_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATE TYPE histogram2d (
-       alignment = double,
-       internallength = variable,
-       input = histogram2d_in,
-       output = histogram2d_out,
-       storage = main
-);
-
--------------------------------------------------------------------
---  BOX3D TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define BOX3D_IN_REP opaque
-# define BOX3D_OUT_REP opaque
-#else
-# define BOX3D_IN_REP box3d
-# define BOX3D_OUT_REP cstring
-#endif
-
-CREATEFUNCTION box3d_in(BOX3D_OUT_REP)
-       RETURNS BOX3D_IN_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION box3d_out(BOX3D_IN_REP)
-       RETURNS BOX3D_OUT_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATE TYPE box3d (
-       alignment = double,
-       internallength = 48,
-       input = box3d_in,
-       output = box3d_out
-);
-
--------------------------------------------------------------------
---  SPHEROID TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define SPHEROID_IN_REP opaque
-# define SPHEROID_OUT_REP opaque
-#else
-# define SPHEROID_IN_REP spheroid
-# define SPHEROID_OUT_REP cstring
-#endif
-
-CREATEFUNCTION spheroid_in(SPHEROID_OUT_REP)
-       RETURNS SPHEROID_IN_REP
-       AS '@MODULE_FILENAME@','ellipsoid_in'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION spheroid_out(SPHEROID_IN_REP)
-       RETURNS SPHEROID_OUT_REP
-       AS '@MODULE_FILENAME@','ellipsoid_out'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATE TYPE spheroid (
-       alignment = double,
-       internallength = 65,
-       input = spheroid_in,
-       output = spheroid_out
-);
-
--------------------------------------------------------------------
---  WKB TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define WKB_IN_REP opaque
-# define WKB_OUT_REP opaque
-#else
-# define WKB_IN_REP wkb
-# define WKB_OUT_REP cstring
-#endif
-
-CREATEFUNCTION wkb_in(WKB_OUT_REP)
-       RETURNS WKB_IN_REP
-       AS '@MODULE_FILENAME@','WKB_in'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION wkb_out(WKB_IN_REP)
-       RETURNS WKB_OUT_REP
-       AS '@MODULE_FILENAME@','WKB_out'
-       LANGUAGE 'C' WITH (isstrict);
-
-#if USE_VERSION > 73
-CREATEFUNCTION wkb_recv(internal)
-       RETURNS wkb
-       AS '@MODULE_FILENAME@','WKB_recv'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION wkb_send(wkb)
-       RETURNS bytea
-       AS '@MODULE_FILENAME@','WKBtoBYTEA'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-#endif
-
-CREATE TYPE wkb (
-       internallength = variable,
-       input = wkb_in,
-       output = wkb_out,
-#if USE_VERSION > 73
-       send = wkb_send,
-       receive = wkb_recv,
-#endif
-       storage = extended
-);
-
--------------------------------------------------------------------
---  CHIP TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define CHIP_IN_REP opaque
-# define CHIP_OUT_REP opaque
-#else
-# define CHIP_IN_REP chip
-# define CHIP_OUT_REP cstring
-#endif
-
-CREATEFUNCTION chip_in(CHIP_OUT_REP)
-       RETURNS CHIP_IN_REP
-       AS '@MODULE_FILENAME@','CHIP_in'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION chip_out(CHIP_IN_REP)
-       RETURNS CHIP_OUT_REP
-       AS '@MODULE_FILENAME@','CHIP_out'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATE TYPE chip (
-       alignment = double,
-       internallength = variable,
-       input = chip_in,
-       output = chip_out,
-       storage = extended
-);
-
--------------------------------------------------------------------
---  GEOMETRY TYPE
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-# define GEOMETRY_IN_REP opaque
-# define GEOMETRY_OUT_REP opaque
-#else
-# define GEOMETRY_IN_REP geometry
-# define GEOMETRY_OUT_REP cstring
-#endif
-
-CREATEFUNCTION geometry_in(GEOMETRY_OUT_REP)
-       RETURNS GEOMETRY_IN_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_out(GEOMETRY_IN_REP)
-       RETURNS GEOMETRY_OUT_REP
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-#if USE_VERSION >= 80
-CREATEFUNCTION geometry_analyze(internal)
-       RETURNS bool
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-#endif
-
-CREATE TYPE geometry (
-       alignment = double,
-       internallength = variable,
-       input = geometry_in,
-       output = geometry_out,
-#if USE_VERSION >= 80
-       analyze = geometry_analyze,
-#endif
-       storage = main
-);
-
-
--------------------------------------------------------------------
--- Workaround for old user defined variable length datatype 
--- default value bug. Should not be necessary > 7.2
--------------------------------------------------------------------
-#if USE_VERSION <= 72
-UPDATE pg_type SET typdefault = NULL WHERE typname = 'wkb';
-UPDATE pg_type SET typdefault = NULL WHERE typname = 'geometry';
-UPDATE pg_type SET typdefault = NULL WHERE typname = 'histogram2d';
-#endif
-
-
-
--------------------------------------------------------------------
--- GiST Selectivity Function
--------------------------------------------------------------------
-#if USE_VERSION == 71
-CREATEFUNCTION postgis_gist_sel(oid, oid, int2, opaque, int4)
-#elif USE_VERSION == 72
-CREATEFUNCTION postgis_gist_sel(opaque, oid,  opaque, int4)
-#else
-CREATEFUNCTION postgis_gist_sel (internal, oid, internal, int4)
-#endif
-       RETURNS float8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
--------------------------------------------------------------------
--- SPATIAL_REF_SYS
--------------------------------------------------------------------
-CREATE TABLE spatial_ref_sys (
-        srid integer not null primary key,
-        auth_name varchar(256), 
-        auth_srid integer, 
-        srtext varchar(2048),
-        proj4text varchar(2048) 
-);
-
--------------------------------------------------------------------
--- GEOMETRY_COLUMNS
--------------------------------------------------------------------
-CREATE TABLE geometry_columns (
-       f_table_catalog varchar(256) not null,
-       f_table_schema varchar(256) not null,
-       f_table_name varchar(256) not null,
-       f_geometry_column varchar(256) not null,
-       coord_dimension integer not null,
-       srid integer not null,
-       type varchar(30) not null,
-#if USE_VERSION < 80
-       attrelid oid,
-       varattnum int,
-       stats histogram2d,
-#endif
-       CONSTRAINT geometry_columns_pk primary key ( 
-               f_table_catalog, 
-               f_table_schema, 
-               f_table_name, 
-               f_geometry_column ) );
-
------------------------------------------------------------------------
--- POSTGIS_VERSION()
------------------------------------------------------------------------
-
-CREATEFUNCTION postgis_version() RETURNS text
-AS 'SELECT \'@POSTGIS_VERSION@\'::text AS version'
-LANGUAGE 'sql';
-
-CREATEFUNCTION postgis_lib_version() RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION postgis_geos_version() RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION postgis_proj_version() RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION postgis_scripts_installed() RETURNS text
-AS 'SELECT \'@POSTGIS_SCRIPTS_VERSION@\'::text AS version'
-LANGUAGE 'sql';
-
-CREATEFUNCTION postgis_scripts_released() RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION postgis_uses_stats() RETURNS bool
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION postgis_full_version() RETURNS text
-AS '
-DECLARE
-       libver text;
-       projver text;
-       geosver text;
-       usestats bool;
-       dbproc text;
-       relproc text;
-       fullver text;
-BEGIN
-       SELECT postgis_lib_version() INTO libver;
-       SELECT postgis_proj_version() INTO projver;
-       SELECT postgis_geos_version() INTO geosver;
-       SELECT postgis_uses_stats() INTO usestats;
-       SELECT postgis_scripts_installed() INTO dbproc;
-       SELECT postgis_scripts_released() INTO relproc;
-
-       fullver = \'POSTGIS="\' || libver || \'"\';
-
-       IF  geosver IS NOT NULL THEN
-               fullver = fullver || \' GEOS="\' || geosver || \'"\';
-       END IF;
-
-       IF  projver IS NOT NULL THEN
-               fullver = fullver || \' PROJ="\' || projver || \'"\';
-       END IF;
-
-       IF usestats THEN
-               fullver = fullver || \' USE_STATS\';
-       END IF;
-
-       fullver = fullver || \' DBPROC="\' || dbproc || \'"\';
-       fullver = fullver || \' RELPROC="\' || relproc || \'"\';
-
-       IF dbproc != relproc THEN
-               fullver = fullver || \' (needs proc upgrade)\';
-       END IF;
-
-       RETURN fullver;
-END
-' LANGUAGE 'plpgsql';
-
------------------------------------------------------------------------
--- FIND_SRID( <schema>, <table>, <geom col> )
------------------------------------------------------------------------
-CREATEFUNCTION find_srid(varchar,varchar,varchar) RETURNS int4 AS
-'DECLARE
-   schem text;
-   tabl text;
-   sr int4;
-BEGIN
-   IF $1 IS NULL THEN
-      RAISE EXCEPTION ''find_srid() - schema is NULL!'';
-   END IF;
-   IF $2 IS NULL THEN
-      RAISE EXCEPTION ''find_srid() - table name is NULL!'';
-   END IF;
-   IF $3 IS NULL THEN
-      RAISE EXCEPTION ''find_srid() - column name is NULL!'';
-   END IF;
-   schem = $1;
-   tabl = $2;
--- if the table contains a . and the schema is empty
--- split the table into a schema and a table
--- otherwise drop through to default behavior
-   IF ( schem = '''' and tabl LIKE ''%.%'' ) THEN
-     schem = substr(tabl,1,strpos(tabl,''.'')-1);
-     tabl = substr(tabl,length(schem)+2);
-   ELSE
-     schem = schem || ''%'';
-   END IF;
-
-   select SRID into sr from geometry_columns where f_table_schema like schem and f_table_name = tabl and f_geometry_column = $3;
-   IF NOT FOUND THEN
-       RAISE EXCEPTION ''find_srid() - couldnt find the corresponding SRID - is the geometry registered in the GEOMETRY_COLUMNS table?  Is there an uppercase/lowercase missmatch?'';
-   END IF;
-  return sr;
-END;
-'
-LANGUAGE 'plpgsql' WITH (iscachable); 
-
------------------------------------------------------------------------
--- GET_PROJ4_FROM_SRID( <srid> )
------------------------------------------------------------------------
-CREATEFUNCTION get_proj4_from_srid(integer) RETURNS text AS
-'SELECT proj4text::text FROM spatial_ref_sys WHERE srid= $1' 
-LANGUAGE 'sql' WITH (iscachable,isstrict);
-
-
------------------------------------------------------------------------
--- RENAME_GEOMETRY_TABLE_CONSTRAINTS()
------------------------------------------------------------------------
--- This function renames geometrytype and srid constraints
--- applied to spatial tables by old AddGeometryColumn to
--- new meaningful name 'enforce_geotype_<geomcolname>'
--- and 'enforce_srid_<geomcolname>'
--- Needs to be called only when upgrading from postgis < 0.8.3
------------------------------------------------------------------------
-CREATEFUNCTION rename_geometry_table_constraints() RETURNS text
-AS 
-'
-UPDATE pg_constraint 
-       SET conname = textcat(''enforce_geotype_'', a.attname)
-       FROM pg_attribute a
-       WHERE
-               a.attrelid = conrelid
-               AND a.attnum = conkey[1]
-               AND consrc LIKE ''((geometrytype(%) = %'';
-
-UPDATE pg_constraint
-       SET conname = textcat(''enforce_srid_'', a.attname)
-       FROM pg_attribute a
-       WHERE
-               a.attrelid = conrelid
-               AND a.attnum = conkey[1]
-               AND consrc LIKE ''(srid(% = %)'';
-
-SELECT ''spatial table constraints renamed''::text;
-
-' LANGUAGE 'SQL';
-
------------------------------------------------------------------------
--- FIX_GEOMETRY_COLUMNS() 
------------------------------------------------------------------------
--- This function will:
---
---     o try to fix the schema of records with an invalid one
---             (for PG>=73)
---
---     o link records to system tables through attrelid and varattnum
---             (for PG<80)
---
---     o delete all records for which no linking was possible
---             (for PG<80)
---     
--- 
------------------------------------------------------------------------
-CREATEFUNCTION fix_geometry_columns() RETURNS text
-AS 
-'
-DECLARE
-       result text;
-       linked integer;
-       deleted integer;
-#if USE_VERSION >= 73
-       foundschema integer;
-#endif
-BEGIN
-
-#if USE_VERSION >= 73
-       -- Since 7.3 schema support has been added.
-       -- Previous postgis versions used to put the database name in
-       -- the schema column. This needs to be fixed, so we try to 
-       -- set the correct schema for each geometry_colums record
-       -- looking at table, column, type and srid.
-       UPDATE geometry_columns SET f_table_schema = n.nspname
-               FROM pg_namespace n, pg_class c, pg_attribute a,
-                       pg_constraint sridcheck, pg_constraint typecheck
-                WHERE ( f_table_schema is NULL
-               OR f_table_schema = ''''
-                OR f_table_schema NOT IN (
-                        SELECT nspname::varchar
-                        FROM pg_namespace nn, pg_class cc, pg_attribute aa
-                        WHERE cc.relnamespace = nn.oid
-                        AND cc.relname = f_table_name::name
-                        AND aa.attrelid = cc.oid
-                        AND aa.attname = f_geometry_column::name))
-                AND f_table_name::name = c.relname
-                AND c.oid = a.attrelid
-                AND c.relnamespace = n.oid
-                AND f_geometry_column::name = a.attname
-                AND sridcheck.conrelid = c.oid
-                --AND sridcheck.conname = ''$1''
-               AND sridcheck.consrc LIKE ''(srid(% = %)''
-                AND typecheck.conrelid = c.oid
-                --AND typecheck.conname = ''$2''
-               AND typecheck.consrc LIKE
-       ''((geometrytype(%) = ''''%''''::text) OR (% IS NULL))''
-                AND sridcheck.consrc ~ textcat('' = '', srid::text)
-                AND typecheck.consrc ~ textcat('' = '''''', type::text)
-                AND NOT EXISTS (
-                        SELECT oid FROM geometry_columns gc
-                        WHERE c.relname::varchar = gc.f_table_name
-#if USE_VERSION >= 73
-                        AND n.nspname::varchar = gc.f_table_schema
-#endif
-                        AND a.attname::varchar = gc.f_geometry_column
-                );
-
-       GET DIAGNOSTICS foundschema = ROW_COUNT;
-#endif
-
-#if USE_VERSION >= 80
-       -- no linkage to system table needed
-       return ''fixed:''||foundschema::text;
-#endif
-
-       -- fix linking to system tables
-       UPDATE geometry_columns SET
-               attrelid = NULL,
-               varattnum = NULL,
-               stats = NULL;
-
-       UPDATE geometry_columns SET
-               attrelid = c.oid,
-               varattnum = a.attnum
-#if USE_VERSION >= 73
-               FROM pg_class c, pg_attribute a, pg_namespace n
-               WHERE n.nspname = f_table_schema::name
-               AND c.relname = f_table_name::name
-               AND c.relnamespace = n.oid
-#else // USE_VERSION < 73 
-               FROM pg_class c, pg_attribute a
-               WHERE c.relname = f_table_name::name
-#endif
-               AND a.attname = f_geometry_column::name
-               AND a.attrelid = c.oid;
-       
-       GET DIAGNOSTICS linked = ROW_COUNT;
-
-       -- remove stale records
-       DELETE FROM geometry_columns WHERE attrelid IS NULL;
-
-       GET DIAGNOSTICS deleted = ROW_COUNT;
-
-       result = 
-#if USE_VERSION >= 73
-               ''fixed:'' || foundschema::text ||
-#endif
-               '' linked:'' || linked::text || 
-               '' deleted:'' || deleted::text;
-
-       return result;
-
-END;
-'
-LANGUAGE 'plpgsql' ;
-
------------------------------------------------------------------------
--- PROBE_GEOMETRY_COLUMNS() 
------------------------------------------------------------------------
--- Fill the geometry_columns table with values probed from the system
--- catalogues. 3d flag can not be probed, it defaults to 2
---
--- Note that bogus records already in geometry_columns are not
--- overridden (a check for schema.table.column is performed), so
--- to have a fresh probe backup your geometry_column, delete from
--- it and probe.
------------------------------------------------------------------------
-CREATEFUNCTION probe_geometry_columns() RETURNS text AS
-'
-DECLARE
-       inserted integer;
-       oldcount integer;
-       probed integer;
-       stale integer;
-BEGIN
-
-       SELECT count(*) INTO oldcount FROM geometry_columns;
-
-       SELECT count(*) INTO probed
-               FROM pg_class c, pg_attribute a, pg_type t, 
-#if USE_VERSION >= 73
-                       pg_namespace n,
-#endif
-                       pg_constraint sridcheck, pg_constraint typecheck
-               WHERE t.typname = ''geometry''
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-#if USE_VERSION >= 73
-               AND c.relnamespace = n.oid
-               AND sridcheck.connamespace = n.oid
-               AND typecheck.connamespace = n.oid
-#endif
-               AND sridcheck.conrelid = c.oid
-               --AND sridcheck.conname = ''$1''
-               AND sridcheck.consrc LIKE ''(srid(% = %)''
-               AND typecheck.conrelid = c.oid
-               --AND typecheck.conname = ''$2'';
-               AND typecheck.consrc LIKE
-       ''((geometrytype(%) = ''''%''''::text) OR (% IS NULL))''
-               ;
-
-       INSERT INTO geometry_columns SELECT
-               ''''::varchar as f_table_catalogue,
-#if USE_VERSION >= 73
-               n.nspname::varchar as f_table_schema,
-#else
-               ''''::varchar as f_table_schema,
-#endif
-               c.relname::varchar as f_table_name,
-               a.attname::varchar as f_geometry_column,
-               2 as coord_dimension,
-               trim(both  '' =)'' from substr(sridcheck.consrc,
-                       strpos(sridcheck.consrc, ''='')))::integer as srid,
-               trim(both '' =)'''''' from substr(typecheck.consrc, 
-                       strpos(typecheck.consrc, ''=''),
-                       strpos(typecheck.consrc, ''::'')-
-                       strpos(typecheck.consrc, ''='')
-                       ))::varchar as type,
-#if USE_VERSION < 80
-               a.attrelid,
-               a.attnum as varattnum,
-               null::histogram2d as stats
-#endif
-               FROM pg_class c, pg_attribute a, pg_type t, 
-#if USE_VERSION >= 73
-                       pg_namespace n,
-#endif
-                       pg_constraint sridcheck, pg_constraint typecheck
-               WHERE t.typname = ''geometry''
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-#if USE_VERSION >= 73
-               AND c.relnamespace = n.oid
-               AND sridcheck.connamespace = n.oid
-               AND typecheck.connamespace = n.oid
-#endif
-               AND sridcheck.conrelid = c.oid
-               --AND sridcheck.conname = ''$1''
-               AND sridcheck.consrc LIKE ''(srid(% = %)''
-               AND typecheck.conrelid = c.oid
-               --AND typecheck.conname = ''$2''
-               AND typecheck.consrc LIKE
-       ''((geometrytype(%) = ''''%''''::text) OR (% IS NULL))''
-
-                AND NOT EXISTS (
-                        SELECT oid FROM geometry_columns gc
-                        WHERE c.relname::varchar = gc.f_table_name
-#if USE_VERSION >= 73
-                        AND n.nspname::varchar = gc.f_table_schema
-#endif
-                        AND a.attname::varchar = gc.f_geometry_column
-                );
-
-       GET DIAGNOSTICS inserted = ROW_COUNT;
-
-       IF oldcount > probed THEN
-               stale = oldcount-probed;
-       ELSE
-               stale = 0;
-       END IF;
-
-        RETURN ''probed:''||probed||
-               '' inserted:''||inserted||
-               '' conflicts:''||probed-inserted||
-               '' stale:''||stale;
-END
-
-' LANGUAGE 'plpgsql';
-
------------------------------------------------------------------------
--- FIND_EXTENT( <schema name>, <table name>, <column name> )
------------------------------------------------------------------------
-CREATEFUNCTION find_extent(text,text,text) RETURNS box3d AS
-'
-DECLARE
-       schemaname alias for $1;
-       tablename alias for $2;
-       columnname alias for $3;
-       okay boolean;
- myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE ''SELECT extent("''||columnname||''") FROM "''||schemaname||''"."''||tablename||''"'' LOOP
-               return myrec.extent;
-       END LOOP; 
-END;
-'
-LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- FIND_EXTENT( <table name>, <column name> )
------------------------------------------------------------------------
-CREATEFUNCTION find_extent(text,text) RETURNS box3d AS
-'
-DECLARE
-       tablename alias for $1;
-       columnname alias for $2;
-       okay boolean;
- myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE ''SELECT extent("''||columnname||''") FROM "''||tablename||''"'' LOOP
-               return myrec.extent;
-       END LOOP; 
-END;
-'
-LANGUAGE 'plpgsql' WITH (isstrict);
-
-
------------------------------------------------------------------------
--- TRANSFORM ( <geometry>, <srid> )
------------------------------------------------------------------------
---
--- Test:
---
--- trans=# select * from spatial_ref_sys ;
---
---  srid |   auth_name   | auth_srid | srtext | proj4text 
--- ------+---------------+-----------+--------+--------------------------------------------------------------------------
---     1 | latlong WGS84 |         1 |        | +proj=longlat +datum=WGS84
---     2 | BC albers     |         2 |        | proj=aea ellps=GRS80 lon_0=-126 lat_0=45 lat_1=50 lat_2=58.5 x_0=1000000
---
--- select transform( 'SRID=1;POINT(-120.8 50.3)', 2);
---      -> 'SRID=2;POINT(1370033.37046971 600755.810968684)'
---
------------------------------------------------------------------------
-CREATEFUNCTION transform_geometry(geometry,text,text,int)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','transform_geom'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION transform(geometry,integer) RETURNS geometry AS
-'BEGIN
- RETURN transform_geometry( $1 , get_proj4_from_srid(SRID( $1 ) ), get_proj4_from_srid( $2 ), $2 );
- END;'
-LANGUAGE 'plpgsql' WITH (iscachable,isstrict);
-
-
-
------------------------------------------------------------------------
--- COMMON FUNCTIONS
------------------------------------------------------------------------
-
-CREATEFUNCTION srid(chip)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','srid_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION height(chip)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','height_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION factor(chip)
-       RETURNS FLOAT4
-       AS '@MODULE_FILENAME@','factor_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION width(chip)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','width_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION datatype(chip)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','datatype_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION compression(chip)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','compression_chip'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION setSRID(chip,int4)
-       RETURNS chip
-       AS '@MODULE_FILENAME@','setsrid_chip'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION setfactor(chip,float4)
-       RETURNS chip
-       AS '@MODULE_FILENAME@','setfactor_chip'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION geometry(CHIP)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','CHIP_to_geom'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION box3d(geometry)
-       RETURNS box3d
-       AS '@MODULE_FILENAME@','get_bbox_of_geometry'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION box(geometry)
-       RETURNS BOX
-       AS '@MODULE_FILENAME@','geometry2box'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION geometry(box3d)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','get_geometry_of_bbox'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION geometry(text)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_text'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION expand(box3d,float8)
-       RETURNS box3d
-       AS '@MODULE_FILENAME@','expand_bbox'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION expand(geometry,float8)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','expand_geometry'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
---
--- Functions for converting to WKB
---
-
-CREATEFUNCTION asbinary(geometry)
-       RETURNS wkb
-       AS '@MODULE_FILENAME@','asbinary_simple'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION asbinary(geometry,TEXT)
-       RETURNS wkb
-       AS '@MODULE_FILENAME@','asbinary_specify'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION bytea(wkb)
-       RETURNS bytea
-       AS '@MODULE_FILENAME@','WKBtoBYTEA'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION geometry(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','geometryfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION GeomFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','geometryfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION GeomFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','geometryfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION PointFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION PointFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION LineFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','LinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION LineFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','LinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-
-CREATEFUNCTION LinestringFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','LinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION LinestringFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','LinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION PolyFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION PolyFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION PolygonFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION PolygonFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-
-CREATEFUNCTION MPointFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MPointFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-
-CREATEFUNCTION MultiPointFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MultiPointFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MultiLineFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MultiLineFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-       
-CREATEFUNCTION MLineFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MLineFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MPolyFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MPolyFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-CREATEFUNCTION MultiPolyFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION MultiPolyFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-
-       
-CREATEFUNCTION GeomCollFromWKB(wkb,int)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','GCfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-
-CREATEFUNCTION GeomCollFromWKB(wkb)
-       RETURNS GEOMETRY
-       AS '@MODULE_FILENAME@','GCfromWKB_SRID'
-       LANGUAGE 'C' WITH (iscachable,isstrict);
-       
-       
--- CREATEFUNCTION index_thing(geometry)
--- RETURNS BOOL
--- AS '@MODULE_FILENAME@'
--- LANGUAGE 'C' WITH (isstrict);
-
---
--- Debugging functions
---
-
-CREATEFUNCTION npoints(geometry)
-       RETURNS int4
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION nrings(geometry)
-       RETURNS int4
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict) ;
-
-CREATEFUNCTION mem_size(geometry)
-       RETURNS int4
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-
-CREATEFUNCTION summary(geometry)
-       RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION translate(geometry,float8,float8,float8)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict) ;
-
-CREATEFUNCTION dimension(geometry)
-       RETURNS int4
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict) ;
-
-CREATEFUNCTION geometrytype(geometry)
-       RETURNS text
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION envelope(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION x(geometry)
-       RETURNS float8
-       AS '@MODULE_FILENAME@','x_point'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION y(geometry)
-       RETURNS float8
-       AS '@MODULE_FILENAME@','y_point'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION z(geometry)
-       RETURNS float8
-       AS '@MODULE_FILENAME@','z_point'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION numpoints(geometry)
-       RETURNS integer
-       AS '@MODULE_FILENAME@','numpoints_linestring'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION pointn(geometry,integer)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','pointn_linestring'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION exteriorring(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','exteriorring_polygon'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION numinteriorrings(geometry)
-       RETURNS integer
-       AS '@MODULE_FILENAME@','numinteriorrings_polygon'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION interiorringn(geometry,integer)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','interiorringn_polygon'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION numgeometries(geometry)
-       RETURNS integer
-       AS '@MODULE_FILENAME@','numgeometries_collection'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometryn(geometry,integer)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometryn_collection'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION max_distance(geometry,geometry)
-       RETURNS float8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION optimistic_overlap(geometry,geometry,FLOAT8)
-       RETURNS BOOL
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION segmentize(geometry,FLOAT8)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION distance(geometry,geometry)
-       RETURNS float8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION astext(geometry)
-       RETURNS TEXT
-       AS '@MODULE_FILENAME@','astext_geometry'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION srid(geometry)
-       RETURNS int4
-       AS '@MODULE_FILENAME@','srid_geom'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometryfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-       
-CREATEFUNCTION geometryfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION geomfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION geomfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION polyfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_poly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION polygonfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_poly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION polygonfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_poly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-CREATEFUNCTION mpolyfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION linefromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_line'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-       
-CREATEFUNCTION mlinefromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mline'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multilinestringfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mline'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multilinestringfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mline'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-CREATEFUNCTION pointfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_point'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION mpointfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multipointfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multipointfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-CREATEFUNCTION geomcollfromtext(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_gc'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION setSRID(geometry,int4)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION polyfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_poly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-
-CREATEFUNCTION mpolyfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multipolygonfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION multipolygonfromtext(geometry,int)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-CREATEFUNCTION linefromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_line'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-CREATEFUNCTION linestringfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_line'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION linestringfromtext(geometry,int)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_line'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION mlinefromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mline'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION pointfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_point'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION mpointfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION geomcollfromtext(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geometry_from_text_gc'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-
-CREATEFUNCTION isempty(geometry)
-       RETURNS boolean
-       AS '@MODULE_FILENAME@','isempty'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION issimple(geometry)
-       RETURNS boolean
-       AS '@MODULE_FILENAME@','issimple'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-       
-
-CREATEFUNCTION equals(geometry,geometry)
-       RETURNS boolean
-       AS '@MODULE_FILENAME@','geomequals'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-
---
--- Special spheroid functions
---
-
-CREATEFUNCTION length_spheroid(geometry,spheroid)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','length_ellipsoid'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION length3d_spheroid(geometry,spheroid)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','length3d_ellipsoid'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION distance_spheroid(geometry,geometry,spheroid)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','distance_ellipsoid'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION distance_sphere(geometry,geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@', 'distance_sphere'
-       LANGUAGE 'C' WITH (isstrict);
-
---
--- Generic operations
---
-
-CREATEFUNCTION multi(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','fluffType'
-       LANGUAGE 'C' WITH (isstrict);
-       
-CREATEFUNCTION length3d(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION length(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','length2d'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION area2d(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION area(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','area2d'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION perimeter3d(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION perimeter(geometry)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','perimeter2d'
-       LANGUAGE 'C' WITH (isstrict);
-
----CREATEFUNCTION truly_inside(geometry,geometry)
----    RETURNS bool
----    AS '@MODULE_FILENAME@'
----    LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION point_inside_circle(geometry,float8,float8,float8)
-       RETURNS bool
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION startpoint(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION endpoint(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION isclosed(geometry)
-       RETURNS boolean
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION centroid(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-       
-CREATEFUNCTION isring(geometry)
-       RETURNS boolean
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION pointonsurface(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C' WITH (isstrict);
-       
-
---
--- BBox operations
---
-
-CREATEFUNCTION xmin(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_xmin'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION ymin(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_ymin'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION zmin(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_zmin'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION xmax(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_xmax'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION ymax(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_ymax'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION zmax(box3d)
-       RETURNS FLOAT8
-       AS '@MODULE_FILENAME@','box3d_zmax'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
-CREATEFUNCTION box3dtobox(box3d)
-       RETURNS BOX
-       AS '@MODULE_FILENAME@','box3dtobox'
-       LANGUAGE 'C' WITH (isstrict,iscachable);
-
---
--- Aggregate functions
---
-
-CREATEFUNCTION geom_accum (geometry[],geometry)
-       RETURNS geometry[]
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION combine_bbox(box3d,geometry)
-       RETURNS box3d
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATE AGGREGATE extent(
-       sfunc = combine_bbox,
-       basetype = geometry,
-       stype = box3d
-       );
-
-CREATEFUNCTION collector(geometry,geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATE AGGREGATE memcollect(
-       sfunc = collector,
-       basetype = geometry,
-       stype = geometry
-       );
-
-CREATEFUNCTION collect_garray (geometry[])
-        RETURNS geometry
-        AS '@MODULE_FILENAME@'
-        LANGUAGE 'C';
-
-CREATE AGGREGATE collect (
-       sfunc = geom_accum,
-       basetype = geometry,
-       stype = geometry[],
-       finalfunc = collect_garray
-       );
-
-
---
--- Operator definitions
---
-
-CREATEFUNCTION geometry_overleft(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_overright(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_left(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_right(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_contain(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_contained(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_overlap(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_same(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
---
--- Sorting functions
---
-
-CREATEFUNCTION geometry_lt(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_le(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_gt(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_ge(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_eq(geometry, geometry) 
-       RETURNS bool
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geometry_cmp(geometry, geometry) 
-       RETURNS integer
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
---
--- Two dimensional to three dimensional forces
--- 
-
-CREATEFUNCTION force_2d(geometry) 
-       RETURNS geometry
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION force_3d(geometry) 
-       RETURNS geometry
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
---
--- Force collection
---
-
-CREATEFUNCTION force_collection(geometry) 
-       RETURNS geometry
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C' WITH (isstrict);
-
--- 
--- Operator definitions
---
-
-CREATE OPERATOR << (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_left,
-   COMMUTATOR = '>>',
-   RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR &< (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_overleft,
-   COMMUTATOR = '&>',
-   RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR && (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_overlap,
-   COMMUTATOR = '&&',
-   RESTRICT = postgis_gist_sel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR &> (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_overright,
-   COMMUTATOR = '&<',
-   RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR >> (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_right,
-   COMMUTATOR = '<<',
-   RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR ~= (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_same,
-   COMMUTATOR = '~=', 
-   RESTRICT = eqsel, JOIN = eqjoinsel
-);
-
-CREATE OPERATOR @ (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_contained,
-   COMMUTATOR = '~',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR ~ (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_contain,
-   COMMUTATOR = '@',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
---
--- Sorting operators for Btree
---
-
-CREATE OPERATOR < (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_lt,
-   COMMUTATOR = '>', NEGATOR = '>=',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR <= (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_le,
-   COMMUTATOR = '>=', NEGATOR = '>',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR = (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_eq,
-   COMMUTATOR = '=', -- we might implement a faster negator here
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR >= (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_ge,
-   COMMUTATOR = '<=', NEGATOR = '<',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-CREATE OPERATOR > (
-   LEFTARG = GEOMETRY, RIGHTARG = GEOMETRY, PROCEDURE = geometry_gt,
-   COMMUTATOR = '<', NEGATOR = '<=',
-   RESTRICT = contsel, JOIN = contjoinsel
-);
-
---
--- GEOS Functions
---
-
-
-CREATEFUNCTION intersection(geometry,geometry)
-   RETURNS geometry
-   AS '@MODULE_FILENAME@','intersection'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION buffer(geometry,float8)
-   RETURNS geometry
-   AS '@MODULE_FILENAME@','buffer'
-   LANGUAGE 'C' WITH (isstrict);
-   
-CREATEFUNCTION convexhull(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','convexhull'
-       LANGUAGE 'C' WITH (isstrict);
-  
-  
-CREATEFUNCTION difference(geometry,geometry)
-       RETURNS geometry
-        AS '@MODULE_FILENAME@','difference'
-       LANGUAGE 'C' WITH (isstrict);
-   
-CREATEFUNCTION boundary(geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','boundary'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION symdifference(geometry,geometry)
-        RETURNS geometry
-        AS '@MODULE_FILENAME@','symdifference'
-   LANGUAGE 'C' WITH (isstrict);
-
-
-CREATEFUNCTION symmetricdifference(geometry,geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','symdifference'
-       LANGUAGE 'C' WITH (isstrict);
-
-
-CREATEFUNCTION GeomUnion(geometry,geometry)
-       RETURNS geometry
-       AS '@MODULE_FILENAME@','geomunion'
-       LANGUAGE 'C' WITH (isstrict);
-
-CREATE AGGREGATE MemGeomUnion (
-       basetype = geometry,
-       sfunc = geomunion,
-       stype = geometry
-       );
-
-CREATEFUNCTION unite_garray (geometry[])
-       RETURNS geometry
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C'; 
-
-CREATE AGGREGATE GeomUnion (
-       sfunc = geom_accum,
-       basetype = geometry,
-       stype = geometry[],
-       finalfunc = unite_garray
-       );
-
-
-CREATEFUNCTION relate(geometry,geometry)
-   RETURNS text
-   AS '@MODULE_FILENAME@','relate_full'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION relate(geometry,geometry,text)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@','relate_pattern'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION disjoint(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION touches(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION intersects(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION crosses(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION within(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION contains(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION overlaps(geometry,geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION isvalid(geometry)
-   RETURNS boolean
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION geosnoop(geometry)
-   RETURNS geometry
-   AS '@MODULE_FILENAME@', 'GEOSnoop'
-   LANGUAGE 'C' WITH (isstrict);
-   
-
---
--- Algorithms
---
-
-CREATEFUNCTION simplify(geometry, float8)
-   RETURNS geometry
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
-CREATEFUNCTION line_interpolate_point(geometry, float8)
-   RETURNS geometry
-   AS '@MODULE_FILENAME@'
-   LANGUAGE 'C' WITH (isstrict);
-
--------------------------------------------------------------------
--- GiST support functions
--------------------------------------------------------------------
-
-#if USE_VERSION < 73
-#define OPAQUE_TYPE opaque
-#else
-#define OPAQUE_TYPE internal
-#endif
-
-CREATEFUNCTION ggeometry_consistent(OPAQUE_TYPE,geometry,int4) 
-       RETURNS bool 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-CREATEFUNCTION ggeometry_compress(OPAQUE_TYPE) 
-       RETURNS OPAQUE_TYPE 
-       AS '@MODULE_FILENAME@'
-       LANGUAGE 'C';
-
-CREATEFUNCTION rtree_decompress(OPAQUE_TYPE) 
-       RETURNS OPAQUE_TYPE
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-#if USE_VERSION == 71
-CREATEFUNCTION ggeometry_penalty(OPAQUE_TYPE,OPAQUE_TYPE,OPAQUE_TYPE) 
-#else
-CREATEFUNCTION gbox_penalty(OPAQUE_TYPE,OPAQUE_TYPE,OPAQUE_TYPE) 
-#endif
-       RETURNS OPAQUE_TYPE 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-#if USE_VERSION == 71
-CREATEFUNCTION ggeometry_picksplit(OPAQUE_TYPE, OPAQUE_TYPE) 
-#else
-CREATEFUNCTION gbox_picksplit(OPAQUE_TYPE, OPAQUE_TYPE) 
-#endif
-       RETURNS OPAQUE_TYPE 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-#if USE_VERSION == 71
-CREATEFUNCTION ggeometry_union(bytea, OPAQUE_TYPE) 
-#else
-CREATEFUNCTION gbox_union(bytea, OPAQUE_TYPE) 
-#endif
-       RETURNS OPAQUE_TYPE 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-#if USE_VERSION == 71
-CREATEFUNCTION ggeometry_same(OPAQUE_TYPE, OPAQUE_TYPE, OPAQUE_TYPE) 
-#else
-CREATEFUNCTION gbox_same(box, box, OPAQUE_TYPE) 
-#endif
-       RETURNS OPAQUE_TYPE 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
--------------------------------------------------------------------
--- R-Tree support functions
--------------------------------------------------------------------
-
-CREATEFUNCTION geometry_union(geometry,geometry) 
-       RETURNS geometry 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-CREATEFUNCTION geometry_inter(geometry,geometry) 
-       RETURNS geometry 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-CREATEFUNCTION geometry_size(geometry,opaque) 
-       RETURNS float4 
-       AS '@MODULE_FILENAME@' 
-       LANGUAGE 'C';
-
-
-#if USE_VERSION == 71
-
---
--- Create opclass index binding entries.
---
-
-INSERT INTO pg_opclass (opcname, opcdeftype)
-       SELECT 'gist_geometry_ops', oid
-       FROM pg_type
-       WHERE typname = 'geometry';
-
-SELECT o.oid AS opoid, o.oprname
-       INTO TABLE rt_ops_tmp
-       FROM pg_operator o, pg_type t
-       WHERE o.oprleft = t.oid AND t.typname = 'geometry';
-
--- box_left
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) 
-       SELECT am.oid, opcl.oid, c.opoid, 1
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '<<';
-
--- box_overleft
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) 
-       SELECT am.oid, opcl.oid, c.opoid, 2
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '&<';
-
--- box_overlap
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) 
-       SELECT am.oid, opcl.oid, c.opoid, 3
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '&&';
-
--- box_overright
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) 
-       SELECT am.oid, opcl.oid, c.opoid, 4
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '&>';
-
--- box_right
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
-       SELECT am.oid, opcl.oid, c.opoid, 5
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '>>';
-
--- box_same
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) 
-       SELECT am.oid, opcl.oid, c.opoid, 6
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '~=';
-
--- box_contains
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
-       SELECT am.oid, opcl.oid, c.opoid, 7
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '~';
-
--- box_contained
-INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
-       SELECT am.oid, opcl.oid, c.opoid, 8
-       FROM pg_am am, pg_opclass opcl, rt_ops_tmp c
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops' 
-               AND c.oprname = '@';
-
-DROP TABLE rt_ops_tmp;
-
---
--- Add the entries to amproc for the support methods.
--- Note the amprocnum numbers associated with each are specific!
---
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 1
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_consistent';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 2
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_union';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 3
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_compress';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 4
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'rtree_decompress';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 5
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_penalty';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 6
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_picksplit';
-
-INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
-       SELECT am.oid, opcl.oid, pro.oid, 7
-       FROM pg_am am, pg_opclass opcl, pg_proc pro
-       WHERE amname = 'gist' AND opcname = 'gist_geometry_ops'
-               AND proname = 'ggeometry_same';
-
-#elsif USE_VERSION == 72
-
---
--- Create opclass index binding entries.
---
-
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
-    VALUES (
-        (SELECT oid FROM pg_am WHERE amname = 'gist'),
-        'gist_geometry_ops',
-        (SELECT oid FROM pg_type WHERE typname = 'geometry'),
-        true,
-        (SELECT oid FROM pg_type WHERE typname = 'box'));
-
--- drop table rt_ops_tmp;
-
-SELECT o.oid AS opoid, o.oprname
-       INTO TABLE rt_ops_tmp
-       FROM pg_operator o, pg_type t
-       WHERE o.oprleft = t.oid 
-               AND t.typname = 'geometry';
-
--- poly_left
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) 
-   SELECT opcl.oid, 1, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '<<';
-
--- poly_overleft
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) 
-   SELECT opcl.oid, 2, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '&<';
-
--- poly_overlap
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) 
-   SELECT opcl.oid, 3, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '&&';
-
--- poly_overright
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) 
-   SELECT opcl.oid, 4, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '&>';
-
--- poly_right
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
-   SELECT opcl.oid, 5, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '>>';
-
--- poly_same
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) 
-   SELECT opcl.oid, 6, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '~=';
-
--- poly_contains
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
-   SELECT opcl.oid, 7, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '~';
-
--- poly_contained
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
-   SELECT opcl.oid, 8, true, c.opoid
-   FROM pg_opclass opcl, rt_ops_tmp c
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops' 
-      and c.oprname = '@';
-
-DROP TABLE rt_ops_tmp;
-
--- add the entries to amproc for the support methods
--- note the amprocnum numbers associated with each are specific!
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 1, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'ggeometry_consistent';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 2, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'gbox_union';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 3, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'ggeometry_compress';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 4, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'rtree_decompress';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 5, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'gbox_penalty';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 6, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'gbox_picksplit';
-
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
-   SELECT opcl.oid, 7, pro.oid
-   FROM pg_opclass opcl, pg_proc pro
-   WHERE
-      opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
-      and opcname = 'gist_geometry_ops'
-      and proname = 'gbox_same';
-
-#else // USE_VERSION >= 73
-
---
--- Create opclass index bindings 
---
-
-CREATE OPERATOR CLASS gist_geometry_ops
-       DEFAULT FOR TYPE geometry USING gist AS
-       OPERATOR        1       <<      RECHECK,
-       OPERATOR        2       &<      RECHECK,
-       OPERATOR        3       &&      RECHECK,
-       OPERATOR        4       &>      RECHECK,
-       OPERATOR        5       >>      RECHECK,
-       OPERATOR        6       ~=      RECHECK,
-       OPERATOR        7       ~       RECHECK,
-       OPERATOR        8       @       RECHECK,
-       FUNCTION        1       ggeometry_consistent (internal, geometry, int4),
-       FUNCTION        2       gbox_union (bytea, internal),
-       FUNCTION        3       ggeometry_compress (internal),
-       FUNCTION        4       rtree_decompress (internal),
-       FUNCTION        5       gbox_penalty (internal, internal, internal),
-       FUNCTION        6       gbox_picksplit (internal, internal),
-       FUNCTION        7       gbox_same (box, box, internal);
-
-UPDATE pg_opclass 
-       SET opckeytype = (select oid from pg_type where typname = 'box') 
-       WHERE opcname = 'gist_geometry_ops';
-
-#if USE_VERSION >= 74
-
-CREATE OPERATOR CLASS btree_geometry_ops
-       DEFAULT FOR TYPE geometry USING btree AS
-       OPERATOR        1       < ,
-       OPERATOR        2       <= ,
-       OPERATOR        3       = ,
-       OPERATOR        4       >= ,
-       OPERATOR        5       > ,
-       FUNCTION        1       geometry_cmp (geometry, geometry);
-
-#endif // USE_VERSION >= 74
-
-
-#endif // USE_VERSION >= 73
-
-
------------------------------------------------------------------------
--- 7.3+ explicit casting definitions
------------------------------------------------------------------------
-#if USE_VERSION >= 73
---CREATE CAST ( chip AS geometry ) WITH FUNCTION geometry(chip) AS IMPLICIT;
-CREATE CAST ( geometry AS box3d ) WITH FUNCTION box3d(geometry) AS IMPLICIT;
-CREATE CAST ( geometry AS box ) WITH FUNCTION box(geometry) AS IMPLICIT;
-CREATE CAST ( box3d AS geometry ) WITH FUNCTION geometry(box3d) AS IMPLICIT;
-CREATE CAST ( text AS geometry) WITH FUNCTION geometry(text) AS IMPLICIT;
-CREATE CAST ( wkb AS bytea ) WITH FUNCTION bytea(wkb) AS IMPLICIT;
-CREATE CAST ( box3d AS box ) WITH FUNCTION box3dtobox(box3d);
-CREATE CAST ( geometry AS text ) WITH FUNCTION astext(geometry);
-#endif
-
------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN
---   <catalogue>, <schema>, <table>, <column>, <srid>, <type>, <dim>
------------------------------------------------------------------------
---
--- Type can be one of geometry, GEOMETRYCOLLECTION, POINT, MULTIPOINT, POLYGON,
--- MULTIPOLYGON, LINESTRING, or MULTILINESTRING.
---
--- Types (except geometry) are checked for consistency using a CHECK constraint
--- uses SQL ALTER TABLE command to add the geometry column to the table.
--- Addes a row to geometry_columns.
--- Addes a constraint on the table that all the geometries MUST have the same 
--- SRID. Checks the coord_dimension to make sure its between 0 and 3.
--- Should also check the precision grid (future expansion).
--- Calls fix_geometry_columns() at the end.
---
------------------------------------------------------------------------
-CREATEFUNCTION AddGeometryColumn(varchar,varchar,varchar,varchar,integer,varchar,integer)
-       RETURNS text
-       AS 
-'
-DECLARE
-       catalog_name alias for $1;
-       schema_name alias for $2;
-       table_name alias for $3;
-       column_name alias for $4;
-       new_srid alias for $5;
-       new_type alias for $6;
-       new_dim alias for $7;
-#if USE_VERSION >= 73
-       rec RECORD;
-       schema_ok bool;
-       real_schema name;
-#endif
-       fixgeomres text;
-
-BEGIN
-
-       IF ( not ( (new_type =''GEOMETRY'') or
-                  (new_type =''GEOMETRYCOLLECTION'') or
-                  (new_type =''POINT'') or 
-                  (new_type =''MULTIPOINT'') or
-                  (new_type =''POLYGON'') or
-                  (new_type =''MULTIPOLYGON'') or
-                  (new_type =''LINESTRING'') or
-                  (new_type =''MULTILINESTRING'')) )
-       THEN
-               RAISE EXCEPTION ''Invalid type name - valid ones are: 
-                       GEOMETRY, GEOMETRYCOLLECTION, POINT, 
-                       MULTIPOINT, POLYGON, MULTIPOLYGON, 
-                       LINESTRING, or MULTILINESTRING '';
-               return ''fail'';
-       END IF;
-
-       IF ( (new_dim >3) or (new_dim <0) ) THEN
-               RAISE EXCEPTION ''invalid dimension'';
-               return ''fail'';
-       END IF;
-
-#if USE_VERSION >= 73
-       IF ( schema_name != '''' ) THEN
-               schema_ok = ''f'';
-               FOR rec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
-                       schema_ok := ''t'';
-               END LOOP;
-
-               if ( schema_ok <> ''t'' ) THEN
-                       RAISE NOTICE ''Invalid schema name - using current_schema()'';
-                       SELECT current_schema() into real_schema;
-               ELSE
-                       real_schema = schema_name;
-               END IF;
-
-       ELSE
-               SELECT current_schema() into real_schema;
-       END IF;
-#endif
-
-
-       -- Add geometry column
-
-       EXECUTE ''ALTER TABLE '' ||
-#if USE_VERSION >= 73
-               quote_ident(real_schema) || ''.'' || quote_ident(table_name)
-#else
-               quote_ident(table_name)
-#endif
-               || '' ADD COLUMN '' || quote_ident(column_name) || 
-               '' geometry '';
-
-
-       -- Delete stale record in geometry_column (if any)
-
-       EXECUTE ''DELETE FROM geometry_columns WHERE
-               f_table_catalog = '' || quote_literal('''') || 
-               '' AND f_table_schema = '' ||
-#if USE_VERSION >= 73
-               quote_literal(real_schema) || 
-#else
-               quote_literal('''') || 
-#endif
-               '' AND f_table_name = '' || quote_literal(table_name) ||
-               '' AND f_geometry_column = '' || quote_literal(column_name);
-
-
-       -- Add record in geometry_column 
-
-       EXECUTE ''INSERT INTO geometry_columns VALUES ('' ||
-               quote_literal('''') || '','' ||
-#if USE_VERSION >= 73
-               quote_literal(real_schema) || '','' ||
-#else
-               quote_literal('''') || '','' ||
-#endif
-               quote_literal(table_name) || '','' ||
-               quote_literal(column_name) || '','' ||
-               new_dim || '','' || new_srid || '','' ||
-               quote_literal(new_type) || '')'';
-
-       -- Add table checks
-
-       EXECUTE ''ALTER TABLE '' || 
-#if USE_VERSION >= 73
-               quote_ident(real_schema) || ''.'' || quote_ident(table_name)
-#else
-               quote_ident(table_name)
-#endif
-               || '' ADD CONSTRAINT "enforce_srid_'' || 
-               column_name || ''" CHECK (SRID('' || quote_ident(column_name) ||
-               '') = '' || new_srid || '')'' ;
-
-       IF (not(new_type = ''GEOMETRY'')) THEN
-               EXECUTE ''ALTER TABLE '' || 
-#if USE_VERSION >= 73
-               quote_ident(real_schema) || ''.'' || quote_ident(table_name)
-#else
-               quote_ident(table_name)
-#endif
-               || '' ADD CONSTRAINT "enforce_geotype_'' ||
-               column_name || ''" CHECK (geometrytype('' ||
-               quote_ident(column_name) || '')='' ||
-               quote_literal(new_type) || '' OR ('' ||
-               quote_ident(column_name) || '') is null)'';
-       END IF;
-
-       SELECT fix_geometry_columns() INTO fixgeomres;
-
-       return 
-#if USE_VERSION >= 73
-               real_schema || ''.'' || 
-#endif
-               table_name || ''.'' || column_name ||
-               '' SRID:'' || new_srid ||
-               '' TYPE:'' || new_type || ''\n '' ||
-               ''geometry_column '' || fixgeomres;
-END;
-' LANGUAGE 'plpgsql' WITH (isstrict);
-
-----------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN ( <schema>, <table>, <column>, <srid>, <type>, <dim> )
-----------------------------------------------------------------------------
---
--- This is a wrapper to the real AddGeometryColumn, for use
--- when catalogue is undefined
---
-----------------------------------------------------------------------------
-CREATEFUNCTION AddGeometryColumn(varchar,varchar,varchar,integer,varchar,integer) RETURNS text AS '
-DECLARE
-       ret  text;
-BEGIN
-       SELECT AddGeometryColumn('''',$1,$2,$3,$4,$5,$6) into ret;
-       RETURN ret;
-END;
-' LANGUAGE 'plpgsql' WITH (isstrict);
-
-----------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN ( <table>, <column>, <srid>, <type>, <dim> )
-----------------------------------------------------------------------------
---
--- This is a wrapper to the real AddGeometryColumn, for use
--- when catalogue and schema are undefined
---
-----------------------------------------------------------------------------
-CREATEFUNCTION AddGeometryColumn(varchar,varchar,integer,varchar,integer) RETURNS text AS '
-DECLARE
-       ret  text;
-BEGIN
-       SELECT AddGeometryColumn('''','''',$1,$2,$3,$4,$5) into ret;
-       RETURN ret;
-END;
-' LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <catalogue>, <schema>, <table>, <column>
------------------------------------------------------------------------
---
--- Removes geometry column reference from geometry_columns table.
--- Drops the column with pgsql >= 73.
--- Make some silly enforcements on it for pgsql < 73
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryColumn(varchar, varchar,varchar,varchar)
-       RETURNS text
-       AS 
-'
-DECLARE
-       catalog_name alias for $1; 
-       schema_name alias for $2;
-       table_name alias for $3;
-       column_name alias for $4;
-       myrec RECORD;
-       okay boolean;
-       real_schema name;
-
-BEGIN
-
-
-#if USE_VERSION >= 73
-       -- Find, check or fix schema_name
-       IF ( schema_name != '''' ) THEN
-               okay = ''f'';
-
-               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
-                       okay := ''t'';
-               END LOOP;
-
-               IF ( okay <> ''t'' ) THEN
-                       RAISE NOTICE ''Invalid schema name - using current_schema()'';
-                       SELECT current_schema() into real_schema;
-               ELSE
-                       real_schema = schema_name;
-               END IF;
-       ELSE
-               SELECT current_schema() into real_schema;
-       END IF;
-#else
-       real_schema = schema_name;
-#endif // USE_VERSION >= 73
-
-       -- Find out if the column is in the geometry_columns table
-       okay = ''f'';
-       FOR myrec IN SELECT * from geometry_columns where f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP
-               okay := ''t'';
-       END LOOP; 
-       IF (okay <> ''t'') THEN 
-               RAISE EXCEPTION ''column not found in geometry_columns table'';
-               RETURN ''f'';
-       END IF;
-
-       -- Remove ref from geometry_columns table
-       EXECUTE ''delete from geometry_columns where f_table_schema = '' ||
-               quote_literal(real_schema) || '' and f_table_name = '' ||
-               quote_literal(table_name)  || '' and f_geometry_column = '' ||
-               quote_literal(column_name);
-       
-#if USE_VERSION < 73
-       -- Remove not-null constraint to table column 
-       EXECUTE ''update pg_attribute set attnotnull = false from pg_class where pg_attribute.attrelid = pg_class.oid and pg_class.relname = '' || quote_literal(table_name) ||'' and pg_attribute.attname = '' || quote_literal(column_name);
-       -- update the given table/column so that it it all NULLS
-       EXECUTE ''update "''||table_name||''" set "''||column_name||''"= NULL'';
-       -- add = NULL constraint to given table/column
-       EXECUTE ''ALTER TABLE "''||table_name||''" ADD CHECK ("''||column_name||''" IS NULL)'';
-#else
-       -- Remove table column
-       EXECUTE ''ALTER TABLE '' || quote_ident(real_schema) || ''.'' ||
-               quote_ident(table_name) || '' DROP COLUMN '' ||
-               quote_ident(column_name);
-#endif 
-
-
-       RETURN real_schema || ''.'' || table_name || ''.'' || column_name ||'' effectively removed.'';
-       
-END;
-'
-LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <schema>, <table>, <column>
------------------------------------------------------------------------
---
--- This is a wrapper to the real DropGeometryColumn, for use
--- when catalogue is undefined
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryColumn(varchar,varchar,varchar)
-       RETURNS text
-       AS 
-'
-DECLARE
-       ret text;
-BEGIN
-       SELECT DropGeometryColumn('''',$1,$2,$3) into ret;
-       RETURN ret;
-END;
-' LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <table>, <column>
------------------------------------------------------------------------
---
--- This is a wrapper to the real DropGeometryColumn, for use
--- when catalogue and schema is undefined. 
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryColumn(varchar,varchar)
-       RETURNS text
-       AS 
-'
-DECLARE
-       ret text;
-BEGIN
-       SELECT DropGeometryColumn('''','''',$1,$2) into ret;
-       RETURN ret;
-END;
-' LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <catalogue>, <schema>, <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryTable(varchar, varchar,varchar)
-       RETURNS text
-       AS 
-'
-DECLARE
-       catalog_name alias for $1; 
-       schema_name alias for $2;
-       table_name alias for $3;
-       real_schema name;
-
-BEGIN
-
-#if USE_VERSION >= 73
-       IF ( schema_name = '''' ) THEN
-               SELECT current_schema() into real_schema;
-       ELSE
-               real_schema = schema_name;
-       END IF;
-#endif // USE_VERSION >= 73
-
-       -- Remove refs from geometry_columns table
-       EXECUTE ''DELETE FROM geometry_columns WHERE '' ||
-#if USE_VERSION >= 73
-               ''f_table_schema = '' || quote_literal(real_schema) ||
-               '' AND '' ||
-#endif
-               '' f_table_name = '' || quote_literal(table_name);
-       
-       -- Remove table 
-       EXECUTE ''DROP TABLE ''
-#if USE_VERSION >= 73
-               || quote_ident(real_schema) || ''.'' ||
-#endif 
-               quote_ident(table_name);
-
-       RETURN
-#if USE_VERSION >= 73
-               real_schema || ''.'' ||
-#endif 
-               table_name ||'' dropped.'';
-       
-END;
-'
-LANGUAGE 'plpgsql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <schema>, <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryTable(varchar,varchar) RETURNS text AS 
-'SELECT DropGeometryTable('''',$1,$2)'
-LANGUAGE 'sql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
--- For PG>=73 use current_schema()
---
------------------------------------------------------------------------
-CREATEFUNCTION DropGeometryTable(varchar) RETURNS text AS 
-'SELECT DropGeometryTable('''','''',$1)'
-LANGUAGE 'sql' WITH (isstrict);
-
------------------------------------------------------------------------
--- UPDATE_GEOMETRY_STATS()
------------------------------------------------------------------------
---
--- Only meaningful for PG<80.
--- Gather statisticts about geometry columns for use
--- with cost estimator.
---
--- It is defined also for PG>=80 for back-compatibility
---
------------------------------------------------------------------------
-#if USE_VERSION >= 80
-CREATEFUNCTION update_geometry_stats() RETURNS text
-AS ' SELECT ''update_geometry_stats() has been obsoleted. Statistics are automatically built running the ANALYZE command''::text' LANGUAGE 'sql';
-#else // USE_VERSION < 80
-CREATEFUNCTION update_geometry_stats()
-RETURNS text
-AS
-'
-DECLARE
-       result text;
-       stated integer;
-       fixres text;
-BEGIN
-
-       SELECT fix_geometry_columns() INTO fixres;
-
-       UPDATE geometry_columns SET
-#if USE_VERSION >= 73
-               stats = (build_histogram2d(create_histogram2d(
-                       find_extent(f_table_schema, f_table_name, f_geometry_column), 40), f_table_schema, f_table_name, f_geometry_column))
-               FROM pg_class c, pg_attribute a, pg_namespace n
-               WHERE n.nspname = f_table_schema::name
-               AND c.relname = f_table_name::name
-               AND c.relnamespace = n.oid
-#else // USE_VERSION < 73 
-               stats = (build_histogram2d(create_histogram2d(
-                       find_extent(f_table_name, f_geometry_column),
-                       40), f_table_name, f_geometry_column))
-               FROM pg_class c, pg_attribute a
-               WHERE c.relname = f_table_name::name
-#endif
-               AND a.attname = f_geometry_column::name
-               AND a.attrelid = c.oid
-               AND geometry_columns.attrelid is not null;
-
-       GET DIAGNOSTICS stated = ROW_COUNT;
-
-       result = fixres || '' stats:'' || stated::text;
-
-       return result;
-END;
-'
-LANGUAGE 'plpgsql' ;
-#endif // USE_VERSION < 80
-
------------------------------------------------------------------------
--- UPDATE_GEOMETRY_STATS( <table>, <column> )
------------------------------------------------------------------------
---
--- Only meaningful for PG<80.
--- Gather statisticts about a geometry column for use
--- with cost estimator.
---
--- It is defined also for PG>=80 for back-compatibility
---
------------------------------------------------------------------------
-#if USE_VERSION >= 80
-CREATEFUNCTION update_geometry_stats(varchar,varchar) RETURNS text
-AS 'SELECT update_geometry_stats();' LANGUAGE 'sql' ;
-#else
-CREATEFUNCTION update_geometry_stats(varchar,varchar) RETURNS text
-AS
-'
-DECLARE
-       tablename aliAS for $1;
-       columnname aliAS for $2;
-       stated integer;
-       result text;
-       fixres text;
-BEGIN
-
-       SELECT fix_geometry_columns() INTO fixres;
-
-       EXECUTE ''UPDATE geometry_columns SET
-#if USE_VERSION >= 73
-                       stats = (build_histogram2d(create_histogram2d(
-                               find_extent(f_table_schema,
-                                       f_table_name,
-                                       f_geometry_column), 40),
-                                       f_table_schema, f_table_name,
-                                       f_geometry_column))
-                       FROM pg_class c, pg_attribute a, pg_namespace n
-                       WHERE n.nspname = f_table_schema::name
-                       AND c.relname = f_table_name::name
-                       AND a.attname = f_geometry_column::name
-                       AND c.relnamespace = n.oid
-                       AND a.attrelid = c.oid
-#else // USE_VERSION < 73 
-                       stats = (build_histogram2d(create_histogram2d(
-                               find_extent(f_table_name, f_geometry_column),
-                               40), f_table_name, f_geometry_column))
-                       FROM pg_class c, pg_attribute a
-                       WHERE c.relname = f_table_name::name
-                       AND a.attname = f_geometry_column::name
-                       AND a.attrelid = c.oid
-#endif
-                       AND f_table_name = '' || quote_literal(tablename) || ''
-                       AND f_geometry_column = '' || quote_literal(columnname)
-                       || '' AND geometry_columns.attrelid is not null'';
-
-       GET DIAGNOSTICS stated = ROW_COUNT;
-
-       result = fixres || '' stats:'' || stated::text;
-
-       return result;
-END;
-'
-LANGUAGE 'plpgsql' ;
-
-#endif  // USE_VERSION < 80
-
------------------------------------------------------------------------
--- CREATE_HISTOGRAM2D( <box>, <size> )
------------------------------------------------------------------------
---
--- Returns a histgram with 0s in all the boxes.
---
------------------------------------------------------------------------
-CREATEFUNCTION create_histogram2d(box3d,int)
-       RETURNS histogram2d
-       AS '@MODULE_FILENAME@','create_histogram2d'
-       LANGUAGE 'C'  with (isstrict);
-
------------------------------------------------------------------------
--- BUILD_HISTOGRAM2D( <histogram2d>, <tablename>, <columnname> )
------------------------------------------------------------------------
-CREATEFUNCTION build_histogram2d (histogram2d,text,text)
-       RETURNS histogram2d
-       AS '@MODULE_FILENAME@','build_histogram2d'
-       LANGUAGE 'C'  with (isstrict);
-
-#if USE_VERSION >= 73
------------------------------------------------------------------------
--- BUILD_HISTOGRAM2D(<histogram2d>,<schema>,<tablename>,<columnname>)
------------------------------------------------------------------------
--- This is a wrapper to the omonimous schema unaware function,
--- thanks to Carl Anderson for the idea.
------------------------------------------------------------------------
-CREATEFUNCTION build_histogram2d (histogram2d,text,text,text)
-RETURNS histogram2d
-AS '
-BEGIN
-       EXECUTE ''SET local search_path = ''||$2||'',public'';
-       RETURN public.build_histogram2d($1,$3,$4);
-END
-' LANGUAGE 'plpgsql'  with (isstrict);
-#endif // USE_VERSION >= 73
-
------------------------------------------------------------------------
--- EXPLODE_HISTOGRAM2D( <histogram2d>, <tablename> )
------------------------------------------------------------------------
-CREATEFUNCTION explode_histogram2d (HISTOGRAM2D,text)
-       RETURNS histogram2d
-       AS '@MODULE_FILENAME@','explode_histogram2d'
-       LANGUAGE 'C'  with (isstrict);
-
------------------------------------------------------------------------
--- ESTIMATE_HISTOGRAM2D( <histogram2d>, <box> )
------------------------------------------------------------------------
-CREATEFUNCTION estimate_histogram2d(HISTOGRAM2D,box)
-       RETURNS float8
-       AS '@MODULE_FILENAME@','estimate_histogram2d'
-       LANGUAGE 'C'  with (isstrict);
-
-
------------------------------------------------------------------------
--- SVG OUTPUT
------------------------------------------------------------------------
-CREATEFUNCTION AsSvg(geometry,int4,int4)
-       RETURNS TEXT
-       AS '@MODULE_FILENAME@','assvg_geometry'
-       LANGUAGE 'C';
-
-CREATEFUNCTION AsSvg(geometry,int4)
-       RETURNS TEXT
-       AS '@MODULE_FILENAME@','assvg_geometry'
-       LANGUAGE 'C';
-
-CREATEFUNCTION AsSvg(geometry)
-       RETURNS TEXT
-       AS '@MODULE_FILENAME@','assvg_geometry'
-       LANGUAGE 'C';
-
-END TRANSACTION;
diff --git a/hwgeom/postgis_algo.c b/hwgeom/postgis_algo.c
deleted file mode 100644 (file)
index f0994bc..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.3  2004/04/27 13:50:59  strk
- * Fixed bug in simplify() that was using the square of the given tolerance.
- *
- * Revision 1.2  2004/01/21 19:04:03  strk
- * Added line_interpolate_point function by jsunday@rochgrp.com
- *
- * Revision 1.1  2003/10/27 10:21:15  strk
- * Initial import.
- *
- **********************************************************************/
-
-#include "postgres.h"
-#include "postgis.h"
-
-
-/***********************************************************************
- * Simple Douglas-Peucker line simplification. 
- * No checks are done to avoid introduction of self-intersections.
- * No topology relations are considered.
- *
- * --strk@keybit.net;
- ***********************************************************************/
-
-#define SAMEPOINT(a,b) ((a)->x==(b)->x&&(a)->y==(b)->y&&(a)->z==(b)->z)
-#define VERBOSE 0
-
-#if VERBOSE > 0
-#undef REPORT_POINTS_REDUCTION
-#undef REPORT_RINGS_REDUCTION
-#define REPORT_RINGS_ADJUSTMENTS
-#endif
-
-#undef CHECK_RING_IS_CLOSE
-
-
-/*
- * Search farthest point from segment p1-p2
- * returns distance in an int pointer
- */
-void DP_findsplit(POINT3D *pts, int npts, int p1, int p2,
-   int *split, double *dist)
-{
-   int k;
-   POINT3D *pa, *pb, *pk;
-   double tmp;
-
-#if VERBOSE > 4
-elog(NOTICE, "DP_findsplit called");
-#endif
-
-   *dist = -1;
-   *split = p1;
-
-   if (p1 + 1 < p2)
-   {
-
-      pa = &(pts[p1]);
-      pb = &(pts[p2]);
-
-#if VERBOSE > 4
-elog(NOTICE, "DP_findsplit: P%d(%f,%f) to P%d(%f,%f)",
-   p1, pa->x, pa->y, p2, pb->x, pb->y);
-#endif
-
-      for (k=p1+1; k<p2; k++)
-      {
-         pk = &(pts[k]);
-
-#if VERBOSE > 4
-elog(NOTICE, "DP_findsplit: P%d(%f,%f)", k, pk->x, pk->y);
-#endif
-
-         /* distance computation */
-         tmp = distance_pt_seg(pk, pa, pb);
-
-         if (tmp > *dist) 
-         {
-            *dist = tmp;       /* record the maximum */
-            *split = k;
-#if VERBOSE > 4
-elog(NOTICE, "DP_findsplit: P%d is farthest (%g)", k, *dist);
-#endif
-         }
-      }
-
-   } /* length---should be redone if can == 0 */
-
-   else
-   {
-#if VERBOSE > 3
-elog(NOTICE, "DP_findsplit: segment too short, no split/no dist");
-#endif
-   }
-
-}
-
-
-void
-DP_simplify(POINT3D *inpts, int inptsn, POINT3D **outpts, int *outptsn, double epsilon)
-{
-   int stack[inptsn];          /* recursion stack */
-   int sp=-1;              /* recursion stack pointer */
-   int p1, split; 
-   double dist;
-   POINT3D *outpoints;
-   int numoutpoints=0;
-
-   p1 = 0;
-   stack[++sp] = inptsn-1;
-
-#if VERBOSE > 4
-   elog(NOTICE, "DP_simplify called");
-#endif
-
-   outpoints = (POINT3D *)palloc( sizeof(POINT3D) * inptsn);
-   memcpy(outpoints, inpts, sizeof(POINT3D));
-   numoutpoints++;
-
-#if VERBOSE > 3
-elog(NOTICE, "DP_simplify: added P0 to simplified point array (size 1)");
-#endif
-
-
-   do
-   {
-
-      DP_findsplit(inpts, inptsn, p1, stack[sp], &split, &dist);
-#if VERBOSE > 3
-      elog(NOTICE, "DP_simplify: farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist);
-#endif
-
-      if (dist > epsilon) {
-         stack[++sp] = split;
-      } else {
-         /*
-         outpoints = repalloc( outpoints, sizeof(POINT3D) * numoutpoints+1 );
-         if ( outpoints == NULL ) elog(NOTICE, "Out of virtual memory");
-         */
-         memcpy(outpoints+numoutpoints, &(inpts[stack[sp]]),
-            sizeof(POINT3D));
-         numoutpoints++;
-#if VERBOSE > 3
-elog(NOTICE, "DP_simplify: added P%d to simplified point array (size: %d)",
-   stack[sp], numoutpoints);
-#endif
-             p1 = stack[sp--];
-      }
-#if VERBOSE > 5
-elog(NOTICE, "stack pointer = %d", sp);
-#endif
-   }
-   while (! (sp<0) );
-
-   /*
-    * If we have reduced the number of points realloc
-    * outpoints array to free up some memory.
-    * Might be turned on and of with a SAVE_MEMORY define ...
-    */
-   if ( numoutpoints < inptsn )
-   {
-      outpoints = (POINT3D *)repalloc(outpoints, sizeof(POINT3D)*numoutpoints);
-      if ( outpoints == NULL ) {
-         elog(ERROR, "Out of virtual memory");
-      }
-   }
-
-   *outpts = outpoints;
-   *outptsn = numoutpoints;
-}
-
-char *
-simplify_line3d(LINE3D *iline, double dist)
-{
-   POINT3D *ipts;
-   POINT3D *opts;
-   int iptsn, optsn, olinesize;
-   LINE3D *oline;
-
-   ipts = iline->points;
-   iptsn = iline->npoints;
-
-   DP_simplify(ipts, iptsn, &opts, &optsn, dist);
-
-   oline = make_line(optsn, opts, &olinesize);
-
-   return (char *)oline;
-}
-
-char *
-simplify_polygon3d(POLYGON3D *ipoly, double dist)
-{
-   POINT3D *ipts;
-   POINT3D *opts;
-   int iptsn, optsn, size;
-   int nrings;
-   int pts_per_ring[ipoly->nrings];
-   POLYGON3D *opoly;
-   int ri;
-   POINT3D *allpts = NULL;
-   int allptsn = 0;
-   int pt_off = 0; /* point offset for each ring */
-
-   nrings = 0;
-
-#ifdef REPORT_RINGS_REDUCTION
-elog(NOTICE, "simplify_polygon3d: simplifying polygon with %d rings",
-   ipoly->nrings);
-#endif
-
-   /* Points start here */
-   ipts = (POINT3D *) ((char *)&(ipoly->npoints[ipoly->nrings] ));
-
-   pt_off=0;
-   for (ri=0; ri<ipoly->nrings; pt_off += ipoly->npoints[ri++])
-   {
-      iptsn = ipoly->npoints[ri];
-
-#ifdef CHECK_RING_IS_CLOSE
-      if ( ! SAMEPOINT(ipts+pt_off, ipts+pt_off+iptsn-1) )
-         elog(NOTICE, "First point != Last point");
-#endif
-
-      DP_simplify(ipts+pt_off, iptsn, &opts, &optsn, dist);
-      if ( optsn < 2 )
-      {
-         /* There as to be an error in DP_simplify */
-         elog(NOTICE, "DP_simplify returned a <2 pts array");
-         pfree(opts);
-         continue;
-      }
-
-#ifdef CHECK_RING_IS_CLOSE
-      if ( ! SAMEPOINT(opts, opts+optsn-1) )
-         elog(NOTICE, "First point != Last point");
-#endif
-
-
-      if ( optsn < 4 )
-      {
-         pfree(opts);
-#ifdef REPORT_RINGS_ADJUSTMENTS
-         elog(NOTICE, "simplify_polygon3d: ring%d skipped ( <4 pts )", ri);
-#endif
-         if ( ri ) continue;
-         else break;
-      }
-
-
-#ifdef REPORT_POINTS_REDUCTION
-elog(NOTICE, "simplify_polygon3d: ring%d simplified from %d to %d points", ri, iptsn, optsn);
-#endif
-
-
-      /*
-       * Add ring to simplified ring array
-       * (TODO: dinamic allocation of pts_per_ring)
-       */
-      pts_per_ring[nrings++] = optsn;
-      if ( ! allptsn ) {
-         allptsn = optsn;
-         allpts = palloc(sizeof(POINT3D)*allptsn);
-         memcpy(allpts, opts, sizeof(POINT3D)*optsn);
-      } else {
-         allptsn += optsn;
-         allpts = repalloc(allpts, sizeof(POINT3D)*allptsn);
-         memcpy(allpts+(allptsn-optsn), opts, sizeof(POINT3D)*optsn);
-      }
-      pfree(opts);
-
-      if ( ! allpts ) {
-         elog(NOTICE, "Error allocating memory for all ring points");
-         return NULL;
-      }
-
-   }
-
-#ifdef REPORT_RINGS_REDUCTION
-elog(NOTICE, "simplify_polygon3d: simplified polygon with %d rings", nrings);
-#endif
-
-   if ( nrings )
-   {
-      opoly = make_polygon(nrings, pts_per_ring, allpts, allptsn, &size);
-      pfree(allpts);
-      return (char *)opoly;
-   }
-   else
-   {
-      return NULL;
-   }
-
-}
-
-char *
-simplify_point3d(POINT3D *ipoint, double dist)
-{
-   return (char *)ipoint;
-}
-
-PG_FUNCTION_INFO_V1(simplify);
-Datum simplify(PG_FUNCTION_ARGS)
-{
-   Datum datum;
-   BOX3D *bbox;
-   GEOMETRY *orig_geom;
-   GEOMETRY *simp_geom = NULL;
-   char *orig_obj;       /* pointer to each object in orig_geom */
-   char *simp_obj;       /* pointer to each simplified object */
-   int simp_obj_size;    /* size of simplified object */
-   int32 *offsets;
-   int i;
-   double dist;
-
-   if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-   datum = PG_GETARG_DATUM(0);
-   orig_geom = (GEOMETRY *)PG_DETOAST_DATUM(datum);
-
-   if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-   dist = PG_GETARG_FLOAT8(1);
-
-   /*
-    * Three or more points on a straight line will still collapse!
-    */
-   // if ( dist == 0 ) PG_RETURN_POINTER(orig_geom);
-
-   offsets = (int32 *) ( ((char *) &(orig_geom->objType[0] )) +
-      sizeof(int32) * orig_geom->nobjs );
-
-
-   /*
-    * Simplify each subobject indipendently.
-    * No topology relations kept.
-    */
-   for(i=0;i<orig_geom->nobjs; i++)
-   {
-      orig_obj = (char *) orig_geom+offsets[i];
-
-      if ( orig_geom->objType[i] == LINETYPE )
-      {
-         simp_obj = simplify_line3d((LINE3D *)orig_obj, dist);
-      }
-      else if ( orig_geom->objType[i] == POLYGONTYPE )
-      {
-         simp_obj = simplify_polygon3d((POLYGON3D *)orig_obj, dist);
-      }
-      else if ( orig_geom->objType[i] == POINTTYPE )
-      {
-         simp_obj = simplify_point3d((POINT3D *)orig_obj, dist);
-      }
-      else
-      {
-         elog(NOTICE, "Unknown geometry type");
-         PG_RETURN_NULL();
-      }
-
-      /* Simplified object degenerated to empty set */
-      if ( ! simp_obj ) continue;
-
-      /* Get size of simplified object */
-      simp_obj_size = size_subobject(simp_obj, orig_geom->objType[i]);
-
-      /* Create one-object geometry (will add objects later) */
-      if ( simp_geom == NULL )
-      {
-         simp_geom = make_oneobj_geometry(
-            simp_obj_size, simp_obj, orig_geom->objType[i],
-            orig_geom->is3d, orig_geom->SRID, orig_geom->scale,
-            orig_geom->offsetX, orig_geom->offsetY);
-      }
-
-      /* Add object to already initialized geometry  */
-      else
-      {
-         simp_geom = add_to_geometry(
-                  simp_geom, simp_obj_size, simp_obj, 
-                  orig_geom->objType[i] );
-      }
-
-      /* Error in simplified geometry construction */
-      if ( ! simp_geom )
-      {
-         elog(ERROR, "geometry construction failed at iteration %d", i);
-         PG_RETURN_NULL();
-      }
-
-   }
-
-   if ( simp_geom == NULL ) PG_RETURN_NULL();
-
-   /* Calculate the bounding box */
-   bbox = bbox_of_geometry(simp_geom);
-   memcpy(&(simp_geom->bvol), bbox, sizeof(BOX3D));
-   pfree(bbox);
-
-
-   simp_geom->type = orig_geom->type;
-   PG_RETURN_POINTER(simp_geom);
-}
-/***********************************************************************
- * --strk@keybit.net;
- ***********************************************************************/
-
-/***********************************************************************
- * Interpolate a point along a line, useful for Geocoding applications
- * SELECT line_interpolate_point( 'LINESTRING( 0 0, 2 2'::geometry, .5 )
- * returns POINT( 1 1 )
- *
- * -- jsunday@rochgrp.com;
- ***********************************************************************/
-PG_FUNCTION_INFO_V1(line_interpolate_point);
-Datum line_interpolate_point(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       double distance = PG_GETARG_FLOAT8(1);
-
-       int32 *offsets1;
-       LINE3D *line;
-       POINT3D point;
-       int nsegs, i;
-       double length, slength, tlength;
-
-       if( distance < 0 || distance > 1 ) {
-               elog(ERROR,"line_interpolate_point: 2nd arg isnt within [0,1]");
-               PG_RETURN_NULL();
-       }
-
-       if( geom->type != LINETYPE ) {
-               elog(ERROR,"line_interpolate_point: 1st arg isnt a line");
-               PG_RETURN_NULL();
-       }
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] )) +
-                       sizeof(int32) * geom->nobjs );
-       line = (LINE3D*) ( (char *)geom + offsets1[0] );
-
-       /* If distance is one of the two extremes, return the point on that
-        * end rather than doing any expensive computations
-        */
-       if( distance == 0.0 ) {
-               PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                       /*(char*)&(line->points[0]), POINTTYPE, */
-                                       (char*)&(line->points[0]), POINTTYPE,
-                                       geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY
-                                       )
-                               );
-       }
-
-       if( distance == 1.0 ) {
-               PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                       (char*)&(line->points[line->npoints-1]), POINTTYPE, 
-                                       geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY
-                                       )
-                               );
-       }
-
-       /* Interpolate a point on the line */
-       nsegs = line->npoints - 1;
-       length = line_length2d( line );
-       tlength = 0;
-       for( i = 0; i < nsegs; i++ ) {
-               POINT3D *p1, *p2;
-               p1 = &(line->points[i]);
-               p2 = &(line->points[i+1]);
-               /* Find the relative length of this segment */
-               slength = distance_pt_pt( p1, p2 )/length;
-               /* If our target distance is before the total length we've seen
-                * so far. create a new point some distance down the current
-                * segment.
-                */
-               if( distance < tlength + slength ) {
-                       double dseg = (distance - tlength) / slength;
-                       point.x = (p1->x) + ((p2->x - p1->x) * dseg);
-                       point.y = (p1->y) + ((p2->y - p1->y) * dseg);
-                       point.z = 0;
-                       PG_RETURN_POINTER(
-                                       make_oneobj_geometry(sizeof(POINT3D),
-                                               (char*)&point, POINTTYPE, 
-                                               geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY
-                                               )
-                                       );
-               }
-               tlength += slength;
-       }
-       /* Return the last point on the line. This shouldn't happen, but
-        * could if there's some floating point rounding errors. */
-       PG_RETURN_POINTER(
-                       make_oneobj_geometry(sizeof(POINT3D),
-                               (char*)&(line->points[line->npoints-1]), POINTTYPE, 
-                               geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY
-                               )
-                       );
-}
-/***********************************************************************
- * --jsunday@rochgrp.com;
- ***********************************************************************/
diff --git a/hwgeom/postgis_chip.c b/hwgeom/postgis_chip.c
deleted file mode 100644 (file)
index 4602edb..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.7  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.6  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-
-#include "fmgr.h"
-
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-
-
-// input is a string with hex chars in it.  Convert to binary and put in the result
-PG_FUNCTION_INFO_V1(CHIP_in);
-Datum CHIP_in(PG_FUNCTION_ARGS)
-{
-       char                    *str = PG_GETARG_CSTRING(0);
-       CHIP                    *result;
-       int                     size;
-       int                     t;
-       int                     input_str_len;
-       int                     datum_size;
-
-//printf("chip_in called\n");
-
-       input_str_len = strlen(str);
-
-       if  ( ( ( (int)(input_str_len/2.0) ) *2.0) != input_str_len)
-       {
-               elog(ERROR,"CHIP_in parser - should be even number of characters!");
-               PG_RETURN_NULL();
-       }
-
-       if (strspn(str,"0123456789ABCDEF") != strlen(str) )
-       {
-               elog(ERROR,"CHIP_in parser - input contains bad characters.  Should only have '0123456789ABCDEF'!");
-               PG_RETURN_NULL();       
-       }
-       size = (input_str_len/2) ;
-       result = (CHIP *) palloc(size);
-       
-       
-       for (t=0;t<size;t++)
-       {
-               ((unsigned char *)result)[t] = parse_hex( &str[t*2]) ;
-       }
-// if endian is wrong, flip it otherwise do nothing
-       result->size = size;
-       if (result->size < sizeof(CHIP) )
-       {
-               elog(ERROR,"CHIP_in parser - bad data (too small to be a CHIP)!");
-               PG_RETURN_NULL();       
-       }
-
-
-       if (result->endian_hint != 1)
-       {
-               //need to do an endian flip
-               flip_endian_int32( (char *)   &result->endian_hint);
-
-               flip_endian_double((char *)  &result->bvol.LLB.x);
-               flip_endian_double((char *)  &result->bvol.LLB.y);
-               flip_endian_double((char *)  &result->bvol.LLB.z);
-
-               flip_endian_double((char *)  &result->bvol.URT.x);
-               flip_endian_double((char *)  &result->bvol.URT.y);
-               flip_endian_double((char *)  &result->bvol.URT.z);
-
-               flip_endian_int32( (char *)  & result->SRID);   
-                       //dont know what to do with future[8] ...
-
-               flip_endian_int32( (char *)  & result->height); 
-               flip_endian_int32( (char *)  & result->width);
-               flip_endian_int32( (char *)  & result->compression);
-               flip_endian_int32( (char *)  & result->factor);
-               flip_endian_int32( (char *)  & result->datatype);
-
-       }
-       if (result->endian_hint != 1 )
-       {
-               elog(ERROR,"CHIP_in parser - bad data (endian flag != 1)!");
-               PG_RETURN_NULL();       
-       }
-       datum_size = 4;
-
-       if ( (result->datatype == 6) || (result->datatype == 7) || (result->datatype == 106) || (result->datatype == 107) )
-       {
-               datum_size = 2;
-       }
-       if ( (result->datatype == 8) || (result->datatype == 108) )
-       {
-               datum_size=1;
-       }
-
-       if (result->compression ==0) //only true for non-compressed data
-       {
-               if (result->size != (sizeof(CHIP) + datum_size * result->width*result->height) )
-               {
-                       elog(ERROR,"CHIP_in parser - bad data (actual size != computed size)!");
-                       PG_RETURN_NULL();
-               }
-       }
-
-       PG_RETURN_POINTER(result);
-}
-
-
-//given a CHIP structure, convert it to Hex and put it in a string
-PG_FUNCTION_INFO_V1(CHIP_out);
-Datum CHIP_out(PG_FUNCTION_ARGS)
-{
-       CHIP                                  *chip = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                                    *result;
-       int                                     size_result;
-       int                                     t;
-
-//printf("chip_out called\n");
-
-       size_result = (chip->size ) *2 +1; //+1 for null char
-       result = palloc (size_result);
-       result[size_result-1] = 0; //null terminate
-
-       for (t=0; t< (chip->size); t++)
-       {
-               deparse_hex( ((unsigned char *) chip)[t], &result[t*2]);                        
-       }
-       PG_RETURN_CSTRING(result);      
-}
-
-
-
-PG_FUNCTION_INFO_V1(CHIP_to_geom);
-Datum CHIP_to_geom(PG_FUNCTION_ARGS)
-{
-       CHIP                                  *chip = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                                *result;
-       
-       POLYGON3D                       *poly;
-       POINT3D                 pts[5]; //5 points around box
-       int                             pts_per_ring[1];
-       int                             poly_size;
-       
-       //use LLB's z value (we're going to set is3d to false)
-
-       set_point( &pts[0], chip->bvol.LLB.x , chip->bvol.LLB.y , chip->bvol.LLB.z );
-       set_point( &pts[1], chip->bvol.URT.x , chip->bvol.LLB.y , chip->bvol.LLB.z );
-       set_point( &pts[2], chip->bvol.URT.x , chip->bvol.URT.y , chip->bvol.LLB.z );
-       set_point( &pts[3], chip->bvol.LLB.x , chip->bvol.URT.y , chip->bvol.LLB.z );
-       set_point( &pts[4], chip->bvol.LLB.x , chip->bvol.LLB.y , chip->bvol.LLB.z );
-       
-       pts_per_ring[0] = 5; //ring has 5 points
-
-               //make a polygon
-       poly = make_polygon(1, pts_per_ring, pts, 5, &poly_size);
-
-       result = make_oneobj_geometry(poly_size, (char *)poly, POLYGONTYPE, FALSE,chip->SRID, 1.0, 0.0, 0.0);
-
-       PG_RETURN_POINTER(result);      
-
-}
-
-PG_FUNCTION_INFO_V1(srid_chip);
-Datum srid_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(c->SRID);
-}
-
-PG_FUNCTION_INFO_V1(factor_chip);
-Datum factor_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_FLOAT4(c->factor);
-}
-
-
-PG_FUNCTION_INFO_V1(datatype_chip);
-Datum datatype_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(c->datatype);
-}
-
-PG_FUNCTION_INFO_V1(compression_chip);
-Datum compression_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(c->compression);
-}
-
-
-PG_FUNCTION_INFO_V1(height_chip);
-Datum height_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(c->height);
-}
-
-PG_FUNCTION_INFO_V1(width_chip);
-Datum width_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP               *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(c->width);
-}
-
-
-
-PG_FUNCTION_INFO_V1(setsrid_chip);
-Datum setsrid_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP    *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32   new_srid = PG_GETARG_INT32(1);
-       CHIP  *result;
-
-       result = (CHIP *) palloc(c->size);
-
-       memcpy(result,c,c->size);
-       result->SRID = new_srid;
-
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(setfactor_chip);
-Datum setfactor_chip(PG_FUNCTION_ARGS)
-{ 
-       CHIP    *c = (CHIP *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       float   factor = PG_GETARG_FLOAT4(1);
-       CHIP  *result;
-
-       result = (CHIP *) palloc(c->size);
-
-       memcpy(result,c,c->size);
-       result->factor = factor;
-
-       PG_RETURN_POINTER(result);
-}
diff --git a/hwgeom/postgis_debug.c b/hwgeom/postgis_debug.c
deleted file mode 100644 (file)
index 2521a10..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.16  2004/08/20 10:23:19  strk
- * removed leak from mem_size()
- *
- * Revision 1.15  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.14  2004/01/13 20:30:19  strk
- * Added useless PG_RETURN_NULL() call to make compiler happy
- *
- * Revision 1.13  2003/11/19 18:01:31  strk
- * CR removed
- *
- * Revision 1.12  2003/09/16 20:27:12  dblasby
- * added ability to delete geometries.
- *
- * Revision 1.11  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.10  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.9  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-
-#include "fmgr.h"
-
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-#include "executor/spi.h"
-#include "commands/trigger.h"
-
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-// #define DEBUG_GIST
-//#define DEBUG_GIST2
-
-
-
-
-
-//find the size of geometry
-PG_FUNCTION_INFO_V1(mem_size);
-Datum mem_size(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32 size = geom->size;
-       PG_FREE_IF_COPY(geom,0);
-       PG_RETURN_INT32(size);
-}
-
-
-
-//get summary info on a GEOMETRY
-PG_FUNCTION_INFO_V1(summary);
-Datum summary(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j,i;
-       POLYGON3D                       *poly;
-       LINE3D                  *line;
-       char                            *result;
-       int                             size;
-       char                            tmp[100];
-       text                            *mytext;
-
-
-       size = 1;
-       result = palloc(1);
-       result[0] = 0; //null terminate it
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       size += 30;
-                       result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a POINT()\n",j);
-                       strcat(result,tmp);
-               }
-
-               if (type1 == LINETYPE)  //line
-               {
-                       line = (LINE3D *) o1;
-
-                       size += 57;
-                       result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a LINESTRING() with %i points\n",j,line->npoints);
-                       strcat(result,tmp);
-               }
-
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-
-                       size += 57*(poly->nrings +1);
-                       result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a POLYGON() with %i rings\n",j,poly->nrings);
-                       strcat(result,tmp);
-                       for (i=0; i<poly->nrings;i++)
-                       {
-                               sprintf(tmp,"     + ring %i has %i points\n",i,poly->npoints[i]);
-                               strcat(result,tmp);
-                       }
-               }
-       }
-
-               // create a text obj to return
-       mytext = (text *) palloc(VARHDRSZ  + strlen(result) );
-       VARATT_SIZEP(mytext) = VARHDRSZ + strlen(result) ;
-       memcpy(VARDATA(mytext) , result, strlen(result) );
-       pfree(result);
-       PG_RETURN_POINTER(mytext);
-}
-
-
-
-
-
-extern Datum lockcheck(PG_FUNCTION_ARGS);
-
-PG_FUNCTION_INFO_V1(lockcheck);
-
-Datum lockcheck (PG_FUNCTION_ARGS)
-{
-       TriggerData *trigdata =      (TriggerData *) fcinfo->context;
-       char            *colname ;
-       int                     id;
-       HeapTuple   rettuple;
-       TupleDesc   tupdesc;
-       int         SPIcode;
-       char            *relname;
-       bool            isnull;
-       char            query[1024];
-       int                     pk_type_oid;
-       char            *pk_id = NULL;
-
-
-       elog(NOTICE,"in lockcheck()");
-
-       /* Make sure trigdata is pointing at what I expect */
-    if (!CALLED_AS_TRIGGER(fcinfo))
-        elog(ERROR, "lockcheck: not fired by trigger manager");
-
-       rettuple = trigdata->tg_newtuple;
-       tupdesc = trigdata->tg_relation->rd_att;
-
-           /* Connect to SPI manager */
-    SPIcode = SPI_connect();
-
-       if (SPIcode  != SPI_OK_CONNECT)
-       {
-               elog(ERROR,"lockcheck: couldnt open a connection to SPI");
-               PG_RETURN_NULL() ;
-       }
-
-       relname = SPI_getrelname(trigdata->tg_relation);
-
-       colname  =       trigdata->tg_trigger->tgargs[0];
-
-
-
-
-       elog(NOTICE,"trigger was executed on the relation: '%s', with attribute named '%s', with locktable named '%s'", relname,colname,"authorization_table");
-
-       //get the value
-
-       pk_type_oid =SPI_gettypeid ( tupdesc  , SPI_fnumber(tupdesc,colname));
-       elog(NOTICE,"primary key type # = %i", pk_type_oid  ) ;
-
-       if (pk_type_oid == 23) //int4
-       {
-               int id = (int) DatumGetInt32( SPI_getbinval(rettuple, tupdesc, SPI_fnumber(tupdesc,colname), &isnull) );
-               if (isnull)
-               {
-                       elog(ERROR,"lockcheck - column (%s) of table (%s) is null!",colname,relname);
-               }
-               pk_id = palloc(100);
-               sprintf(pk_id,"%i",id);
-       }
-       else if (pk_type_oid == 25) // text
-       {
-                Datum id = ( SPI_getbinval(rettuple, tupdesc, SPI_fnumber(tupdesc,colname), &isnull) );
-                if (isnull)
-                {
-                                       elog(ERROR,"lockcheck - column (%s) of table (%s) is null!",colname,relname);
-                }
-                pk_id  = DatumGetCString(DirectFunctionCall1(textout,id));
-
-       }
-       else if (pk_type_oid == 1043) // varchar
-       {
-               Datum id = ( SPI_getbinval(rettuple, tupdesc, SPI_fnumber(tupdesc,colname), &isnull) );
-                if (isnull)
-                {
-                                       elog(ERROR,"lockcheck - column (%s) of table (%s) is null!",colname,relname);
-                }
-                pk_id  = DatumGetCString(DirectFunctionCall1(varcharout,id));
-       }
-       else
-       {
-               elog(ERROR,"id column (%s) of table (%s) has to be either int4, text, or varchar.  Its - %s (oid %i)",colname,relname,SPI_gettype ( tupdesc  , SPI_fnumber(tupdesc,colname) ) ,pk_type_oid );
-       }
-
-
-       id = (int) DatumGetInt32( SPI_getbinval(rettuple, tupdesc, SPI_fnumber(tupdesc,colname), &isnull) );
-
-       sprintf(query,"SELECT authid FROM %s WHERE expires >= now() AND tname = '%s' and  fid = '%s'::text", "authorization_table",relname,pk_id);
-       elog(NOTICE,"about to execute :%s", query);
-
-       SPIcode = SPI_exec(query,0);
-       if (SPIcode !=SPI_OK_SELECT )
-               elog(ERROR,"couldnt execute to test for lock :%s",query);
-
-
-       if (SPI_processed >0)
-       {
-               // there is a lock - check to see if I have rights to it!
-
-               TupleDesc tupdesc = SPI_tuptable->tupdesc;
-               SPITupleTable *tuptable = SPI_tuptable;
-               HeapTuple tuple = tuptable->vals[0];
-               char    *lockcode = SPI_getvalue(tuple, tupdesc, 1);
-
-               elog(NOTICE,"there is a lock on this row!");
-
-               // check to see if temp_lock_have_table table exists (it might not exist if they own no locks
-               sprintf(query,"SELECT * FROM pg_class WHERE relname = 'temp_lock_have_table'");
-               SPIcode = SPI_exec(query,0);
-               if (SPIcode !=SPI_OK_SELECT )
-                       elog(ERROR,"couldnt execute to test for lockkey temp table :%s",query);
-               if (SPI_processed ==0)
-               {
-                       elog(NOTICE,"I do not own any locks (no lock table) - I cannot modify the row");
-                       //PG_RETURN_NULL();
-                       SPI_finish();
-                       //return NULL;
-                       elog(ERROR,"attemted to modify a locked row that I do not have authorization for!");
-               }
-
-
-               sprintf(query,"SELECT * FROM temp_lock_have_table  WHERE xideq(transid , getTransactionID() ) AND lockcode ='%s'",lockcode);
-               elog(NOTICE,"about to execute :%s", query);
-
-               SPIcode = SPI_exec(query,0);
-               if (SPIcode !=SPI_OK_SELECT )
-                       elog(ERROR,"couldnt execute to test for lock aquire:%s",query);
-
-               if (SPI_processed >0)
-               {
-                       elog(NOTICE,"I own the lock - I can modify the row");
-                       SPI_finish();
-                       return PointerGetDatum(rettuple);
-               }
-
-               elog(NOTICE,"I do not own the lock - I cannot modify the row");
-               //PG_RETURN_NULL();
-               SPI_finish();
-               //return NULL;
-               elog(ERROR,"attemted to modify a locked row that I do not have authorization for!");
-               PG_RETURN_NULL();
-       }
-       else
-       {
-               elog(NOTICE,"there is NOT a lock on this row!");
-               SPI_finish();
-               return PointerGetDatum(rettuple);
-       }
-
-}
-
-
-extern Datum getTransactionID(PG_FUNCTION_ARGS);
-
-PG_FUNCTION_INFO_V1(getTransactionID);
-
-Datum getTransactionID(PG_FUNCTION_ARGS)
-{
-    TransactionId xid = GetCurrentTransactionId();
-    PG_RETURN_DATUM( TransactionIdGetDatum(xid) );
-}
-
-
diff --git a/hwgeom/postgis_estimate.c b/hwgeom/postgis_estimate.c
deleted file mode 100644 (file)
index 995067c..0000000
+++ /dev/null
@@ -1,1950 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.31  2004/08/19 06:15:58  strk
- * USE_VERSION gets 80 where it got 75
- *
- * Revision 1.30  2004/08/16 11:03:25  mcayland
- * Added DLLIMPORT reference to "default_statistics_target" if we are compiling under Win32. This should make it unnecessary to apply Romi's patch to the PostgreSQL source tree when compiling PostgreSQL ready for PostGIS.
- *
- * Revision 1.29  2004/06/22 16:52:17  strk
- * Standard deviation factor used in histogram extent computation made
- * a compile-time define.
- *
- * Revision 1.28  2004/06/14 07:48:10  strk
- * Histogram extent redefinition after hard deviant removal fixed to be
- * "at most" the standard deviation based computed.
- *
- * Revision 1.27  2004/06/11 11:38:57  strk
- * Infinite geometries handling.
- * Histogram extent re-computation after 'hard deviant' features removal.
- *
- * Revision 1.26  2004/06/10 18:54:12  strk
- * histogram grid size refined to use near-square cells.
- *
- * Revision 1.25  2004/06/10 15:44:43  strk
- * Added standard deviation based histogram extent refinement
- *
- * Revision 1.24  2004/06/10 13:42:17  strk
- * Separated the estimator code in an estimate_selectivity() function.
- * Handled complete contaiment and complete miss of histogram by searc box.
- *
- * Revision 1.23  2004/06/09 09:35:49  strk
- * Removed partial pgsql List API copy
- *
- * Revision 1.22  2004/06/08 17:49:14  strk
- * Fixed to build cleanly agains pg75
- *
- * Revision 1.21  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.20  2004/03/15 17:07:05  strk
- * Added calls to vacuum_delay_point() to give backend a chance of
- * interrupting geometry stats computation.
- * Set default DEBUG_GEOMETRY_STATS to 0.
- *
- * Revision 1.19  2004/03/09 00:21:02  strk
- * Removed useless code blocks in histogram builder
- *
- * Revision 1.18  2004/03/09 00:09:56  strk
- * estimator applies a gain of AOI/cell_area on each cell it intersects (reverted to previous behaviour)
- *
- * Revision 1.17  2004/03/04 13:50:45  strk
- * postgis_gist_sel(): added warnings if search_box goes outside of histogram grid
- *
- * Revision 1.16  2004/03/04 09:44:57  strk
- * The selectivity estimator does add the full value of each cell it overlaps,
- * regardless of the actual overlapping area. Final gain is not applied
- * (formerly 1 / minimun between average feature cells occupation and
- *  search_box cells occupation)
- *
- * Revision 1.15  2004/03/03 21:59:48  strk
- * added check to keep selectivity value in the range of validity (suggested by m.cave)
- *
- * Revision 1.14  2004/03/01 16:02:41  strk
- * histogram's boxesPerSide computed as a function of the column's statistic target
- *
- * Revision 1.13  2004/02/29 21:53:42  strk
- * bug fix in postgis_gist_sel (for PG75): SysCache is not released if not acquired
- *
- * Revision 1.12  2004/02/26 16:42:59  strk
- * Fixed bugs reported by Mark Cave-Ayland <m.cave-ayland@webbased.co.uk>.
- * Re-introduced previously removed estimate value incrementation by
- * the fractional part of each of the cells' value computed as the fraction
- * of overlapping area.
- *
- * Revision 1.11  2004/02/25 12:00:32  strk
- * Added handling for point features in histogram creation (add 1 instead of AOI/cell_area when AOI is 0).
- * Fixed a wrong cast of BOX3D to BOX (called the convertion func).
- * Added some comments and an implementation on how to change evaluation
- * based on the average feature and search box cells occupation.
- *
- * Revision 1.10  2004/02/25 00:46:26  strk
- * initial version of && selectivity estimation for PG75
- *
- * Revision 1.9  2004/02/23 21:59:16  strk
- * geometry analyzer builds the histogram
- *
- * Revision 1.8  2004/02/23 12:18:55  strk
- * added skeleton functions for pg75 stats integration
- *
- * Revision 1.7  2003/11/11 10:14:57  strk
- * Added support for PG74
- *
- * Revision 1.6  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.5  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
- // If you're modifiying this file you should read the postgis mail list as it has
- // detailed descriptions of whats happening here and why.
-
-#include "postgres.h"
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-//--------------------------------------------------------------------------
-
-#include "access/heapam.h"
-#include "catalog/catname.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_statistic.h"
-#include "catalog/pg_type.h"
-#include "mb/pg_wchar.h"
-#include "nodes/makefuncs.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/plancat.h"
-#include "optimizer/prep.h"
-#include "parser/parse_func.h"
-#include "parser/parse_oper.h"
-#include "parser/parsetree.h"
-#include "utils/builtins.h"
-#include "utils/date.h"
-#include "utils/int8.h"
-#include "utils/lsyscache.h"
-#include "utils/selfuncs.h"
-#include "utils/syscache.h"
-
-
-
-#include "executor/spi.h"
-
-#if USE_VERSION >= 80
-
-#include "commands/vacuum.h"
-
-/*
- *     Assign a number to the postgis statistics kind
- *
- *     tgl suggested:
- *
- *     1-100:  reserved for assignment by the core Postgres project
- *     100-199: reserved for assignment by PostGIS
- *     200-9999: reserved for other globally-known stats kinds
- *     10000-32767: reserved for private site-local use
- *
- */
-#define STATISTIC_KIND_GEOMETRY 100
-
-#define DEBUG_GEOMETRY_STATS 1
-
-/*
- * Define this if you want to use standard deviation based
- * histogram extent computation. If you do, you can also 
- * tweak the deviation factor used in computation with
- * SDFACTOR.
- */
-#define USE_STANDARD_DEVIATION 1
-#define SDFACTOR 2
-
-/*
- * Default geometry selectivity factor
- */
-#define DEFAULT_GEOMETRY_SEL 0.000005 
-
-typedef struct GEOM_STATS_T
-{
-       // cols * rows = total boxes in grid
-       float4 cols;
-       float4 rows;
-       
-       // average bounding box area of not-null features 
-       float4 avgFeatureArea;
-
-       // average number of histogram cells
-       // covered by the sample not-null features
-       float4 avgFeatureCells;
-
-       // BOX of area
-       float4 xmin,ymin, xmax, ymax;
-       // variable length # of floats for histogram
-       float4 value[1];
-} GEOM_STATS;
-
-#endif
-
-
-// For Win32 we must declare default_statistics_target as DLLIMPORT *after*
-// including all the relevant header files otherwise we get a link error.
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-extern DLLIMPORT int default_statistics_target;
-#endif
-
-
-//estimate_histogram2d(histogram2d, box)
-// returns a % estimate of the # of features that will be returned by that box query
-//
-//For each grid cell that intersects the query box
-//       Calculate area of intersection (AOI)
-//    IF AOI < avgFeatureArea THEN set AOI = avgFeatureArea
-//    SUM AOI/area-of-cell*value-of-cell
-//
-// change : instead of avgFeatureArea, use avgFeatureArea or 10% of a grid cell (whichever is smaller)
-
-PG_FUNCTION_INFO_V1(estimate_histogram2d);
-Datum estimate_histogram2d(PG_FUNCTION_ARGS)
-{
-       HISTOGRAM2D   *histo = (HISTOGRAM2D *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       BOX                       *box = (BOX *) PG_GETARG_POINTER(1);
-       double box_area;
-       int                     x_idx_min, x_idx_max, y_idx_min, y_idx_max;
-       double intersect_x, intersect_y, AOI;
-       int x,y;
-       double xmin,ymin,xmax,ymax;
-       int32 result_sum;
-       double cell_area;
-       int total,t;
-       double  avg_feature_size;
-
-
-
-       result_sum = 0;
-    xmin = histo->xmin;
-    ymin = histo->ymin;
-    xmax = histo->xmax;
-    ymax = histo->ymax;
-
-                       cell_area = ( (xmax-xmin)*(ymax-ymin)/(histo->boxesPerSide*histo->boxesPerSide) );
-
-                       avg_feature_size = histo->avgFeatureArea;
-                       if ( avg_feature_size > cell_area*0.1)
-                       {
-                               avg_feature_size = cell_area*0.1;
-                       }
-
-
-//elog(NOTICE,"start estimate_histogram2d: ");
-//elog(NOTICE,"box is : (%.15g,%.15g to %.15g,%.15g)",box->low.x,box->low.y, box->high.x, box->high.y);
-
-                                       box_area = (box->high.x-box->low.x)*(box->high.y-box->low.y);
-
-                                       if (box_area<0)
-                                           box_area =0;  // for precision!
-
-                                       //check to see which boxes this intersects
-                                       x_idx_min = (box->low.x-xmin)/(xmax-xmin)*histo->boxesPerSide;
-                                       if (x_idx_min <0)
-                                               x_idx_min = 0;
-                                       if (x_idx_min >= histo->boxesPerSide)
-                                               x_idx_min = histo->boxesPerSide-1;
-                                       y_idx_min = (box->low.y-ymin)/(ymax-ymin)*histo->boxesPerSide;
-                                       if (y_idx_min <0)
-                                               y_idx_min = 0;
-                                       if (y_idx_min >= histo->boxesPerSide)
-                                               y_idx_min = histo->boxesPerSide-1;
-
-                                       x_idx_max = (box->high.x-xmin)/(xmax-xmin)*histo->boxesPerSide;
-                                       if (x_idx_max <0)
-                                               x_idx_max = 0;
-                                       if (x_idx_max >= histo->boxesPerSide)
-                                               x_idx_max = histo->boxesPerSide-1;
-                                       y_idx_max = (box->high.y-ymin)/(ymax-ymin)*histo->boxesPerSide ;
-                                       if (y_idx_max <0)
-                                               y_idx_max = 0;
-                                       if (y_idx_max >= histo->boxesPerSide)
-                                               y_idx_max = histo->boxesPerSide-1;
-
-                                       //the {x,y}_idx_{min,max} define the grid squares that the box intersects
-
-
-//elog(NOTICE,"        search is in x: %i to %i   y: %i to %i",x_idx_min, x_idx_max, y_idx_min,y_idx_max);
-                                       for (y= y_idx_min; y<=y_idx_max;y++)
-                                       {
-                                               for (x=x_idx_min;x<= x_idx_max;x++)
-                                               {
-                                                               intersect_x = min(box->high.x, xmin+ (x+1) * (xmax-xmin)/histo->boxesPerSide ) -
-                                                                                       max(box->low.x, xmin+ x*(xmax-xmin)/histo->boxesPerSide ) ;
-                                                               intersect_y = min(box->high.y, ymin+ (y+1) * (ymax-ymin)/histo->boxesPerSide ) -
-                                                                                       max(box->low.y, ymin+ y*(ymax-ymin)/histo->boxesPerSide ) ;
-
-                                                                       // for a point, intersect_x=0, intersect_y=0, box_area =0
-//elog(NOTICE,"x=%i,y=%i, intersect_x= %.15g, intersect_y = %.15g",x,y,intersect_x,intersect_y);
-                                                               if ( (intersect_x>=0) && (intersect_y>=0) )
-                                                               {
-                                                                       AOI = intersect_x*intersect_y;
-                                                                       if (AOI< avg_feature_size)
-                                                                                       AOI = avg_feature_size;
-                                                                       result_sum += AOI/cell_area* histo->value[x+y*histo->boxesPerSide];
-                                                               }
-                                               }
-                                       }
-                       total = 0;
-                       for(t=0;t<histo->boxesPerSide*histo->boxesPerSide;t++)
-                       {
-                               total+=histo->value[t];
-                       }
-
-                       if ( (histo->avgFeatureArea <=0) && (box_area <=0) )
-                               PG_RETURN_FLOAT8(1.0/((double)(total)));
-                       else
-                               PG_RETURN_FLOAT8(result_sum/((double)total));
-
-}
-
-//explode_histogram2d(histogram2d, tablename::text)
-// executes CREATE TABLE tablename (the_geom geometry, id int, hits int, percent float)
-// then populates it
-//  DOES NOT UPDATE GEOMETRY_COLUMNS
-PG_FUNCTION_INFO_V1(explode_histogram2d);
-Datum explode_histogram2d(PG_FUNCTION_ARGS)
-{
-       HISTOGRAM2D   *histo = (HISTOGRAM2D *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char    *tablename;
-       char    sql[1000];
-       char    geom[1000];
-       int t;
-    int total;
-       double cellx,celly;
-       int x,y;
-       int SPIcode;
-
-
-       cellx = (histo->xmax-histo->xmin)/histo->boxesPerSide;
-       celly = (histo->ymax-histo->ymin)/histo->boxesPerSide;
-
-       tablename  = DatumGetCString(DirectFunctionCall1(textout,
-                       PointerGetDatum(PG_GETARG_DATUM(1))));
-
-       total = 0;
-       for(t=0;t<histo->boxesPerSide*histo->boxesPerSide;t++)
-       {
-               total+=histo->value[t];
-       }
-       if (total==0)
-               total=1;
-
-               SPIcode = SPI_connect();
-               if (SPIcode  != SPI_OK_CONNECT)
-               {
-                       elog(ERROR,"build_histogram2d: couldnt open a connection to SPI");
-                       PG_RETURN_NULL() ;
-
-               }
-
-               sprintf(sql,"CREATE TABLE %s (the_geom geometry, id int, hits int, percent float)",tablename);
-
-               SPIcode = SPI_exec(sql, 2147483640 ); // max signed int32
-
-                       if (SPIcode  != SPI_OK_UTILITY )
-                       {
-                                       elog(ERROR,"explode_histogram2d: couldnt create table");
-                                       PG_RETURN_NULL() ;
-                       }
-                       t=0;
-                       for(y=0;y<histo->boxesPerSide;y++)
-                       {
-                                       for(x=0;x<histo->boxesPerSide;x++)
-                                       {
-
-                                               sprintf(geom,"POLYGON((%.15g %.15g, %.15g %.15g, %.15g %.15g, %.15g %.15g, %.15g %.15g ))",
-                                                       histo->xmin + x*cellx,     histo->ymin+y*celly,
-                                                       histo->xmin + (x)*cellx,   histo->ymin+ (y+1)*celly,
-                                                       histo->xmin + (x+1)*cellx, histo->ymin+ (y+1)*celly,
-                                                       histo->xmin + (x+1)*cellx, histo->ymin+y*celly,
-                                                       histo->xmin + x*cellx,     histo->ymin+y*celly
-                                                       );
-                                               sprintf(sql,"INSERT INTO %s VALUES('%s'::geometry,%i,%i,%.15g)",tablename,geom,t,histo->value[t],histo->value[t]/((double)total)*100.0);
-//elog(NOTICE,"SQL:%s",sql);
-                                               t++;
-                                               SPIcode = SPI_exec(sql, 2147483640 ); // max signed int32
-                                               if (SPIcode  != SPI_OK_INSERT )
-                                               {
-                                                               elog(ERROR,"explode_histogram2d: couldnt insert into");
-                                                               PG_RETURN_NULL() ;
-                                               }
-                                       }
-                       }
-
-           SPIcode =SPI_finish();
-           if (SPIcode  != SPI_OK_FINISH )
-               {
-                                       elog(ERROR,"build_histogram2d: couldnt disconnect from SPI");
-                                       PG_RETURN_NULL() ;
-               }
-
-       PG_RETURN_POINTER(histo) ;
-}
-
-
-//build_histogram2d (HISTOGRAM2D, tablename, columnname)
-// executes the SPI 'SELECT box3d(columnname) FROM tablename'
-// and sticks all the results in the histogram
-PG_FUNCTION_INFO_V1(build_histogram2d);
-Datum build_histogram2d(PG_FUNCTION_ARGS)
-{
-       HISTOGRAM2D   *histo = (HISTOGRAM2D *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       char    *tablename, *columnname;
-       HISTOGRAM2D   *result;
-       int SPIcode;
-       char    sql[1000];
-       SPITupleTable *tuptable;
-       TupleDesc tupdesc ;
-       int ntuples,t;
-       Datum   datum;
-       bool    isnull;
-       HeapTuple tuple ;
-       BOX     *box;
-    double box_area, area_intersect, cell_area;
-    int x_idx_min, x_idx_max;
-    int y_idx_min, y_idx_max;
-    double xmin,ymin, xmax,ymax;
-    double intersect_x, intersect_y;
-    int x,y;
-    int total;
-    double sum_area;
-    int    sum_area_numb;
-
-       double sum_area_new      = 0;
-    int    sum_area_numb_new =0;
-       int bump=0;
-
-       int tuplimit = 500000;  // No. of tuples returned on each cursor fetch
-       bool moredata;
-       void *SPIplan;
-       void *SPIportal;
-
-
-    xmin = histo->xmin;
-    ymin = histo->ymin;
-    xmax = histo->xmax;
-    ymax = histo->ymax;
-
-
-       result = (HISTOGRAM2D *) malloc(histo->size);
-       memcpy(result,histo,histo->size);
-
-
-               total = 0;
-               for(t=0;t<histo->boxesPerSide*histo->boxesPerSide;t++)
-               {
-                       total+=histo->value[t];
-               }
-
-
-
-               sum_area = histo->avgFeatureArea * total;
-               sum_area_numb = total;
-
-
-
-           tablename  = DatumGetCString(DirectFunctionCall1(textout,
-                                                       PointerGetDatum(PG_GETARG_DATUM(1))));
-
-               columnname = DatumGetCString(DirectFunctionCall1(textout,
-                                                       PointerGetDatum(PG_GETARG_DATUM(2))));
-
-       //elog(NOTICE,"Start build_histogram2d with %i items already existing", sum_area_numb);
-       //elog(NOTICE,"table=\"%s\", column = \"%s\"", tablename, columnname);
-
-
-               SPIcode = SPI_connect();
-
-               if (SPIcode  != SPI_OK_CONNECT)
-               {
-                       elog(ERROR,"build_histogram2d: couldnt open a connection to SPI");
-                       PG_RETURN_NULL() ;
-
-               }
-
-
-                       sprintf(sql,"SELECT box(\"%s\") FROM \"%s\"",columnname,tablename);
-                       //elog(NOTICE,"executing %s",sql);
-
-                       SPIplan = SPI_prepare(sql, 0, NULL);
-                       if (SPIplan  == NULL)
-                       {
-                                       elog(ERROR,"build_histogram2d: couldnt create query plan via SPI");
-                                       PG_RETURN_NULL() ;
-                       }
-
-                       SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL);
-                       if (SPIportal == NULL)
-                       {
-                                       elog(ERROR,"build_histogram2d: couldn't create cursor via SPI");
-                                       PG_RETURN_NULL() ;
-                       }
-
-                       
-                       moredata = TRUE;
-                       while (moredata==TRUE) {
-
-                               //elog(NOTICE,"about to fetch...");
-                               SPI_cursor_fetch(SPIportal, TRUE, tuplimit);
-
-                               ntuples = SPI_processed;
-                               //elog(NOTICE,"processing %d records", ntuples);
-
-                               if (ntuples > 0) {
-
-                                       tuptable = SPI_tuptable;
-                                       tupdesc = SPI_tuptable->tupdesc;
-
-                                       cell_area = ( (xmax-xmin)*(ymax-ymin)/(histo->boxesPerSide*histo->boxesPerSide) );
-
-                                       for (t=0;t<ntuples;t++)
-                                       {
-                                               tuple = tuptable->vals[t];
-                                               datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
-                                               if (!(isnull))
-                                               {
-                                                       box = (BOX *)DatumGetPointer(datum);
-                                                       box_area = (box->high.x-box->low.x)*(box->high.y-box->low.y);
-
-                                                       sum_area_new += box_area;
-                                                       sum_area_numb_new ++;
-
-                                                       if (box_area > cell_area )
-                                                               box_area = cell_area;
-                                                       if (box_area<0)
-                                                               box_area =0;  // for precision!
-
-                                                       //check to see which boxes this intersects
-                                                       x_idx_min = (box->low.x-xmin)/(xmax-xmin)*histo->boxesPerSide;
-                                                       if (x_idx_min <0)
-                                                               x_idx_min = 0;
-                                                       if (x_idx_min >= histo->boxesPerSide)
-                                                               x_idx_min = histo->boxesPerSide-1;
-                                                       y_idx_min = (box->low.y-ymin)/(ymax-ymin)*histo->boxesPerSide;
-                                                       if (y_idx_min <0)
-                                                               y_idx_min = 0;
-                                                       if (y_idx_min >= histo->boxesPerSide)
-                                                               y_idx_min = histo->boxesPerSide-1;
-
-                                                       x_idx_max = (box->high.x-xmin)/(xmax-xmin)*histo->boxesPerSide;
-                                                       if (x_idx_max <0)
-                                                               x_idx_max = 0;
-                                                       if (x_idx_max >= histo->boxesPerSide)
-                                                               x_idx_max = histo->boxesPerSide-1;
-                                                       y_idx_max = (box->high.y-ymin)/(ymax-ymin)*histo->boxesPerSide ;
-                                                       if (y_idx_max <0)
-                                                               y_idx_max = 0;
-                                                       if (y_idx_max >= histo->boxesPerSide)
-                                                               y_idx_max = histo->boxesPerSide-1;
-
-                                                       //the {x,y}_idx_{min,max} define the grid squares that the box intersects
-                                                       // if the area of the intersect between the box and the grid square > 5% of
-
-                       //elog(NOTICE,"box is : (%.15g,%.15g to %.15g,%.15g)",box->low.x,box->low.y, box->high.x, box->high.y);
-               //elog(NOTICE,"        search is in x: %i to %i   y: %i to %i",x_idx_min, x_idx_max, y_idx_min,y_idx_max);
-                                                       for (y= y_idx_min; y<=y_idx_max;y++)
-                                                       {
-                                                               for (x=x_idx_min;x<= x_idx_max;x++)
-                                                               {
-                                                                               intersect_x = min(box->high.x, xmin+ (x+1) * (xmax-xmin)/histo->boxesPerSide ) -
-                                                                                                       max(box->low.x, xmin+ x*(xmax-xmin)/histo->boxesPerSide ) ;
-                                                                               intersect_y = min(box->high.y, ymin+ (y+1) * (ymax-ymin)/histo->boxesPerSide ) -
-                                                                                                       max(box->low.y, ymin+ y*(ymax-ymin)/histo->boxesPerSide ) ;
-
-                                                                                       // for a point, intersect_x=0, intersect_y=0, box_area =0
-               //elog(NOTICE,"x=%i,y=%i, intersect_x= %.15g, intersect_y = %.15g",x,y,intersect_x,intersect_y);
-                                                                               if ( (intersect_x>=0) && (intersect_y>=0) )
-                                                                               {
-                                                                                       area_intersect = intersect_x*intersect_y;
-                                                                                       if (area_intersect >= box_area*0.05)
-                                                                                       {
-               //elog(NOTICE,"bump");
-                                                                                               bump++;
-                                                                                               result->value[x+y*histo->boxesPerSide]++;
-                                                                                       }
-                                                                               }
-                                                               }
-                                                       } // End of y
-
-                                               } // End isnull
-
-                                       } // End of for loop
-
-                                       // Free all the results after each fetch, otherwise all tuples stay
-                                       // in memory until the end of the table...
-                                       SPI_freetuptable(tuptable);
-
-                               } else {
-                                               moredata = FALSE;
-                               } // End of if ntuples > 0
-
-                       } // End of while loop
-
-
-               // Close the cursor
-               SPI_cursor_close(SPIportal);
-
-           SPIcode =SPI_finish();
-           if (SPIcode  != SPI_OK_FINISH )
-               {
-                                       elog(ERROR,"build_histogram2d: couldnt disconnect from SPI");
-                                       PG_RETURN_NULL() ;
-               }
-
-               //elog(NOTICE,"finishing up build_histogram2d ");
-
-       //pfree(tablename);
-       //pfree(columnname);
-
-       total = 0;
-       for(t=0;t<histo->boxesPerSide*histo->boxesPerSide;t++)
-       {
-               total+=result->value[t];
-       }
-       //elog(NOTICE ,"histogram finishes with %i items in it - acutally added %i rows and %i bumps\n",total,sum_area_numb_new,bump);
-       //elog(NOTICE,"done build_histogram2d ");
-
-
-       //re-calculate statistics on avg bbox size
-       if (sum_area_numb_new >0)
-               result->avgFeatureArea = (sum_area_new+sum_area)/((double)(sum_area_numb_new+sum_area_numb));
-
-       PG_RETURN_POINTER(result) ;
-}
-
-
-
-
-
-#if USE_VERSION < 80
-/*
- * get_restriction_var
- *             Examine the args of a restriction clause to see if it's of the
- *             form (var op something) or (something op var).  If so, extract
- *             and return the var and the other argument.
- *
- * Inputs:
- *     args: clause argument list
- *     varRelid: see specs for restriction selectivity functions
- *
- * Outputs: (these are set only if TRUE is returned)
- *     *var: gets Var node
- *     *other: gets other clause argument
- *     *varonleft: set TRUE if var is on the left, FALSE if on the right
- *
- * Returns TRUE if a Var is identified, otherwise FALSE.
- */
-static bool
-get_restriction_var(List *args,
-                                       int varRelid,
-                                       Var **var,
-                                       Node **other,
-                                       bool *varonleft)
-{
-       Node       *left,
-                          *right;
-
-       if (length(args) != 2)
-               return false;
-
-       left = (Node *) lfirst(args);
-       right = (Node *) lsecond(args);
-
-       /* Ignore any binary-compatible relabeling */
-
-       if (IsA(left, RelabelType))
-               left = (Node *)((RelabelType *) left)->arg;
-       if (IsA(right, RelabelType))
-               right = (Node *)((RelabelType *) right)->arg;
-
-       /* Look for the var */
-
-       if (IsA(left, Var) &&
-               (varRelid == 0 || varRelid == ((Var *) left)->varno))
-       {
-               *var = (Var *) left;
-               *other = right;
-               *varonleft = true;
-       }
-       else if (IsA(right, Var) &&
-                        (varRelid == 0 || varRelid == ((Var *) right)->varno))
-       {
-               *var = (Var *) right;
-               *other = left;
-               *varonleft = false;
-       }
-       else
-       {
-               /* Duh, it's too complicated for me... */
-               return false;
-       }
-
-       return true;
-}
-
-//restriction in the GiST && operator
-PG_FUNCTION_INFO_V1(postgis_gist_sel);
-Datum postgis_gist_sel(PG_FUNCTION_ARGS)
-{
-               Query      *root = (Query *) PG_GETARG_POINTER(0);
-       //      Oid                     operator = PG_GETARG_OID(1);
-               List       *args = (List *) PG_GETARG_POINTER(2);
-               int                     varRelid = PG_GETARG_INT32(3);
-               GEOMETRY        *in;
-               BOX                     *search_box;
-               char            sql[1000];
-
-               SPITupleTable *tuptable;
-               TupleDesc tupdesc ;
-               HeapTuple tuple ;
-
-               Datum datum;
-               bool isnull;
-
-
-               Var     *var;
-               Node    *other;
-               bool varonleft;
-               Oid relid;
-               int SPIcode;
-
-               double myest;
-
-#ifndef USE_STATS
-       PG_RETURN_FLOAT8(0.000005);
-#endif
-
-                 //PG_RETURN_FLOAT8(0.000005);
-
-               //elog(NOTICE,"postgis_gist_sel was called");
-
-               if (!get_restriction_var(args, varRelid,
-                                                        &var, &other, &varonleft))
-               {
-                       //elog(NOTICE,"get_restriction_var FAILED -returning early");
-                       PG_RETURN_FLOAT8(0.000005);
-               }
-
-               relid = getrelid(var->varno, root->rtable);
-               if (relid == InvalidOid)
-               {
-                       //elog(NOTICE,"getrelid FAILED (invalid oid) -returning early");
-                       PG_RETURN_FLOAT8(0.000005);
-               }
-
-               //elog(NOTICE,"operator's oid = %i (this should be GEOMETRY && GEOMETRY)",operator);
-               //elog(NOTICE,"relations' oid = %i (this should be the relation that the && is working on) ",relid);
-               //elog(NOTICE,"varatt oid = %i (basically relations column #) ",var->varattno);
-
-
-               if (IsA(other, Const) &&((Const *) other)->constisnull)
-               {
-                       //elog(NOTICE,"other operand of && is NULL - returning early");
-                       PG_RETURN_FLOAT8(0.000005);
-               }
-
-               if (IsA(other, Const))
-               {
-                       //elog(NOTICE,"The other side of the && is a constant with type (oid) = %i and length %i.  This should be GEOMETRY with length -1 (variable length)",((Const*)other)->consttype,((Const*)other)->constlen);
-
-               }
-               else
-               {
-                       //elog(NOTICE,"the other side of && isnt a constant - returning early");
-                       PG_RETURN_FLOAT8(0.000005);
-               }
-
-               //get the BOX thats being searched in
-               in = (GEOMETRY*)PG_DETOAST_DATUM( ((Const*)other)->constvalue );
-               search_box = convert_box3d_to_box(&in->bvol);
-
-               //elog(NOTICE,"requested search box is : (%.15g %.15g, %.15g %.15g)",search_box->low.x,search_box->low.y,search_box->high.x,search_box->high.y);
-
-
-                       SPIcode = SPI_connect();
-                       if (SPIcode  != SPI_OK_CONNECT)
-                       {
-                               elog(NOTICE,"postgis_gist_sel: couldnt open a connection to SPI:%i",SPIcode);
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-
-                       sprintf(sql,"SELECT stats FROM GEOMETRY_COLUMNS WHERE attrelid=%u AND varattnum=%i",relid,var->varattno);
-                       //elog(NOTICE,"sql:%s",sql);
-                       SPIcode = SPI_exec(sql, 1 );
-                       if (SPIcode  != SPI_OK_SELECT )
-                       {
-                               SPI_finish();
-                               elog(NOTICE,"postgis_gist_sel: couldnt execute sql via SPI");
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-
-                       if (SPI_processed !=1)
-                       {
-                               SPI_finish();
-                               //elog(NOTICE,"postgis_gist_sel: geometry_columns didnt return a unique value");
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-
-                       tuptable = SPI_tuptable;
-                       tupdesc = SPI_tuptable->tupdesc;
-                       tuple = tuptable->vals[0];
-                       datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
-                       if (isnull)
-                       {
-                               SPI_finish();
-                               //elog(NOTICE,"postgis_gist_sel: geometry_columns returned a null histogram");
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-//elog(NOTICE,"postgis_gist_sel: checking against estimate_histogram2d");
-                       // now we have the histogram, and our search box - use the estimate_histogram2d(histo,box) to get the result!
-                       myest =
-                                       DatumGetFloat8( DirectFunctionCall2( estimate_histogram2d, datum, PointerGetDatum(search_box) ) );
-
-                       if ( (myest<0) || (myest!=myest) ) // <0?  or NaN?
-                       {
-                               //elog(NOTICE,"postgis_gist_sel: got something crazy back from estimate_histogram2d");
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-
-
-
-
-                       SPIcode =SPI_finish();
-                       if (SPIcode  != SPI_OK_FINISH )
-                       {
-                               //elog(NOTICE,"postgis_gist_sel: couldnt disconnect from SPI");
-                               PG_RETURN_FLOAT8(0.000005) ;
-                       }
-//elog(NOTICE,"postgis_gist_sel: finished, returning with %lf",myest);
-        PG_RETURN_FLOAT8(myest);
-}
-
-static void
-genericcostestimate2(Query *root, RelOptInfo *rel,
-                                       IndexOptInfo *index, List *indexQuals,
-                                       Cost *indexStartupCost,
-                                       Cost *indexTotalCost,
-                                       Selectivity *indexSelectivity,
-                                       double *indexCorrelation)
-{
-       double          numIndexTuples;
-       double          numIndexPages;
-       List            *selectivityQuals = indexQuals;
-#if USE_VERSION >= 74
-       QualCost        index_qual_cost;
-#endif
-
-
-//elog(NOTICE,"in genericcostestimate");
-
-
-       /*
-        * If the index is partial, AND the index predicate with the
-        * explicitly given indexquals to produce a more accurate idea of the
-        * index restriction.  This may produce redundant clauses, which we
-        * hope that cnfify and clauselist_selectivity will deal with
-        * intelligently.
-        *
-        * Note that index->indpred and indexQuals are both in implicit-AND form
-        * to start with, which we have to make explicit to hand to
-        * canonicalize_qual, and then we get back implicit-AND form again.
-        */
-       if (index->indpred != NIL)
-       {
-               Expr       *andedQuals;
-
-               andedQuals = make_ands_explicit(nconc(listCopy(index->indpred),
-                                                                                         indexQuals));
-               selectivityQuals = canonicalize_qual(andedQuals, true);
-       }
-
-
-
-       /* Estimate the fraction of main-table tuples that will be visited */
-       *indexSelectivity = clauselist_selectivity(root, selectivityQuals,
-#if USE_VERSION < 74
-               lfirsti(rel->relids));
-#else
-               rel->relid, JOIN_INNER);
-#endif
-
-       /*
-        * Estimate the number of tuples that will be visited.  We do it in
-        * this rather peculiar-looking way in order to get the right answer
-        * for partial indexes.  We can bound the number of tuples by the
-        * index size, in any case.
-        */
-       numIndexTuples = *indexSelectivity * rel->tuples;
-
-       //elog(NOTICE,"relation has %li pages",rel->pages);
-       //elog(NOTICE,"indexselectivity is %lf, ntuples = %lf, numindexTuples = %lf, index->tuples = %lf",*indexSelectivity, rel->tuples, numIndexTuples,index->tuples);
-
-
-       if (numIndexTuples > index->tuples)
-               numIndexTuples = index->tuples;
-
-       /*
-        * Always estimate at least one tuple is touched, even when
-        * indexSelectivity estimate is tiny.
-        */
-       if (numIndexTuples < 1.0)
-               numIndexTuples = 1.0;
-
-       /*
-        * Estimate the number of index pages that will be retrieved.
-        *
-        * For all currently-supported index types, the first page of the index
-        * is a metadata page, and we should figure on fetching that plus a
-        * pro-rated fraction of the remaining pages.
-        */
-
-
-        //elog(NOTICE,"index->pages =  %li ",index->pages);
-
-       if (index->pages > 1 && index->tuples > 0)
-       {
-               numIndexPages = (numIndexTuples / index->tuples) * (index->pages - 1);
-               numIndexPages += 1;             /* count the metapage too */
-               numIndexPages = ceil(numIndexPages);
-       }
-       else
-               numIndexPages = 1.0;
-
-
-//elog(NOTICE,"numIndexPages =  %lf ",numIndexPages);
-       /*
-        * Compute the index access cost.
-        *
-        * Our generic assumption is that the index pages will be read
-        * sequentially, so they have cost 1.0 each, not random_page_cost.
-        * Also, we charge for evaluation of the indexquals at each index
-        * tuple. All the costs are assumed to be paid incrementally during
-        * the scan.
-        */
-
-#if USE_VERSION < 74
-       *indexStartupCost = 0;
-       *indexTotalCost = numIndexPages +
-               (cpu_index_tuple_cost + cost_qual_eval(indexQuals)) *
-               numIndexTuples;
-#else
-       cost_qual_eval(&index_qual_cost, indexQuals);
-       *indexStartupCost = index_qual_cost.startup;
-       *indexTotalCost = numIndexPages +
-               (cpu_index_tuple_cost + index_qual_cost.per_tuple) *
-               numIndexTuples;
-#endif
-
-
-       //elog(NOTICE,"cpu_index_tuple_cost = %lf, cost_qual_eval(indexQuals)) = %lf",
-       //      cpu_index_tuple_cost,cost_qual_eval(indexQuals));
-
-       //elog(NOTICE,"indexTotalCost =  %lf ",*indexTotalCost);
-
-       /*
-        * Generic assumption about index correlation: there isn't any.
-        */
-       *indexCorrelation = 0.97;
-       //elog(NOTICE,"indexcorrelation =  %lf ",*indexCorrelation);
-}
-
-
-PG_FUNCTION_INFO_V1(postgisgistcostestimate);
-Datum
-postgisgistcostestimate(PG_FUNCTION_ARGS)
-{
-    Query      *root = (Query *) PG_GETARG_POINTER(0);
-    RelOptInfo *rel = (RelOptInfo *) PG_GETARG_POINTER(1);
-    IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(2);
-    List       *indexQuals = (List *) PG_GETARG_POINTER(3);
-    Cost       *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
-    Cost       *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
-    Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
-    double     *indexCorrelation = (double *) PG_GETARG_POINTER(7);
-
-//elog(NOTICE,"postgisgistcostestimate was called");
-
-    genericcostestimate2(root, rel, index, indexQuals,
-                        indexStartupCost, indexTotalCost,
-                        indexSelectivity, indexCorrelation);
-//elog(NOTICE,"postgisgistcostestimate is going to return void");
-
-    PG_RETURN_VOID();
-}
-
-#else // USE_VERSION >= 80
-
-/*
- * This function returns an estimate of the selectivity
- * of a search_box looking at data in the GEOM_STATS 
- * structure.
- *
- * TODO: handle box dimension collapses
- */
-static float8
-estimate_selectivity(BOX *box, GEOM_STATS *geomstats)
-{
-       int x, y;
-       int x_idx_min, x_idx_max, y_idx_min, y_idx_max;
-       double intersect_x, intersect_y, AOI;
-       double cell_area, box_area;
-       double geow, geoh; // width and height of histogram
-       int histocols, historows; // histogram grid size
-       double value;
-       float overlapping_cells;
-       float avg_feat_cells;
-       double gain;
-       float8 selectivity;
-
-
-       /*
-        * Search box completely miss histogram extent
-        */
-       if ( box->high.x < geomstats->xmin ||
-               box->low.x > geomstats->xmax ||
-               box->high.y < geomstats->ymin ||
-               box->low.y > geomstats->ymax )
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box does not overlaps histogram, returning 0");
-#endif
-               return 0.0;
-       }
-
-       /*
-        * Search box completely contains histogram extent
-        */
-       if ( box->high.x >= geomstats->xmax &&
-               box->low.x <= geomstats->xmin &&
-               box->high.y >= geomstats->ymax &&
-               box->low.y <= geomstats->ymin )
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box contains histogram, returning 1");
-#endif
-               return 1.0;
-       }
-
-       geow = geomstats->xmax-geomstats->xmin;
-       geoh = geomstats->ymax-geomstats->ymin;
-
-       histocols = geomstats->cols;
-       historows = geomstats->rows;
-
-       cell_area = (geow*geoh) / (histocols*historows);
-       box_area = (box->high.x-box->low.x)*(box->high.y-box->low.y);
-       value = 0;
-
-       /* Find first overlapping column */
-       x_idx_min = (box->low.x-geomstats->xmin) / geow * histocols;
-       if (x_idx_min < 0) {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box overlaps %d columns on the left of histogram grid", -x_idx_min);
-#endif
-               // should increment the value somehow
-               x_idx_min = 0;
-       }
-       if (x_idx_min >= histocols)
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box overlaps %d columns on the right of histogram grid", x_idx_min-histocols+1);
-#endif
-               // should increment the value somehow
-               x_idx_min = histocols-1;
-       }
-
-       /* Find first overlapping row */
-       y_idx_min = (box->low.y-geomstats->ymin) / geoh * historows;
-       if (y_idx_min <0)
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box overlaps %d columns on the bottom of histogram grid", -y_idx_min);
-#endif
-               // should increment the value somehow
-               y_idx_min = 0;
-       }
-       if (y_idx_min >= historows)
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " search_box overlaps %d columns on the top of histogram grid", y_idx_min-historows+1);
-#endif
-               // should increment the value somehow
-               y_idx_min = historows-1;
-       }
-
-       /* Find last overlapping column */
-       x_idx_max = (box->high.x-geomstats->xmin) / geow * histocols;
-       if (x_idx_max <0)
-       {
-               // should increment the value somehow
-               x_idx_max = 0;
-       }
-       if (x_idx_max >= histocols )
-       {
-               // should increment the value somehow
-               x_idx_max = histocols-1;
-       }
-
-       /* Find last overlapping row */
-       y_idx_max = (box->high.y-geomstats->ymin) / geoh * historows;
-       if (y_idx_max <0)
-       {
-               // should increment the value somehow
-               y_idx_max = 0;
-       }
-       if (y_idx_max >= historows)
-       {
-               // should increment the value somehow
-               y_idx_max = historows-1;
-       }
-
-       /*
-        * the {x,y}_idx_{min,max}
-        * define the grid squares that the box intersects
-        */
-       for (y=y_idx_min; y<=y_idx_max; y++)
-       {
-               for (x=x_idx_min; x<=x_idx_max; x++)
-               {
-                       double val;
-                       double gain;
-
-                       val = geomstats->value[x+y*histocols];
-
-                       /*
-                        * Of the cell value we get
-                        * only the overlap fraction.
-                        */
-
-                       intersect_x = min(box->high.x, geomstats->xmin + (x+1) * geow / histocols) - max(box->low.x, geomstats->xmin + x * geow / histocols );
-                       intersect_y = min(box->high.y, geomstats->ymin + (y+1) * geoh / historows) - max(box->low.y, geomstats->ymin+ y * geoh / historows) ;
-                       
-                       AOI = intersect_x*intersect_y;
-                       gain = AOI/cell_area;
-
-#if DEBUG_GEOMETRY_STATS > 1
-                       elog(NOTICE, " [%d,%d] cell val %.15f",
-                                       x, y, val);
-                       elog(NOTICE, " [%d,%d] AOI %.15f",
-                                       x, y, AOI);
-                       elog(NOTICE, " [%d,%d] gain %.15f",
-                                       x, y, gain);
-#endif
-
-                       val *= gain;
-
-#if DEBUG_GEOMETRY_STATS > 1
-                       elog(NOTICE, " [%d,%d] adding %.15f to value",
-                               x, y, val);
-#endif
-                       value += val;
-               }
-       }
-
-
-       /*
-        * If the search_box is a point, it will
-        * overlap a single cell and thus get
-        * it's value, which is the fraction of
-        * samples (we can presume of row set also)
-        * which bumped to that cell.
-        *
-        * If the table features are points, each
-        * of them will overlap a single histogram cell.
-        * Our search_box value would then be correctly
-        * computed as the sum of the bumped cells values.
-        *
-        * If both our search_box AND the sample features
-        * overlap more then a single histogram cell we
-        * need to consider the fact that our sum computation
-        * will have many duplicated included. E.g. each
-        * single sample feature would have contributed to
-        * raise the search_box value by as many times as
-        * many cells in the histogram are commonly overlapped
-        * by both searc_box and feature. We should then
-        * divide our value by the number of cells in the virtual
-        * 'intersection' between average feature cell occupation
-        * and occupation of the search_box. This is as 
-        * fuzzy as you understand it :)
-        *
-        * Consistency check: whenever the number of cells is
-        * one of whichever part (search_box_occupation,
-        * avg_feature_occupation) the 'intersection' must be 1.
-        * If sounds that our 'intersaction' is actually the
-        * minimun number between search_box_occupation and
-        * avg_feat_occupation.
-        *
-        */
-       overlapping_cells = (x_idx_max-x_idx_min+1) *
-               (y_idx_max-y_idx_min+1);
-       avg_feat_cells = geomstats->avgFeatureCells;
-
-#if DEBUG_GEOMETRY_STATS
-elog(NOTICE, " search_box overlaps %f cells", overlapping_cells);
-elog(NOTICE, " avg feat overlaps %f cells", avg_feat_cells);
-#endif
-
-       gain = 1/min(overlapping_cells, avg_feat_cells);
-       selectivity = value*gain;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " SUM(ov_histo_cells)=%f", value);
-       elog(NOTICE, " gain=%f", gain);
-       elog(NOTICE, " selectivity=%f", selectivity);
-#endif
-
-       /* prevent rounding overflows */
-       if (selectivity > 1.0) selectivity = 1.0;
-       else if (selectivity < 0) selectivity = 0.0;
-
-       return selectivity;
-}
-
-/*
- * This function should return an estimation of the number of
- * rows returned by a query involving an overlap check 
- * ( it's the restrict function for the && operator )
- *
- * It can make use (if available) of the statistics collected
- * by the geometry analyzer function.
- *
- * Note that the good work is done by estimate_selectivity() above.
- * This function just tries to find the search_box, loads the statistics
- * and invoke the work-horse.
- *
- * This is the one used for PG version >= 7.5
- *
- */
-PG_FUNCTION_INFO_V1(postgis_gist_sel);
-Datum postgis_gist_sel(PG_FUNCTION_ARGS)
-{
-       Query *root = (Query *) PG_GETARG_POINTER(0);
-       //Oid operator = PG_GETARG_OID(1);
-       List *args = (List *) PG_GETARG_POINTER(2);
-       int varRelid = PG_GETARG_INT32(3);
-       Oid relid;
-       HeapTuple stats_tuple;
-       GEOM_STATS *geomstats;
-       int geomstats_nvalues=0;
-       Node *other;
-       Var *self;
-       GEOMETRY *in;
-       BOX *search_box;
-       float8 selectivity=0;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, "postgis_gist_sel called");
-#endif
-
-        /* Fail if not a binary opclause (probably shouldn't happen) */
-       if (list_length(args) != 2)
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, "postgis_gist_sel: not a binary opclause");
-#endif
-               PG_RETURN_FLOAT8(DEFAULT_GEOMETRY_SEL);
-       }
-
-
-       /*
-        * Find the constant part
-        */
-       other = (Node *) linitial(args);
-       if ( ! IsA(other, Const) ) 
-       {
-               self = (Var *)other;
-               other = (Node *) lsecond(args);
-       }
-       else
-       {
-               self = (Var *) lsecond(args);
-       }
-
-       if ( ! IsA(other, Const) ) 
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " no constant arguments - returning default selectivity");
-#endif
-               PG_RETURN_FLOAT8(DEFAULT_GEOMETRY_SEL);
-       }
-
-       /*
-        * We are working on two constants..
-        * TODO: check if expression is true,
-        *       returned set would be either 
-        *       the whole or none.
-        */
-       if ( ! IsA(self, Var) ) 
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " no variable argument ? - returning default selectivity");
-#endif
-               PG_RETURN_FLOAT8(DEFAULT_GEOMETRY_SEL);
-       }
-
-       /*
-        * Convert the constant to a BOX
-        */
-
-       in = (GEOMETRY*)PG_DETOAST_DATUM( ((Const*)other)->constvalue );
-       search_box = convert_box3d_to_box(&in->bvol);
-#if DEBUG_GEOMETRY_STATS > 1
-       elog(NOTICE," requested search box is : %.15g %.15g, %.15g %.15g",search_box->low.x,search_box->low.y,search_box->high.x,search_box->high.y);
-#endif
-
-       /*
-        * Get pg_statistic row
-        */
-
-       relid = getrelid(varRelid, root->rtable);
-
-       stats_tuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(relid), Int16GetDatum(self->varattno), 0, 0);
-       if ( ! stats_tuple )
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " No statistics, returning default estimate");
-#endif
-               PG_RETURN_FLOAT8(DEFAULT_GEOMETRY_SEL);
-       }
-
-
-       if ( ! get_attstatsslot(stats_tuple, 0, 0,
-               STATISTIC_KIND_GEOMETRY, InvalidOid, NULL, NULL,
-               (float4 **)&geomstats, &geomstats_nvalues) )
-       {
-#if DEBUG_GEOMETRY_STATS
-               elog(NOTICE, " STATISTIC_KIND_GEOMETRY stats not found - returning default geometry selectivity");
-#endif
-               ReleaseSysCache(stats_tuple);
-               PG_RETURN_FLOAT8(DEFAULT_GEOMETRY_SEL);
-
-       }
-
-#if DEBUG_GEOMETRY_STATS > 1
-               elog(NOTICE, " %d read from stats", geomstats_nvalues);
-#endif
-
-#if DEBUG_GEOMETRY_STATS > 1
-       elog(NOTICE, " histo: xmin,ymin: %f,%f",
-               geomstats->xmin, geomstats->ymin);
-       elog(NOTICE, " histo: xmax,ymax: %f,%f",
-               geomstats->xmax, geomstats->ymax);
-       elog(NOTICE, " histo: cols: %f", geomstats->rows);
-       elog(NOTICE, " histo: rows: %f", geomstats->cols);
-       elog(NOTICE, " histo: avgFeatureArea: %f", geomstats->avgFeatureArea);
-       elog(NOTICE, " histo: avgFeatureCells: %f", geomstats->avgFeatureCells);
-#endif
-
-       /*
-        * Do the estimation
-        */
-       selectivity = estimate_selectivity(search_box, geomstats);
-
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " returning computed value: %f", selectivity);
-#endif
-
-       free_attstatsslot(0, NULL, 0, (float *)geomstats, geomstats_nvalues);
-       ReleaseSysCache(stats_tuple);
-       PG_RETURN_FLOAT8(selectivity);
-
-}
-
-/*
- * This function is called by the analyze function iff
- * the geometry_analyze() function give it its pointer
- * (this is always the case so far).
- * The geometry_analyze() function is also responsible
- * of deciding the number of "sample" rows we will receive
- * here. It is able to give use other 'custom' data, but we
- * won't use them so far.
- *
- * Our job is to build some statistics on the sample data
- * for use by operator estimators.
- *
- * Currently we only need statistics to estimate the number of rows
- * overlapping a given extent (estimation function bound
- * to the && operator).
- *
- */
-static void
-compute_geometry_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
-               int samplerows, double totalrows)
-{
-       MemoryContext old_context;
-       int i;
-       int geom_stats_size;
-       BOX **sampleboxes;
-       GEOM_STATS *geomstats;
-       bool isnull;
-       int null_cnt=0, notnull_cnt=0, examinedsamples=0;
-       BOX3D *sample_extent=NULL;
-       double total_width=0;
-       double total_boxes_area=0;
-       int total_boxes_cells=0;
-       double cell_area;
-       double cell_width;
-       double cell_height;
-#if USE_STANDARD_DEVIATION
-       /* for standard deviation */
-       double avgLOWx, avgLOWy, avgHIGx, avgHIGy;
-       double sumLOWx=0, sumLOWy=0, sumHIGx=0, sumHIGy=0;
-       double sdLOWx=0, sdLOWy=0, sdHIGx=0, sdHIGy=0;
-       BOX *newhistobox=NULL;
-#endif
-       double geow, geoh; // width and height of histogram
-       int histocells;
-       int cols, rows; // histogram grid size
-       BOX histobox;
-
-       /*
-        * This is where geometry_analyze
-        * should put its' custom parameters.
-        */
-       //void *mystats = stats->extra_data;
-       
-       /*
-        * We'll build an histogram having from 40 to 400 boxesPerSide
-        * Total number of cells is determined by attribute stat
-        * target. It can go from  1600 to 160000 (stat target: 10,1000)
-        */
-       histocells = 160*stats->attr->attstattarget;
-
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, "compute_geometry_stats called");
-       elog(NOTICE, " samplerows: %d", samplerows);
-       elog(NOTICE, " histogram cells: %d", histocells);
-#endif
-
-       /*
-        * We might need less space, but don't think
-        * its worth saving...
-        */
-       sampleboxes = palloc(sizeof(BOX *)*samplerows);
-
-       /*
-        * First scan:
-        *  o find extent of the sample rows
-        *  o count null-infinite/not-null values
-        *  o compute total_width
-        *  o compute total features's box area (for avgFeatureArea)
-        *  o sum features box coordinates (for standard deviation)
-        */
-       for (i=0; i<samplerows; i++)
-       {
-               Datum datum;
-               GEOMETRY *geom;
-               BOX *box;
-
-               datum = fetchfunc(stats, i, &isnull);
-
-               /*
-                * Skip nulls
-                */
-               if ( isnull ) {
-                       null_cnt++;
-                       continue;
-               }
-
-               geom = (GEOMETRY *) PG_DETOAST_DATUM(datum);
-
-               /*
-                * Skip infinite geoms
-                */
-               if ( ! finite(geom->bvol.LLB.x) ||
-                       ! finite(geom->bvol.LLB.y) ||
-                       ! finite(geom->bvol.URT.x) ||
-                       ! finite(geom->bvol.URT.y) )
-               {
-#if DEBUG_GEOMETRY_STATS 
-                       elog(NOTICE, " skipped infinite geometry %d", i);
-#endif
-                       continue;
-               }
-
-               /*
-                * Cache bounding box
-                */
-               box = convert_box3d_to_box(&(geom->bvol));
-               sampleboxes[notnull_cnt] = box;
-
-               /*
-                * Add to sample extent union
-                */
-               sample_extent = union_box3d(&(geom->bvol), sample_extent);
-               
-               // TODO: ask if we need geom or bvol size for stawidth
-               total_width += geom->size;
-               total_boxes_area += (box->high.x-box->low.x)*(box->high.y-box->low.y);
-
-#if USE_STANDARD_DEVIATION
-               /*
-                * Add bvol coordinates to sum for standard deviation 
-                * computation.
-                */
-               sumLOWx += box->low.x;
-               sumLOWy += box->low.y;
-               sumHIGx += box->high.x;
-               sumHIGy += box->high.y;
-#endif
-
-               notnull_cnt++;
-
-               /* give backend a chance of interrupting us */
-               vacuum_delay_point();
-
-       }
-
-       if ( ! notnull_cnt ) {
-               elog(NOTICE, " no notnull values, invalid stats");
-               stats->stats_valid = false;
-               return;
-       }
-
-#if USE_STANDARD_DEVIATION
-
-#if DEBUG_GEOMETRY_STATS 
-       elog(NOTICE, " sample_extent: xmin,ymin: %f,%f",
-               sample_extent->LLB.x, sample_extent->LLB.y);
-       elog(NOTICE, " sample_extent: xmax,ymax: %f,%f",
-               sample_extent->URT.x, sample_extent->URT.y);
-#endif
-
-       /*
-        * Second scan:
-        *  o compute standard deviation
-        */
-       avgLOWx = sumLOWx/notnull_cnt;
-       avgLOWy = sumLOWy/notnull_cnt;
-       avgHIGx = sumHIGx/notnull_cnt;
-       avgHIGy = sumHIGy/notnull_cnt;
-       for (i=0; i<notnull_cnt; i++)
-       {
-               BOX *box;
-               box = (BOX *)sampleboxes[i];
-
-               sdLOWx += (box->low.x - avgLOWx) * (box->low.x - avgLOWx);
-               sdLOWy += (box->low.y - avgLOWy) * (box->low.y - avgLOWy);
-               sdHIGx += (box->high.x - avgHIGx) * (box->high.x - avgHIGx);
-               sdHIGy += (box->high.y - avgHIGy) * (box->high.y - avgHIGy);
-       }
-       sdLOWx = sqrt(sdLOWx/(notnull_cnt-1));
-       sdLOWy = sqrt(sdLOWy/(notnull_cnt-1));
-       sdHIGx = sqrt(sdHIGx/(notnull_cnt-1));
-       sdHIGy = sqrt(sdHIGy/(notnull_cnt-1));
-
-#if DEBUG_GEOMETRY_STATS 
-       elog(NOTICE, " standard deviations:");
-       elog(NOTICE, "  LOWx - avg:%f sd:%f", avgLOWx, sdLOWx);
-       elog(NOTICE, "  LOWy - avg:%f sd:%f", avgLOWy, sdLOWy);
-       elog(NOTICE, "  HIGx - avg:%f sd:%f", avgHIGx, sdHIGx);
-       elog(NOTICE, "  HIGy - avg:%f sd:%f", avgHIGy, sdHIGy);
-#endif
-
-       histobox.low.x = max((avgLOWx - SDFACTOR * sdLOWx),
-               sample_extent->LLB.x);
-       histobox.low.y = max((avgLOWy - SDFACTOR * sdLOWy),
-               sample_extent->LLB.y);
-       histobox.high.x = min((avgHIGx + SDFACTOR * sdHIGx),
-               sample_extent->URT.x); 
-       histobox.high.y = min((avgHIGy + SDFACTOR * sdHIGy),
-               sample_extent->URT.y); 
-
-#if DEBUG_GEOMETRY_STATS 
-       elog(NOTICE, " sd_extent: xmin,ymin: %f,%f",
-               histobox.low.x, histobox.low.y);
-       elog(NOTICE, " sd_extent: xmax,ymax: %f,%f",
-               histobox.high.x, histobox.high.y);
-#endif
-
-       /*
-        * Third scan:
-        *   o skip hard deviants
-        *   o compute new histogram box
-        */
-       for (i=0; i<notnull_cnt; i++)
-       {
-               BOX *box;
-               box = (BOX *)sampleboxes[i];
-
-               if ( box->low.x > histobox.high.x ||
-                       box->high.x < histobox.low.x ||
-                       box->low.y > histobox.high.y ||
-                       box->high.y < histobox.low.y )
-               {
-#if DEBUG_GEOMETRY_STATS > 1
-       elog(NOTICE, " feat %d is an hard deviant, skipped", i);
-#endif
-                       sampleboxes[i] = NULL;
-                       continue;
-               }
-               if ( ! newhistobox ) {
-                       newhistobox = palloc(sizeof(BOX));
-                       memcpy(newhistobox, box, sizeof(BOX));
-               } else {
-                       if ( box->low.x < newhistobox->low.x )
-                               newhistobox->low.x = box->low.x;
-                       if ( box->low.y < newhistobox->low.y )
-                               newhistobox->low.y = box->low.y;
-                       if ( box->high.x > newhistobox->high.x )
-                               newhistobox->high.x = box->high.x;
-                       if ( box->high.y > newhistobox->high.y )
-                               newhistobox->high.y = box->high.y;
-               }
-       }
-
-       /*
-        * Set histogram extent as the intersection between
-        * standard deviation based histogram extent 
-        * and computed sample extent after removal of
-        * hard deviants (there might be no hard deviants).
-        */
-       if ( histobox.low.x < newhistobox->low.x )
-               histobox.low.x = newhistobox->low.x;
-       if ( histobox.low.y < newhistobox->low.y )
-               histobox.low.y = newhistobox->low.y;
-       if ( histobox.high.x > newhistobox->high.x )
-               histobox.high.x = newhistobox->high.x;
-       if ( histobox.high.y > newhistobox->high.y )
-               histobox.high.y = newhistobox->high.y;
-
-
-#else // ! USE_STANDARD_DEVIATION
-
-       /*
-        * Set histogram extent box
-        */
-       histobox.low.x = sample_extent->LLB.x;
-       histobox.low.y = sample_extent->LLB.y;
-       histobox.high.x = sample_extent->URT.x;
-       histobox.high.y = sample_extent->URT.y;
-#endif // USE_STANDARD_DEVIATION
-
-
-#if DEBUG_GEOMETRY_STATS 
-       elog(NOTICE, " histogram_extent: xmin,ymin: %f,%f",
-               histobox.low.x, histobox.low.y);
-       elog(NOTICE, " histogram_extent: xmax,ymax: %f,%f",
-               histobox.high.x, histobox.high.y);
-#endif
-
-
-       geow = histobox.high.x - histobox.low.x;
-       geoh = histobox.high.y - histobox.low.y;
-
-       /*
-        * Compute histogram cols and rows based on aspect ratio
-        * of histogram extent
-        */
-       if ( ! geow && ! geoh ) {
-               cols = 1;
-               rows = 1;
-               histocells = 1;
-       } else if ( ! geow ) {
-               cols = 1;
-               rows = histocells;
-       } else if ( ! geoh ) {
-               cols = histocells;
-               rows = 1;
-       } else {
-               if ( geow<geoh) {
-                       cols = ceil(sqrt((double)histocells*(geow/geoh)));
-                       rows = ceil((double)histocells/cols);
-               } else {
-                       rows = ceil(sqrt((double)histocells*(geoh/geow)));
-                       cols = ceil((double)histocells/rows);
-               }
-               histocells = cols*rows;
-       }
-#if DEBUG_GEOMETRY_STATS 
-       elog(NOTICE, " computed histogram grid size (CxR): %dx%d (%d cells)", cols, rows, histocells);
-#endif
-
-
-       /*
-        * Create the histogram (GEOM_STATS)
-        */
-       old_context = MemoryContextSwitchTo(stats->anl_context);
-       geom_stats_size=sizeof(GEOM_STATS)+(histocells-1)*sizeof(float4);
-       geomstats = palloc(geom_stats_size);
-       MemoryContextSwitchTo(old_context);
-
-       geomstats->avgFeatureArea = total_boxes_area/notnull_cnt;
-       geomstats->xmin = histobox.low.x;
-       geomstats->ymin = histobox.low.y;
-       geomstats->xmax = histobox.high.x;
-       geomstats->ymax = histobox.high.y;
-       geomstats->cols = cols;
-       geomstats->rows = rows;
-
-       // Initialize all values to 0
-       for (i=0;i<histocells; i++) geomstats->value[i] = 0;
-
-       cell_width = geow/cols;
-       cell_height = geoh/rows;
-       cell_area = cell_width*cell_height;
-
-#if DEBUG_GEOMETRY_STATS > 2
-       elog(NOTICE, "cell_width: %f", cell_width);
-       elog(NOTICE, "cell_height: %f", cell_height);
-#endif
-       
-
-       /*
-        * Fourth scan:
-        *  o fill histogram values with the number of
-        *    features' bbox overlaps: a feature's bvol
-        *    can fully overlap (1) or partially overlap
-        *    (fraction of 1) an histogram cell.
-        *
-        *  o compute total cells occupation
-        *
-        */
-       for (i=0; i<notnull_cnt; i++)
-       {
-               BOX *box;
-               int x_idx_min, x_idx_max, x;
-               int y_idx_min, y_idx_max, y;
-               int numcells=0;
-
-               box = (BOX *)sampleboxes[i];
-               if ( ! box ) continue; // hard deviant..
-
-               /* give backend a chance of interrupting us */
-               vacuum_delay_point();
-
-#if DEBUG_GEOMETRY_STATS > 2
-               elog(NOTICE, " feat %d box is %f %f, %f %f",
-                               i, box->high.x, box->high.y,
-                               box->low.x, box->low.y);
-#endif
-                                                       
-               /* Find first overlapping column */
-               x_idx_min = (box->low.x-geomstats->xmin) / geow * cols;
-               if (x_idx_min <0) x_idx_min = 0;
-               if (x_idx_min >= cols) x_idx_min = cols-1;
-
-               /* Find first overlapping row */
-               y_idx_min = (box->low.y-geomstats->ymin) / geoh * rows;
-               if (y_idx_min <0) y_idx_min = 0;
-               if (y_idx_min >= rows) y_idx_min = rows-1;
-
-               /* Find last overlapping column */
-               x_idx_max = (box->high.x-geomstats->xmin) / geow * cols;
-               if (x_idx_max <0) x_idx_max = 0;
-               if (x_idx_max >= cols ) x_idx_max = cols-1;
-
-               /* Find last overlapping row */
-               y_idx_max = (box->high.y-geomstats->ymin) / geoh * rows;
-               if (y_idx_max <0) y_idx_max = 0;
-               if (y_idx_max >= rows) y_idx_max = rows-1;
-#if DEBUG_GEOMETRY_STATS > 2
-               elog(NOTICE, " feat %d overlaps columns %d-%d, rows %d-%d",
-                               i, x_idx_min, x_idx_max, y_idx_min, y_idx_max);
-#endif
-
-               /*
-                * the {x,y}_idx_{min,max}
-                * define the grid squares that the box intersects
-                */
-               for (y=y_idx_min; y<=y_idx_max; y++)
-               {
-                       for (x=x_idx_min; x<=x_idx_max; x++)
-                       {
-                               geomstats->value[x+y*cols] += 1;
-                               numcells++;
-                       }
-               }
-
-               // before adding to the total cells
-               // we could decide if we really 
-               // want this feature to count
-               total_boxes_cells += numcells;
-
-               examinedsamples++;
-       }
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " examined_samples: %d/%d", examinedsamples, samplerows);
-#endif
-
-       if ( ! examinedsamples ) {
-               elog(NOTICE, " no examined values, invalid stats");
-               stats->stats_valid = false;
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " no stats have been gathered");
-#endif
-               return;
-       }
-
-       // what about null features (TODO) ?
-       geomstats->avgFeatureCells = (float4)total_boxes_cells/examinedsamples;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " histo: total_boxes_cells: %d", total_boxes_cells);
-       elog(NOTICE, " histo: avgFeatureArea: %f", geomstats->avgFeatureArea);
-       elog(NOTICE, " histo: avgFeatureCells: %f", geomstats->avgFeatureCells);
-#endif
-
-
-       /*
-        * Normalize histogram
-        *
-        * We divide each histogram cell value
-        * by the number of samples examined.
-        *
-        */
-       for (i=0; i<histocells; i++)
-               geomstats->value[i] /= examinedsamples;
-
-#if DEBUG_GEOMETRY_STATS > 1
-       {
-               int x, y;
-               for (x=0; x<cols; x++)
-               {
-                       for (y=0; y<rows; y++)
-                       {
-                               elog(NOTICE, " histo[%d,%d] = %.15f", x, y, geomstats->value[x+y*cols]);
-                       }
-               }
-       }
-#endif
-
-       /*
-        * Write the statistics data 
-        */
-       stats->stakind[0] = STATISTIC_KIND_GEOMETRY;
-       stats->staop[0] = InvalidOid;
-       stats->stanumbers[0] = (float4 *)geomstats;
-       stats->numnumbers[0] = geom_stats_size/sizeof(float4);
-
-       stats->stanullfrac = null_cnt/samplerows;
-       stats->stawidth = total_width/notnull_cnt;
-       stats->stadistinct = -1.0;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " out: slot 0: kind %d (STATISTIC_KIND_GEOMETRY)",
-               stats->stakind[0]);
-       elog(NOTICE, " out: slot 0: op %d (InvalidOid)", stats->staop[0]);
-       elog(NOTICE, " out: slot 0: numnumbers %d", stats->numnumbers[0]);
-       elog(NOTICE, " out: null fraction: %d/%d", null_cnt, samplerows);
-       elog(NOTICE, " out: average width: %d bytes", stats->stawidth);
-       elog(NOTICE, " out: distinct values: all (no check done)");
-#endif
-
-       stats->stats_valid = true;
-}
-
-/*
- * This function will be called when the ANALYZE command is run
- * on a column of the "geometry" type.
- * 
- * It will need to return a stats builder function reference
- * and a "minimum" sample rows to feed it.
- * If we want analisys to be completely skipped we can return
- * FALSE and leave output vals untouched.
- *
- * What we know from this call is:
- *
- *     o The pg_attribute row referring to the specific column.
- *       Could be used to get reltuples from pg_class (which 
- *       might quite inexact though...) and use them to set an
- *       appropriate minimum number of sample rows to feed to
- *       the stats builder. The stats builder will also receive
- *       a more accurate "estimation" of the number or rows.
- *
- *     o The pg_type row for the specific column.
- *       Could be used to set stat builder / sample rows
- *       based on domain type (when postgis will be implemented
- *       that way).
- *
- * Being this experimental we'll stick to a static stat_builder/sample_rows
- * value for now.
- *
- */
-PG_FUNCTION_INFO_V1(geometry_analyze);
-Datum geometry_analyze(PG_FUNCTION_ARGS)
-{
-       VacAttrStats *stats = (VacAttrStats *)PG_GETARG_POINTER(0);
-       Form_pg_attribute attr = stats->attr;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, "geometry_analyze called");
-#endif
-
-       /* If the attstattarget column is negative, use the default value */
-       /* NB: it is okay to scribble on stats->attr since it's a copy */
-        if (attr->attstattarget < 0)
-                attr->attstattarget = default_statistics_target;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " attribute stat target: %d", attr->attstattarget);
-#endif
-
-       /*
-        * There might be a reason not to analyze this column
-        * (can we detect the absence of an index?)
-        */
-       //elog(NOTICE, "compute_geometry_stats not implemented yet");
-       //PG_RETURN_BOOL(false);
-
-       /* Setup the minimum rows and the algorithm function */
-       stats->minrows = 300 * stats->attr->attstattarget;
-       stats->compute_stats = compute_geometry_stats;
-
-#if DEBUG_GEOMETRY_STATS
-       elog(NOTICE, " minrows: %d", stats->minrows);
-#endif
-
-       /* Indicate we are done successfully */
-       PG_RETURN_BOOL(true);
-}
-       
-
-
-#endif
-
-
diff --git a/hwgeom/postgis_fn.c b/hwgeom/postgis_fn.c
deleted file mode 100644 (file)
index a449ffb..0000000
+++ /dev/null
@@ -1,3218 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.40  2004/08/26 16:55:09  strk
- * max_distance() raises an 'unimplemented yet' error.
- *
- * Revision 1.39  2004/07/28 16:10:59  strk
- * Changed all version functions to return text.
- * Renamed postgis_scripts_version() to postgis_scripts_installed()
- * Added postgis_scripts_released().
- * Added postgis_full_version().
- *
- * Revision 1.38  2004/07/28 13:37:43  strk
- * Added postgis_uses_stats and postgis_scripts_version.
- * Experimented with PIP short-circuit in within/contains functions.
- * Documented new version functions.
- *
- * Revision 1.37  2004/07/22 16:20:10  strk
- * Added postgis_lib_version() and postgis_geos_version()
- *
- * Revision 1.36  2004/06/03 16:44:56  strk
- * Added expand_geometry - expand(geometry, int8)
- *
- * Revision 1.35  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.34  2004/03/26 00:54:09  dblasby
- * added full support for fluffType(<geom>)
- * postgis09=# select fluffType('POINT(0 0)');
- *         flufftype
- *             -------------------------
- *              SRID=-1;MULTIPOINT(0 0)
- *
- * Revision 1.33  2004/03/25 00:43:41  dblasby
- * added function fluffType() that takes POINT LINESTRING or POLYGON
- * type and converts it to a multi*.
- * Needs to be integrated into a proper Postgresql function and given an
- * SQL CREATE FUNCTION
- *
- * Revision 1.32  2004/02/12 10:34:49  strk
- * changed USE_GEOS check from ifdef / ifndef to if / if !
- *
- * Revision 1.31  2003/11/11 10:58:43  strk
- * Fixed a typo in envelope()
- *
- * Revision 1.30  2003/10/29 15:53:10  strk
- * geoscentroid() removed. both geos and pgis versions are called 'centroid'.
- * only one version will be compiled based on USE_GEOS flag.
- *
- * Revision 1.29  2003/10/28 16:57:35  strk
- * Added collect_garray() function.
- *
- * Revision 1.28  2003/10/28 15:16:17  strk
- * unite_sfunc() from postgis_geos.c renamed to geom_accum() and moved in postgis_fn.c
- *
- * Revision 1.27  2003/10/17 16:12:23  dblasby
- * Made Envelope() CW instead of CCW.
- *
- * Revision 1.26  2003/10/17 16:07:05  dblasby
- * made isEmpty() return true/false
- *
- * Revision 1.25  2003/09/16 20:27:12  dblasby
- * added ability to delete geometries.
- *
- * Revision 1.24  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.23  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.22  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-#include "utils/array.h"
-
-#define NfunctionFirstPoint 1
-
-// if you use #define NfunctionFirstPoint 0, you get 0-based indexing (this is what programmers want)::
-//  pointN(<linestring>, 0) is the 1st point, and pointN(<linestring>, 1) is the second point.
-
-// if you use #define NfunctionFirstPoint 1, you get 1-based indexing (which seems to be what the spec wants)::
-//  pointN(<linestring>, 1) is the 1st point, and pointN(<linestring>, 2) is the second point.
-
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-// #define DEBUG_GIST
-//#define DEBUG_GIST2
-
-
-
-
-/**************************************************************************
- * GENERAL PURPOSE GEOMETRY FUNCTIONS
- **************************************************************************/
-
-
-double line_length2d(LINE3D *line)
-{
-       int     i;
-       POINT3D *frm,*to;
-       double  dist = 0.0;
-
-       if (line->npoints <2)
-               return 0.0;     //must have >1 point to make sense
-
-       frm = &line->points[0];
-
-       for (i=1; i<line->npoints;i++)
-       {
-               to = &line->points[i];
-
-               dist += sqrt( ( (frm->x - to->x)*(frm->x - to->x) )  +
-                                 ( (frm->y - to->y)*(frm->y - to->y) ) );
-
-               frm = to;
-       }
-       return dist;
-}
-
-double line_length3d(LINE3D *line)
-{
-       int     i;
-       POINT3D *frm,*to;
-       double  dist = 0.0;
-
-       if (line->npoints <2)
-               return 0.0;     //must have >1 point to make sense
-
-       frm = &line->points[0];
-
-       for (i=1; i<line->npoints;i++)
-       {
-               to = &line->points[i];
-
-               dist += sqrt( ( (frm->x - to->x)*(frm->x - to->x) )  +
-                               ((frm->y - to->y)*(frm->y - to->y) ) +
-                               ((frm->z - to->z)*(frm->z - to->z) ) );
-
-               frm = to;
-       }
-       return dist;
-}
-
-
-//find the "length of a geometry"
-// length3d(point) = 0
-// length3d(line) = length of line
-// length3d(polygon) = 0  -- could make sense to return sum(ring perimeter)
-// uses euclidian 3d length
-
-PG_FUNCTION_INFO_V1(length3d);
-Datum length3d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       LINE3D                  *line;
-       double                  dist = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-               if (type1 == LINETYPE)  //LINESTRING
-               {
-                       line = (LINE3D *) o1;
-                       dist += line_length3d(line);
-               }
-       }
-       PG_RETURN_FLOAT8(dist);
-}
-
-//find the "length of a geometry"
-// length3d(point) = 0
-// length3d(line) = length of line
-// length3d(polygon) = 0  -- could make sense to return sum(ring perimeter)
-// uses euclidian 2d length
-
-PG_FUNCTION_INFO_V1(length2d);
-Datum length2d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       LINE3D                  *line;
-       double                  dist = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-               if (type1 == LINETYPE)  //LINESTRING
-               {
-                       line = (LINE3D *) o1;
-                       dist += line_length2d(line);
-               }
-       }
-       PG_RETURN_FLOAT8(dist);
-}
-
-
-//find the 2d area of the outer ring - sum (area 2d of inner rings)
-// Could use a more numerically stable calculator...
-double polygon_area2d_old(POLYGON3D *poly1)
-{
-       double  poly_area=0.0, ringarea=0.0;
-       int i,j,ring,pt_offset;
-       POINT3D *pts1;
-
-
-       pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] )  );
-       pts1 = (POINT3D *) MAXALIGN(pts1);
-
-//elog(NOTICE,"in polygon_area2d_old");
-
-       pt_offset = 0; //index to first point in ring
-       for (ring = 0; ring < poly1->nrings; ring++)
-       {
-               ringarea = 0.0;
-
-               for (i=0;i<(poly1->npoints[ring]-1);i++)
-       {
-               //      j = (i+1) % (poly1->npoints[ring]);
-                       j = i+1;
-                       ringarea  += pts1[pt_offset+ i].x * pts1[pt_offset+j].y - pts1[pt_offset+ i].y * pts1[pt_offset+j].x;
-               }
-
-               ringarea  /= 2.0;
-//elog(NOTICE," ring 1 has area %lf",ringarea);
-               ringarea  = fabs(ringarea );
-               if (ring != 0)  //outer
-                       ringarea  = -1.0*ringarea ; // its a hole
-
-               poly_area += ringarea;
-
-               pt_offset += poly1->npoints[ring];
-       }
-
-       return poly_area;
-}
-
-
-
-//calculate the area of all the subobj in a polygon
-// area(point) = 0
-// area (line) = 0
-// area(polygon) = find its 2d area
-PG_FUNCTION_INFO_V1(area2d);
-Datum area2d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       POLYGON3D                       *poly;
-       double                  area = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       area += polygon_area2d_old(poly);
-               }
-       }
-       PG_RETURN_FLOAT8(area);
-}
-
-double         polygon_perimeter3d(POLYGON3D   *poly1)
-{
-       double  poly_perimeter=0.0, ring_perimeter=0.0;
-       int i,ring,pt_offset;
-       POINT3D *pts1;
-       POINT3D *to,*frm;
-
-
-       pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] )  );
-       pts1 = (POINT3D *) MAXALIGN(pts1);
-
-
-
-       pt_offset = 0; //index to first point in ring
-       for (ring = 0; ring < poly1->nrings; ring++)
-       {
-               ring_perimeter = 0.0;
-
-
-               frm = &pts1[pt_offset];
-
-               for (i=1; i<poly1->npoints[ring];i++)
-               {
-                       to = &pts1[pt_offset+ i];
-
-                       ring_perimeter += sqrt( ( (frm->x - to->x)*(frm->x - to->x) )  +
-                               ((frm->y - to->y)*(frm->y - to->y) ) +
-                               ((frm->z - to->z)*(frm->z - to->z) ) );
-
-                       frm = to;
-               }
-
-               poly_perimeter += ring_perimeter;
-
-               pt_offset += poly1->npoints[ring];
-       }
-
-       return poly_perimeter;
-
-}
-
-double         polygon_perimeter2d(POLYGON3D   *poly1)
-{
-       double  poly_perimeter=0.0, ring_perimeter=0.0;
-       int i,ring,pt_offset;
-       POINT3D *pts1;
-       POINT3D *to,*frm;
-
-
-       pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] )  );
-       pts1 = (POINT3D *) MAXALIGN(pts1);
-
-
-       pt_offset = 0; //index to first point in ring
-       for (ring = 0; ring < poly1->nrings; ring++)
-       {
-               ring_perimeter = 0.0;
-
-
-               frm = &pts1[pt_offset];
-
-               for (i=1; i<poly1->npoints[ring];i++)
-               {
-                       to = &pts1[pt_offset+ i];
-
-                       ring_perimeter += sqrt( ( (frm->x - to->x)*(frm->x - to->x) )  +
-                               ((frm->y - to->y)*(frm->y - to->y) )   );
-
-                       frm = to;
-               }
-
-               poly_perimeter += ring_perimeter;
-
-               pt_offset += poly1->npoints[ring];
-       }
-
-       return poly_perimeter;
-
-}
-
-
-
-//calculate the perimeter of polys (sum of length of all rings)
-PG_FUNCTION_INFO_V1(perimeter3d);
-Datum perimeter3d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       POLYGON3D                       *poly;
-       double                  area = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       area += polygon_perimeter3d(poly);
-               }
-       }
-       PG_RETURN_FLOAT8(area);
-}
-
-//calculate the perimeter of polys (sum of length of all rings)
-PG_FUNCTION_INFO_V1(perimeter2d);
-Datum perimeter2d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       POLYGON3D                       *poly;
-       double                  area = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       area += polygon_perimeter2d(poly);
-               }
-       }
-       PG_RETURN_FLOAT8(area);
-}
-
-
-// cn_PnPoly(): crossing number test for a point in a polygon
-//      input:   P = a point,
-//               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
-//      returns: 0 = outside, 1 = inside
-//
-//     Our polygons have first and last point the same,
-//
-int PIP( POINT3D *P, POINT3D *V, int n )
-{
-    int    cn = 0;    // the crossing number counter
-               int i;
-
-       double vt;
-
-    // loop through all edges of the polygon
-
-       for (i=0; i< (n-1) ; i++)
-       {    // edge from V[i] to V[i+1]
-
-               if (((V[i].y <= P->y) && (V[i+1].y > P->y))    // an upward crossing
-                        || ((V[i].y > P->y) && (V[i+1].y <= P->y))) // a downward crossing
-               {
-
-                  vt = (double)(P->y - V[i].y) / (V[i+1].y - V[i].y);
-                  if (P->x < V[i].x + vt * (V[i+1].x - V[i].x))                        // P.x <intersect
-                               ++cn;   // a valid crossing of y=P.y right of P.x
-       }
-    }
-    return (cn&1);    // 0 if even (out), and 1 if odd (in)
-
-}
-
-
-
-
-
-//this one is easy - is the point inside a box?
-bool point_truely_inside(POINT3D       *point, BOX3D   *box)
-{
-       return (
-                       (point->x >= box->LLB.x) && (point->x <= box->URT.x)  &&
-                     (point->y >= box->LLB.y) && (point->y <= box->URT.y)
-                );
-}
-
-
-// see if a linestring is inside a box - check to see if each its line
-//     segments are inside the box
-// NOTE: all this is happening in 2d - third dimention is ignored
-//
-//use a modified CohenSutherland line clipping algoritm
-//
-//Step one - compute outcodes for Pi and Pi+1
-//
-//
-//                     |               |
-//             1001    |   1000        |  1010
-//                     |               |
-//      ----------+-----------+------------
-//                     | (inside)      |
-//             0001    |               |  0010
-//                     |   0000        |
-//      ----------+-----------+------------
-//                     |               |
-//             0101    |   0100        |  0110
-//                     |               |
-//
-// If Pi or Pi+1 have code 0000 then this line seg is inside the box  (trivial accept)
-//  if Pi && Pi+1 != 0 then seg is NOT in the box (trivial reject)
-//
-//     Otherwise the line seg might traverse through the box.
-//             => see if the seg intersects any of the walls of the box.
-//
-
-int    compute_outcode( POINT3D *p, BOX3D *box)
-{
-       int     Code=0;
-
-//printf("compute outcode:\n");
-//print_box(box);
-//printf("point = [%g,%g]\n",p->x,p->y);
-       if (p->y > box->URT.y )
-               Code = 8;
-       else
-       {
-         if (p->y <box->LLB.y )
-         {
-               Code = 4;
-         }
-       }
-       if (p->x > box->URT.x )
-       {
-         return (Code+2);
-       }
-       if (p->x <box->LLB.x )
-       {
-         return (Code+1);
-       }
-
-       return (Code);
-}
-
-
-bool lineseg_inside_box( POINT3D *P1, POINT3D *P2, BOX3D *box)
-{
-       int     outcode_p1, outcode_p2;
-       double  Ax,Ay, Bx,By, Cx,Cy, Dx,Dy;
-       double  r,s;
-
-       outcode_p1 = compute_outcode(P1, box);
-       if (outcode_p1 ==0)
-               return TRUE;
-
-       outcode_p2 = compute_outcode(P2, box);
-       if (outcode_p2 ==0)
-               return TRUE;
-       if ((outcode_p1 & outcode_p2) != 0)
-               return FALSE;
-
-
-       if ((outcode_p1 + outcode_p2) == 12)
-               return TRUE; //vertically slices box
-
-       if ((outcode_p1 + outcode_p2) == 3)
-               return TRUE; //horizontally slices box
-
-
-//printf("have to do boundry calcs\n");
-
-       // know that its a diagonal line
-
-       //this is the tough case - it may or maynot intersect the box
-       //see if it intersects the horizonal and vertical box lines
-
-       // from comp.graphics.algo's faq:
-       /*
-              (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
-       r =  ------------------------------------
-                 (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-
-               (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-       s =     -----------------------------------
-               (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-
-       */
-       // if  0<= r&s <=1 then intersection exists
-
-       Ax = P1->x; Ay = P1->y;
-       Bx = P2->x; By = P2->y;
-
-       //top hor part of box
-       Cx = box->LLB.x; Cy= box->URT.y;
-       Dx = box->URT.x; Dy= box->URT.y;
-
-               r= ((Ay-Cy)*(Dx-Cx)-(Ax-Cx)*(Dy-Cy) )/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-               s=  ((Ay-Cy)*(Bx-Ax)-(Ax-Cx)*(By-Ay))/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-       if  ( (r>=0) && (r<=1) && (s>=0) && (s<=1)    )
-               return TRUE;
-
-       //bottom hor part of box
-       Cx = box->LLB.x; Cy= box->LLB.y;
-       Dx = box->URT.x; Dy= box->LLB.y;
-
-               r= ((Ay-Cy)*(Dx-Cx)-(Ax-Cx)*(Dy-Cy) )/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-               s=  ((Ay-Cy)*(Bx-Ax)-(Ax-Cx)*(By-Ay))/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-       if  ( (r>=0) && (r<=1) && (s>=0) && (s<=1)    )
-               return TRUE;
-
-       //left ver part of box
-       Cx = box->LLB.x; Cy= box->LLB.y;
-       Dx = box->LLB.x; Dy= box->URT.y;
-
-               r= ((Ay-Cy)*(Dx-Cx)-(Ax-Cx)*(Dy-Cy) )/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-               s=  ((Ay-Cy)*(Bx-Ax)-(Ax-Cx)*(By-Ay))/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-       if  ( (r>=0) && (r<=1) && (s>=0) && (s<=1)    )
-               return TRUE;
-
-       //right ver part of box
-       Cx = box->URT.x; Cy= box->LLB.y;
-       Dx = box->URT.x; Dy= box->URT.y;
-
-               r= ((Ay-Cy)*(Dx-Cx)-(Ax-Cx)*(Dy-Cy) )/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-
-               s=  ((Ay-Cy)*(Bx-Ax)-(Ax-Cx)*(By-Ay))/
-                       ((Bx-Ax)*(Dy-Cy)-(By-Ay)*(Dx-Cx) ) ;
-       if  ( (r>=0) && (r<=1) && (s>=0) && (s<=1)    )
-               return TRUE;
-
-       //otherwise we did not intersect the box
-       return FALSE;
-
-}
-
-
-//give the work to an easier process
-bool   linestring_inside_box(POINT3D *pts, int npoints, BOX3D *box)
-{
-       POINT3D *frm,*to;
-       int             i;
-
-       if (npoints <2)
-               return FALSE;   //must have >1 point to make sense
-
-       frm = &pts[0];
-
-       for (i=1; i< npoints;i++)
-       {
-               to = &pts[i];
-
-               if (lineseg_inside_box( frm, to,  box))
-                       return TRUE;
-
-               frm = to;
-       }
-       return FALSE;
-}
-
-
-//this ones the most complex
-//     1. treat the outer ring as a line and see if its inside
-//             + if it is, then poly is inside box
-//     2. The polygon could be completely contained inside the box
-//             + line detector (step 1) would have found this
-//     3. The polygon could be completely surrounding the box
-//             + point-in-polygon of one of the box corners
-//             + COMPLEXITY: box could be totally inside a single hole
-//                     +test all holes like step 1.  Any that pass arent "bad" holes
-//                     +  each of the bad holes do a point-in-polygon if true =-> totally in hole
-
-bool polygon_truely_inside(POLYGON3D   *poly, BOX3D *box)
-{
-       bool            outer_ring_inside,outer_ring_surrounds;
-       POINT3D *pts1;
-       POINT3D test_point;
-       int32           ring;
-       int             point_offset;
-
-       pts1 = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-       pts1 = (POINT3D *) MAXALIGN(pts1);
-
-
-       //step 1 (and 2)
-       outer_ring_inside = linestring_inside_box(pts1, poly->npoints[0], box);
-
-       if (outer_ring_inside)
-               return TRUE;
-
-       test_point.x = box->LLB.x;
-       test_point.y = box->LLB.y;
-               //.z unimportant
-
-       outer_ring_surrounds = PIP(&test_point, pts1,poly->npoints[0] );
-
-       if (!(outer_ring_surrounds))
-               return FALSE;   // disjoing
-
-       //printf("polygon - have to check holes\n");
-
-       //step 3
-
-       point_offset = poly->npoints[0];
-       for (ring =1; ring< poly->nrings; ring ++)
-       {
-               if (!( linestring_inside_box(&pts1[point_offset], poly->npoints[ring], box) ))
-               {
-                       //doesnt intersect the box
-                       // so if one of the corners of the box is inside the hole, it totally
-                       //   surrounds the box
-
-                       if (PIP(&test_point, &pts1[point_offset],poly->npoints[ring] ) )
-                               return FALSE;
-               }
-               point_offset += poly->npoints[ring];
-       }
-
-       return TRUE;
-}
-
-
-
-
-
-//This is more complicated because all the points in the line can be outside the box,
-// but one of the edges can cross into the box.
-//  We send the work off to another function because its generically usefull for
-//   polygons too
-bool line_truely_inside( LINE3D *line, BOX3D   *box)
-{
-       return  linestring_inside_box(&line->points[0], line->npoints, box);
-}
-
-// is point inside polygon surface ?
-//bool point_within_polygon(POINT3D *point, POLYGON3D *poly)
-//{
-//     POINT3D *ring;
-//     int ringpoints;
-//     int ri; // ring index
-//
-//     // if point is outside the shell return false.
-//     ring = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-//     ringpoints = poly->npoints[0];
-//     if ( !PIP(point, ring, ringpoints) ) return FALSE;
-//
-//     // if point is inside any hole return false.
-//     //ring += ringpoints*sizeof(POINT3D);
-//     //for (ri=1; ri<poly->nrings; ri++)
-//     //{
-//     //      ringpoints = poly->npoints[ri];
-//     //      if ( PIP(point, ring, ringpoints) ) return FALSE;
-//     //      ring += ringpoints*sizeof(POINT3D);
-//     //}
-//
-//     // return true
-//     return TRUE;
-//}
-
-//is anything in geom1 really inside the the bvol (2d only) defined in geom2?
-// send each object to its proper handler
-PG_FUNCTION_INFO_V1(truly_inside);
-Datum truly_inside(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                      *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       BOX3D                           *the_bbox;
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       POLYGON3D                       *poly;
-       LINE3D                  *line;
-       POINT3D                 *point;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       the_bbox = &geom2->bvol;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       point = (POINT3D *) o1;
-                       if ( point_truely_inside(point, the_bbox))
-                               PG_RETURN_BOOL(TRUE);
-               }
-
-               if (type1 == LINETYPE)  //line
-               {
-                       line = (LINE3D *) o1;
-                       if ( line_truely_inside(line, the_bbox))
-                               PG_RETURN_BOOL(TRUE);
-               }
-
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-
-                       if ( polygon_truely_inside(poly, the_bbox))
-                               PG_RETURN_BOOL(TRUE);
-               }
-       }
-       PG_RETURN_BOOL(FALSE);
-}
-
-
-
-//number of points in an object
-PG_FUNCTION_INFO_V1(npoints);
-Datum npoints(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j,i;
-       POLYGON3D                       *poly;
-       LINE3D                  *line;
-       int32                           numb_points = 0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       numb_points ++;
-               }
-
-               if (type1 == LINETYPE)  //line
-               {
-                       line = (LINE3D *) o1;
-                       numb_points += line->npoints;
-               }
-
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       for (i=0; i<poly->nrings;i++)
-                       {
-                               numb_points += poly->npoints[i];
-                       }
-               }
-       }
-
-       PG_RETURN_INT32(numb_points);
-}
-
-//number of rings in an object
-PG_FUNCTION_INFO_V1(nrings);
-Datum nrings(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       POLYGON3D                       *poly;
-       int32                           numb_rings = 0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type1=  geom1->objType[j];
-
-               if (type1 == POLYGONTYPE)       //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       numb_rings += poly->nrings;
-               }
-       }
-
-       PG_RETURN_INT32(numb_rings);
-}
-
-
-
-void   translate_points(POINT3D *pt, int npoints,double x_off, double y_off, double z_off)
-{
-       int i;
-
-//printf("translating %i points by [%g,%g,%g]\n",npoints,x_off,y_off,z_off);
-       if (npoints <1)
-               return; //nothing to do
-
-       for (i=0;i<npoints;i++)
-       {
-//printf("before: [%g,%g,%g]\n", pt[i].x, pt[i].y,pt[i].z);
-
-               pt[i].x += x_off;
-               pt[i].y += y_off;
-               pt[i].z += z_off;
-
-//printf("after: [%g,%g,%g]\n", pt[i].x, pt[i].y,pt[i].z);
-       }
-}
-
-
-
-//translate geometry
-PG_FUNCTION_INFO_V1(translate);
-Datum translate(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                        *geom1;
-       double                  x_off =  PG_GETARG_FLOAT8(1);
-       double                  y_off =  PG_GETARG_FLOAT8(2);
-       double                  z_off =  PG_GETARG_FLOAT8(3);
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type,j,i;
-       POLYGON3D                       *poly;
-       POINT3D                 *point,*pts;
-       LINE3D                  *line;
-       int                             numb_points;
-
-
-
-
-       //make a copy of geom so we can return a new version
-
-       geom1 = (GEOMETRY *) palloc (geom->size);
-       memcpy(geom1, geom, geom->size);                        //Will handle SRID and grid
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;
-               type=  geom1->objType[j];
-
-               if (type == POINTTYPE)  //point
-               {
-                       point = (POINT3D *) o1;
-                       translate_points(point, 1,x_off,y_off,z_off);
-               }
-
-               if (type == LINETYPE)   //line
-               {
-                       line = (LINE3D *) o1;
-                       translate_points(&(line->points[0]), line->npoints,x_off,y_off,z_off);
-               }
-
-               if (type == POLYGONTYPE)        //POLYGON
-               {
-                       poly = (POLYGON3D *) o1;
-                       //find where the points are and where to put them
-                       numb_points =0;
-                       for (i=0; i<poly->nrings;i++)
-                       {
-                               numb_points += poly->npoints[i];
-                       }
-                       pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-                       pts = (POINT3D *) MAXALIGN(pts);
-                       translate_points(pts, numb_points,x_off,y_off,z_off);
-
-
-               }
-       }
-       //translate the bounding box as well
-       geom1->bvol.LLB.x += x_off;
-       geom1->bvol.LLB.y += y_off;
-       geom1->bvol.LLB.z += z_off;
-       geom1->bvol.URT.x += x_off;
-       geom1->bvol.URT.y += y_off;
-       geom1->bvol.URT.z += z_off;
-
-       PG_RETURN_POINTER(geom1);
-}
-
-
-
-
-// set the is3d flag so the system think the geometry is 2d or 3d
-
-PG_FUNCTION_INFO_V1(force_2d);
-Datum force_2d(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                        *result;
-
-       result = (GEOMETRY *) palloc(geom->size);
-       memcpy(result,geom, geom->size);
-
-       result->is3d = FALSE;
-       PG_RETURN_POINTER(result);
-}
-
-
-PG_FUNCTION_INFO_V1(force_3d);
-Datum force_3d(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                        *result;
-
-       result = (GEOMETRY *) palloc(geom->size);
-       memcpy(result,geom, geom->size);
-
-       result->is3d = TRUE;
-       PG_RETURN_POINTER(result);
-
-}
-
-
-//NULL safe bbox union
-// combine_bbox(BOX3D, geometry) => union BOX3D and geometry->bvol
-// For finding the extent of a set of rows using the extent() aggregate
-
-PG_FUNCTION_INFO_V1(combine_bbox);
-Datum combine_bbox(PG_FUNCTION_ARGS)
-{
-                Pointer                 box3d_ptr = PG_GETARG_POINTER(0);
-                Pointer                 geom_ptr =  PG_GETARG_POINTER(1);
-                BOX3D                  *a,*b;
-                GEOMETRY                       *geom;
-               BOX3D                           *box;
-
-       if  ( (box3d_ptr == NULL) && (geom_ptr == NULL) )
-       {
-               PG_RETURN_NULL(); // combine_bbox(null,null) => null
-       }
-
-       if (box3d_ptr == NULL)
-       {
-               geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               box = (BOX3D *) palloc(sizeof(BOX3D));
-               memcpy(box, &(geom->bvol), sizeof(BOX3D) );
-
-               PG_RETURN_POINTER(box);  // combine_bbox(null, geometry) => geometry->bvol
-       }
-
-       if (geom_ptr == NULL)
-       {
-               box = (BOX3D *) palloc(sizeof(BOX3D));
-               memcpy(box, (char *) PG_GETARG_DATUM(0) , sizeof(BOX3D) );
-
-
-               PG_RETURN_POINTER( box ); // combine_bbox(BOX3D, null) => BOX3D
-       }
-
-       //combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol)
-
-       box = (BOX3D *) palloc(sizeof(BOX3D));
-
-       a = (BOX3D *) PG_GETARG_DATUM(0) ;
-       b= &(( (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1)) )->bvol);
-
-       box->LLB.x = b->LLB.x;
-       box->LLB.y = b->LLB.y;
-       box->LLB.z = b->LLB.z;
-
-       box->URT.x = b->URT.x;
-       box->URT.y = b->URT.y;
-       box->URT.z = b->URT.z;
-
-       if (a->LLB.x < b->LLB.x)
-               box->LLB.x = a->LLB.x;
-       if (a->LLB.y < b->LLB.y)
-               box->LLB.y = a->LLB.y;
-       if (a->LLB.z < b->LLB.z)
-               box->LLB.z = a->LLB.z;
-
-       if (a->URT.x > b->URT.x)
-               box->URT.x = a->URT.x;
-       if (a->URT.y > b->URT.y)
-               box->URT.y = a->URT.y;
-       if (a->URT.z > b->URT.z)
-               box->URT.z = a->URT.z;
-
-       PG_RETURN_POINTER(  box  );
-}
-
-
-//returns 0 for points, 1 for lines, 2 for polygons.
-//returns max dimension for a collection.
-PG_FUNCTION_INFO_V1(dimension);
-Datum dimension(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               int t;
-               int result,dim,type;
-
-
-       if ((geom->type == COLLECTIONTYPE) && (geom->nobjs ==0))
-               PG_RETURN_INT32(-1);
-
-       if (geom->type == POINTTYPE)
-               PG_RETURN_INT32(0);
-
-       if (geom->type == LINETYPE)
-               PG_RETURN_INT32(1);
-
-       if (geom->type == POLYGONTYPE)
-               PG_RETURN_INT32(2);
-
-
-       if (geom->type == MULTIPOINTTYPE)
-               PG_RETURN_INT32(0);
-
-       if (geom->type == MULTILINETYPE)
-               PG_RETURN_INT32(1);
-
-       if (geom->type == MULTIPOLYGONTYPE)
-               PG_RETURN_INT32(2);
-
-       result = -1;
-       dim =0;
-       //its a collection -look for the largest one
-       for (t=0;t<geom->nobjs;t++)
-       {
-               type=  geom->objType[t];
-
-               if (type == POINTTYPE)
-                               dim=0;
-
-               if (type == LINETYPE)
-                       dim=1;
-
-               if (type == POLYGONTYPE)
-                       dim=2;
-
-               if (dim>result)
-                       result = dim;
-
-       }
-       PG_RETURN_INT32(result);
-}
-
-//returns a string representation of this geometry's type
-PG_FUNCTION_INFO_V1(geometrytype);
-Datum geometrytype(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               char                            *text_ob = palloc(20+4);
-               char                            *result = text_ob+4;
-               int32                           size;
-
-
-       memset(result,0,20);
-
-       if (geom->type == POINTTYPE)
-               strcpy(result,"POINT");
-       if (geom->type == MULTIPOINTTYPE)
-               strcpy(result,"MULTIPOINT");
-
-       if (geom->type == LINETYPE)
-               strcpy(result,"LINESTRING");
-       if (geom->type == MULTILINETYPE)
-               strcpy(result,"MULTILINESTRING");
-
-       if (geom->type == POLYGONTYPE)
-               strcpy(result,"POLYGON");
-       if (geom->type == MULTIPOLYGONTYPE)
-               strcpy(result,"MULTIPOLYGON");
-
-       if (geom->type == COLLECTIONTYPE)
-               strcpy(result,"GEOMETRYCOLLECTION");
-
-       if (strlen(result) == 0)
-               strcpy(result,"UNKNOWN");
-
-       size = strlen(result) +4 ;
-
-       memcpy(text_ob, &size,4); // size of string
-
-
-       PG_RETURN_POINTER(text_ob);
-
-}
-
-
-//makes a polygon of a features bvol - 1st point = LL 3rd=UR
-// 2d only
-//
-// create new geometry of type polygon, 1 ring, 5 points
-
-PG_FUNCTION_INFO_V1(envelope);
-Datum envelope(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                        *result;
-       POLYGON3D                       *poly;
-       POINT3D                 pts[5]; //5 points around box
-       int                             pts_per_ring[1];
-       int                             poly_size;
-
-       //use LLB's z value (we're going to set is3d to false)
-
-               //0,1,2,3,4 --> CCW order,  4,3,2,1,0 --> CW order
-       set_point( &pts[4], geom->bvol.LLB.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
-       set_point( &pts[3], geom->bvol.URT.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
-       set_point( &pts[2], geom->bvol.URT.x , geom->bvol.URT.y , geom->bvol.LLB.z );
-       set_point( &pts[1], geom->bvol.LLB.x , geom->bvol.URT.y , geom->bvol.LLB.z );
-       set_point( &pts[0], geom->bvol.LLB.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
-
-       pts_per_ring[0] = 5; //ring has 5 points
-
-               //make a polygon
-       poly = make_polygon(1, pts_per_ring, pts, 5, &poly_size);
-
-       result = make_oneobj_geometry(poly_size, (char *)poly, POLYGONTYPE, FALSE,geom->SRID, geom->scale, geom->offsetX, geom->offsetY);
-
-       PG_RETURN_POINTER(result);
-
-}
-
-//X(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its X value.
-//Return NULL if there is no POINT(..) in GEOMETRY
-PG_FUNCTION_INFO_V1(x_point);
-Datum x_point(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       PG_RETURN_FLOAT8( ((POINT3D *)o)->x) ;
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-//Y(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Y value.
-//Return NULL if there is no POINT(..) in GEOMETRY
-PG_FUNCTION_INFO_V1(y_point);
-Datum y_point(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       PG_RETURN_FLOAT8( ((POINT3D *)o)->y) ;
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-//Z(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Z value.
-//Return NULL if there is no POINT(..) in GEOMETRY
-PG_FUNCTION_INFO_V1(z_point);
-Datum z_point(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       PG_RETURN_FLOAT8( ((POINT3D *)o)->z) ;
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-//numpoints(GEOMETRY) -- find the first linestring in GEOMETRY, return
-//the number of points in it.  Return NULL if there is no LINESTRING(..)
-//in GEOMETRY
-PG_FUNCTION_INFO_V1(numpoints_linestring);
-Datum numpoints_linestring(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == LINETYPE)  //linestring
-               {
-                       PG_RETURN_INT32( ((LINE3D *)o)->npoints) ;
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-//pointn(GEOMETRY,INTEGER) -- find the first linestring in GEOMETRY,
-//return the point at index INTEGER (0 is 1st point).  Return NULL if
-//there is no LINESTRING(..) in GEOMETRY or INTEGER is out of bounds.
-// keeps is3d flag
-
-PG_FUNCTION_INFO_V1(pointn_linestring);
-Datum pointn_linestring(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           wanted_index =PG_GETARG_INT32(1);
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-       LINE3D                  *line;
-
-
-       wanted_index -= NfunctionFirstPoint;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == LINETYPE)  //linestring
-               {
-                       line = (LINE3D *)o;
-                       if ( (wanted_index<0) || (wanted_index> (line->npoints-1) ) )
-                               PG_RETURN_NULL(); //index out of range
-                       //get the point, make a new geometry
-                       PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                                        (char *)&line->points[wanted_index],
-                                                          POINTTYPE,  geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-// exteriorRing(GEOMETRY) -- find the first polygon in GEOMETRY, return
-//its exterior ring (as a linestring).  Return NULL if there is no
-//POLYGON(..) in GEOMETRY.
-
-PG_FUNCTION_INFO_V1(exteriorring_polygon);
-Datum exteriorring_polygon(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-       LINE3D                  *line;
-       POLYGON3D                       *poly;
-       POINT3D                 *pts;
-       int                             size_line;
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POLYGONTYPE)       //polygon object
-               {
-                       poly = (POLYGON3D *)o;
-                       pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-                       pts = (POINT3D *) MAXALIGN(pts);
-
-                       line = make_line(poly->npoints[0], pts, &size_line);
-
-                       //get the ring, make a new geometry
-                       PG_RETURN_POINTER(
-                               make_oneobj_geometry(size_line,
-                                                        (char *) line,
-                                                          LINETYPE,  geom->is3d,geom->SRID,  geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-
-       }
-       PG_RETURN_NULL();
-}
-
-//NumInteriorRings(GEOMETRY) -- find the first polygon in GEOMETRY,
-//return the number of interior rings.  Return NULL if there is no
-//POLYGON(..) in GEOMETRY.
-
-PG_FUNCTION_INFO_V1(numinteriorrings_polygon);
-Datum numinteriorrings_polygon(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-       POLYGON3D                       *poly;
-
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POLYGONTYPE)       //polygon object
-               {
-                       poly = (POLYGON3D *)o;
-                       PG_RETURN_INT32( poly->nrings -1 ) ;
-               }
-       }
-       PG_RETURN_NULL();
-}
-
-//        InteriorRingN(GEOMETRY,INTEGER) --  find the first polygon in GEOMETRY,
-//return the interior ring at index INTEGER (as a linestring).  Return
-//NULL if there is no POLYGON(..) in GEOMETRY or INTEGER is out of bounds.
-// 1st ring = exerior ring
-
-PG_FUNCTION_INFO_V1(interiorringn_polygon);
-Datum interiorringn_polygon(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           wanted_index =PG_GETARG_INT32(1);
-       char                            *o;
-       int                             type1,j,t,point_offset;
-       int32                           *offsets1;
-       POLYGON3D                       *poly;
-       LINE3D                  *line;
-       POINT3D                 *pts;
-       int                             size_line;
-
-
-       wanted_index -= NfunctionFirstPoint;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POLYGONTYPE)       //polygon object
-               {
-                       poly = (POLYGON3D *)o;
-
-                       if ( (wanted_index<0) || (wanted_index> (poly->nrings-2) ) )
-                               PG_RETURN_NULL(); //index out of range
-
-
-                       pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-                       pts = (POINT3D *) MAXALIGN(pts);
-
-                       //find the 1st point in wanted ring
-                       point_offset=0;
-                       for (t=0; t< (wanted_index+1); t++)
-                       {
-                               point_offset += poly->npoints[t];
-                       }
-
-                       line = make_line(poly->npoints[wanted_index+1], &pts[point_offset], &size_line);
-
-                       //get the ring, make a new geometry
-                       PG_RETURN_POINTER(
-                               make_oneobj_geometry(size_line,
-                                                        (char *) line,
-                                                          LINETYPE,  geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-       }
-       PG_RETURN_NULL();
-}
-
-
-//        numgeometries(GEOMETRY) -- if GEOMETRY is a GEOMETRYCOLLECTION, return
-//the number of geometries in it, otherwise return NULL.
-//             if GEOMETRY is a MULTI* type, return the number of sub-types in it.
-
-PG_FUNCTION_INFO_V1(numgeometries_collection);
-Datum numgeometries_collection(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-               if  ( (geom->type == COLLECTIONTYPE) ||
-                     (geom->type == MULTIPOINTTYPE) ||
-                       (geom->type == MULTILINETYPE) ||
-                       (geom->type == MULTIPOLYGONTYPE)
-                   )
-                       PG_RETURN_INT32( geom->nobjs ) ;
-               else
-                       PG_RETURN_NULL();
-}
-
-
-//geometryN(GEOMETRY, INTEGER) -- if GEOMETRY is a GEOMETRYCOLLECTION,
-//return the sub-geometry at index INTEGER (0=first geometry), otherwise
-//return NULL.   NOTE: MULTIPOINT, MULTILINESTRING,MULTIPOLYGON are
-//converted to sets of POINT,LINESTRING, and POLYGON so the index may
-//change.
-// if GEOMETRY is a MULTI* type, return the Nth sub-geometry
-
-
-PG_FUNCTION_INFO_V1(geometryn_collection);
-Datum geometryn_collection(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               int32                           wanted_index =PG_GETARG_INT32(1);
-               int                             type;
-               int32                           *offsets1;
-               char                            *o;
-
-       wanted_index -= NfunctionFirstPoint;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-               if  (!(( (geom->type == COLLECTIONTYPE) ||
-                     (geom->type == MULTIPOINTTYPE) ||
-                       (geom->type == MULTILINETYPE) ||
-                       (geom->type == MULTIPOLYGONTYPE)
-                   )))
-                               PG_RETURN_NULL();
-
-
-               if ( (wanted_index <0) || (wanted_index > (geom->nobjs-1) ) )
-                       PG_RETURN_NULL();       //bad index
-
-               type = geom->objType[wanted_index];
-               o = (char *) geom +offsets1[wanted_index] ;
-
-               if (type == POINTTYPE)
-               {
-                               PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                                        o,
-                                                          POINTTYPE,  geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-               if (type == LINETYPE)
-               {
-                               PG_RETURN_POINTER(
-                               make_oneobj_geometry(   size_subobject (o, LINETYPE),
-                                                        o,
-                                                          LINETYPE,  geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-               if (type == POLYGONTYPE)
-               {
-                               PG_RETURN_POINTER(
-                               make_oneobj_geometry(   size_subobject (o, POLYGONTYPE),
-                                                        o,
-                                                          POLYGONTYPE,  geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
-                                               );
-               }
-
-               PG_RETURN_NULL();
-}
-
-
-//force the geometry to be a geometrycollection type
-
-PG_FUNCTION_INFO_V1(force_collection);
-Datum force_collection(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                        *result;
-
-       result = (GEOMETRY *) palloc(geom->size);
-       memcpy(result,geom, geom->size);
-
-       result->type = COLLECTIONTYPE;
-
-       PG_RETURN_POINTER(result);
-}
-
-
-
-// point_inside_circle(geometry, Px, Py, d)
-// returns true if there is a point in geometry whose distance to (Px,Py) is < d
-
-PG_FUNCTION_INFO_V1(point_inside_circle);
-Datum point_inside_circle(PG_FUNCTION_ARGS)
-{
-
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                            *o;
-       int                             type1,j;
-       int32                           *offsets1;
-       POINT3D                 *pt;
-       double                  Px  = PG_GETARG_FLOAT8(1);
-       double                  Py =  PG_GETARG_FLOAT8(2);
-       double                  d =   PG_GETARG_FLOAT8(3);
-       double                  dd = d*d; //d squared
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom
-       {
-               o = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-
-               if (type1 == POINTTYPE) //point
-               {
-                       //see if its within d of Px,Py
-                       pt = (POINT3D *) o;
-                       if  ( (   (pt->x - Px)*(pt->x - Px) + (pt->y - Py)*(pt->y - Py) ) < dd)
-                       {
-                               PG_RETURN_BOOL(TRUE);
-                       }
-               }
-
-       }
-       PG_RETURN_BOOL(FALSE);
-}
-
-
-//distance from p to line A->B
-double distance_pt_seg(POINT3D *p, POINT3D *A, POINT3D *B)
-{
-       double  r,s;
-
-
-       //if start==end, then use pt distance
-       if (  ( A->x == B->x) && (A->y == B->y) )
-               return distance_pt_pt(p,A);
-
-       //otherwise, we use comp.graphics.algorithms Frequently Asked Questions method
-
-       /*(1)                 AC dot AB
-                   r = ---------
-                         ||AB||^2
-               r has the following meaning:
-               r=0 P = A
-               r=1 P = B
-               r<0 P is on the backward extension of AB
-               r>1 P is on the forward extension of AB
-               0<r<1 P is interior to AB
-       */
-
-       r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-       if (r<0)
-               return (distance_pt_pt(p,A));
-       if (r>1)
-               return(distance_pt_pt(p,B));
-
-
-       /*(2)
-                    (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-               s = -----------------------------
-                               L^2
-
-               Then the distance from C to P = |s|*L.
-
-       */
-
-       s = ((A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) )/ ((B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
-       return abs(s) * sqrt(((B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) ));
-}
-
-
-
-// find the distance from AB to CD
-double distance_seg_seg(POINT3D *A, POINT3D *B, POINT3D *C, POINT3D *D)
-{
-
-       double  s_top, s_bot,s;
-       double  r_top, r_bot,r;
-
-
-//printf("seg_seg [%g,%g]->[%g,%g]  by [%g,%g]->[%g,%g]  \n",A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
-               //A and B are the same point
-
-       if (  ( A->x == B->x) && (A->y == B->y) )
-               return distance_pt_seg(A,C,D);
-
-               //U and V are the same point
-
-       if (  ( C->x == D->x) && (C->y == D->y) )
-               return distance_pt_seg(D,A,B);
-
-       // AB and CD are line segments
-       /* from comp.graphics.algo
-
-       Solving the above for r and s yields
-                               (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
-                  r = ----------------------------- (eqn 1)
-                               (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-
-                       (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
-               s = ----------------------------- (eqn 2)
-                       (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
-       Let P be the position vector of the intersection point, then
-               P=A+r(B-A) or
-               Px=Ax+r(Bx-Ax)
-               Py=Ay+r(By-Ay)
-       By examining the values of r & s, you can also determine some other limiting conditions:
-               If 0<=r<=1 & 0<=s<=1, intersection exists
-               r<0 or r>1 or s<0 or s>1 line segments do not intersect
-               If the denominator in eqn 1 is zero, AB & CD are parallel
-               If the numerator in eqn 1 is also zero, AB & CD are collinear.
-
-       */
-       r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
-       r_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x) ;
-
-       s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y);
-       s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x);
-
-       if  ( (r_bot==0) || (s_bot == 0) )
-       {
-               return (
-                       min(distance_pt_seg(A,C,D),
-                               min(distance_pt_seg(B,C,D),
-                                       min(distance_pt_seg(C,A,B),
-                                               distance_pt_seg(D,A,B)    ) ) )
-                        );
-       }
-       s = s_top/s_bot;
-       r=  r_top/r_bot;
-
-       if ((r<0) || (r>1) || (s<0) || (s>1) )
-       {
-               //no intersection
-               return (
-                       min(distance_pt_seg(A,C,D),
-                               min(distance_pt_seg(B,C,D),
-                                       min(distance_pt_seg(C,A,B),
-                                               distance_pt_seg(D,A,B)    ) ) )
-                        );
-
-       }
-       else
-               return -0; //intersection exists
-
-}
-
-
-
-//trivial
-double distance_pt_pt(POINT3D *p1, POINT3D *p2)
-{
-       //print_point_debug(p1);
-       //print_point_debug(p2);
-       return ( sqrt(  (p2->x - p1->x) * (p2->x - p1->x)  + (p2->y - p1->y) * (p2->y - p1->y)  ) );
-}
-
-
-//search all the segments of line to see which one is closest to p1
-double distance_pt_line(POINT3D *p1, LINE3D *l2)
-{
-       double  result = 99999999999.9,dist_this;
-       bool            result_okay = FALSE; //result is a valid min
-       int             t;
-       POINT3D *start,*end;
-
-       start = &(l2->points[0]);
-
-       for (t =1;t<l2->npoints;t++)
-       {
-               end = &(l2->points[t]);
-
-               dist_this = distance_pt_seg(p1, start,end);
-               if (result_okay)
-                       result= min(result,dist_this);
-               else
-               {
-                       result_okay = TRUE;
-                       result = dist_this;
-               }
-
-               start =end;
-       }
-
-       return result;
-}
-
-
-
-// test each segment of l1 against each segment of l2.  Return min
-double distance_line_line(LINE3D *l1, LINE3D *l2)
-{
-
-       double  result = 99999999999.9,dist_this;
-       bool            result_okay = FALSE; //result is a valid min
-       int             t,u;
-       POINT3D *start,*end;
-       POINT3D *start2,*end2;
-
-
-       start = &(l1->points[0]);
-
-       for (t =1;t<l1->npoints;t++)            //for each segment in L1
-       {
-               end = &(l1->points[t]);
-
-               start2 = &(l2->points[0]);
-
-               for (u=1; u< l2->npoints; u++)  //for each segment in L2
-               {
-                       end2 = &(l2->points[u]);
-
-                               dist_this = distance_seg_seg(start,end,start2,end2);
-//printf("line_line; seg %i * seg %i, dist = %g\n",t,u,dist_this);
-
-                               if (result_okay)
-                                       result= min(result,dist_this);
-                               else
-                               {
-                                       result_okay = TRUE;
-                                       result = dist_this;
-                               }
-                               if (result <=0)
-                                       return 0;       //intersection
-
-                       start2 = end2;
-               }
-               start = end;
-       }
-
-       return result;
-}
-
-
-// 1. see if pt in outer boundary.  if no, then treat the outer ring like a line
-// 2. if in the boundary, test to see if its in a hole.  if so, then return dist to hole
-double distance_pt_poly(POINT3D *p1, POLYGON3D *poly2)
-{
-       POINT3D *pts; //pts array for polygon
-       double  result;
-       LINE3D  *line;
-       int             junk,t;
-       int             offset;
-
-
-                       pts = (POINT3D *) ( (char *)&(poly2->npoints[poly2->nrings] )  );
-                       pts = (POINT3D *) MAXALIGN(pts);
-
-
-       if (PIP( p1, pts, poly2->npoints[0] ) )
-       {
-               //inside the outer ring.  scan though each of the inner rings looking to
-               // see if its inside.  If not, distance =0.  Otherwise, distance =
-               // pt to ring distance
-
-               offset = poly2->npoints[0];     //where ring t starts;
-               for (t=1; t<poly2->nrings;t++)  //foreach inner ring
-               {
-                       if (    PIP( p1, &pts[offset], poly2->npoints[t] ) )
-                       {
-                                       //inside a hole.  Distance = pt -> ring
-
-                                       line = make_line (poly2->npoints[t] , &pts[offset] , &junk);
-                                       result = distance_pt_line(p1, line);
-                                       pfree(line);
-                                       return result;
-                       }
-                       offset += poly2->npoints[t];
-               }
-
-               return 0; //its inside the polygon
-       }
-       else
-       {
-               //outside the outer ring.  Distance = pt -> ring
-
-               line = make_line (poly2->npoints[0] , pts, &junk);
-               result = distance_pt_line(p1, line);
-               pfree(line);
-               return result;
-       }
-
-
-}
-
-
-// brute force.  Test l1 against each ring.  If there's an intersection then return 0 (crosses boundary)
-// otherwise, test to see if a point inside outer rings of polygon, but not in inner rings.
-// if so, return 0  (line inside polygon)
-// otherwise return min distance to a ring (could be outside polygon or inside a hole)
-double distance_line_poly(LINE3D *l1, POLYGON3D *poly2)
-{
-       double  min_dist=9999999.0,this_dist;
-       int             t,junk;
-       LINE3D  *line;
-       POINT3D *pts; //pts array for polygon
-       int             offset;
-
-
-
-                       pts = (POINT3D *) ( (char *)&(poly2->npoints[poly2->nrings] )  );
-                       pts = (POINT3D *) MAXALIGN(pts);
-
-       offset =0;
-       for (t=0;t<poly2->nrings; t++)
-       {
-               line = make_line (poly2->npoints[t] , &pts[offset] , &junk);
-                       this_dist = distance_line_line(l1, line);
-               pfree(line);
-
-//printf("line_poly; ring %i dist = %g\n",t,this_dist);
-               if (t==0)
-                       min_dist = this_dist;
-               else
-                       min_dist = min(min_dist,this_dist);
-
-               if (min_dist <=0)
-                       return 0;               //intersection
-
-               offset += poly2->npoints[t];
-       }
-
-       //no intersection, have to check if a point is inside the outer ring
-
-       if (PIP( &l1->points[0], pts, poly2->npoints[0] ) )
-       {
-               //its in the polygon.  Have to check if its inside a hole
-
-//printf("line_poly; inside outer ring\n");
-               offset =poly2->npoints[0] ;
-               for (t=1; t<poly2->nrings;t++)          //foreach inner ring
-               {
-                       if (    PIP( &l1->points[0],  &pts[offset], poly2->npoints[t] ) )
-                       {
-                               //its inside a hole, then the actual distance is the min ring distance
-//printf("line_poly; inside inner ring %i\n",t);
-                               return min_dist;
-                       }
-                       offset += poly2->npoints[t];
-               }
-               // not in hole, there for inside the polygon
-               return 0;
-       }
-       else
-       {
-               //not in the outside ring, so min distance to a ring is the actual min distance
-               return min_dist;
-       }
-
-}
-
-// true if point is in poly (and not in its holes)
-bool point_in_poly(POINT3D *p, POLYGON3D *poly)
-{
-       int     t;
-       POINT3D *pts1;
-       int             offset;
-
-               pts1 = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-               pts1 = (POINT3D *) MAXALIGN(pts1);
-
-       if (PIP(p, pts1, poly->npoints[0]))
-       {
-               offset = poly->npoints[0];
-               for (t=1;t<poly->nrings;t++)
-               {
-                       if (PIP(p, &pts1[offset], poly->npoints[t]) )
-                       {
-                               return FALSE; //inside a hole
-                       }
-                       offset += poly->npoints[t];
-               }
-               return TRUE; //in outer ring, not in holes
-       }
-       else
-               return FALSE; //not in outer ring
-}
-
-// brute force.
-// test to see if any rings intersect.  if yes, dist =0
-// test to see if one inside the other and if they are inside holes.
-// find min distance ring-to-ring
-double distance_poly_poly(POLYGON3D *poly1, POLYGON3D *poly2)
-{
-       //foreach ring in Poly1
-       // foreach ring in Poly2
-       //   if intersect, return 0
-
-       // if poly1 inside poly2 return 0
-       // if poly2 inside poly1 return 0
-
-       // otherwise return closest approach of rings
-
-       int     t,junk;
-       POINT3D *pts1,*pts2;
-       int32           offset1;
-       double  min_dist= 99999999999.9, this_dist;
-       LINE3D  *line;
-
-
-               pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] )  );
-               pts1 = (POINT3D *) MAXALIGN(pts1);
-               pts2 = (POINT3D *) ( (char *)&(poly2->npoints[poly2->nrings] )  );
-               pts2 = (POINT3D *) MAXALIGN(pts2);
-
-
-                       //do this first as its a quick test
-
-               //test if poly1 inside poly2
-       if (point_in_poly(pts1, poly2) )
-               return 0;
-
-               //test if poly2 inside poly1
-       if (point_in_poly(pts2, poly1) )
-               return 0;
-
-
-       offset1 =0;
-       for (t=0; t<poly1->nrings; t++) //for each ring in poly1
-       {
-               line = make_line (poly1->npoints[t] , &pts1[offset1] , &junk);
-                       this_dist = distance_line_poly(line, poly2);
-               pfree(line);
-//printf("poly_poly; ring %i dist = %g\n",t,this_dist);
-               if (t==0)
-                       min_dist = this_dist;
-               else
-                       min_dist = min(min_dist,this_dist);
-
-               if (min_dist <=0)
-                       return 0;               //intersection
-
-
-               offset1 += poly1->npoints[t];
-       }
-
-       //rings do not intersect
-
-       return min_dist;
-}
-
-//minimum distance between objects in geom1 and geom2.  returns null if it doesnt exist (future null-safe version).
-PG_FUNCTION_INFO_V1(distance);
-Datum distance(PG_FUNCTION_ARGS)
-{
-
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                      *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       int     g1_i, g2_i;
-       double          dist,this_dist = 0;
-       bool                    dist_set = FALSE; //true once dist makes sense.
-       int32                   *offsets1,*offsets2;
-       int                     type1,type2;
-       char                    *o1,*o2;
-
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       dist = 99999999999999999999.9; //very far
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-       offsets2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+ sizeof(int32) * geom2->nobjs ) ;
-
-
-       for (g1_i=0; g1_i < geom1->nobjs; g1_i++)
-       {
-               o1 = (char *) geom1 +offsets1[g1_i] ;
-               type1=  geom1->objType[g1_i];
-               for (g2_i=0; g2_i < geom2->nobjs; g2_i++)
-               {
-                       o2 = (char *) geom2 +offsets2[g2_i] ;
-                       type2=  geom2->objType[g2_i];
-
-                       if  ( (type1 == POINTTYPE) && (type2 == POINTTYPE) )
-                       {
-                               this_dist = distance_pt_pt( (POINT3D *)o1, (POINT3D *)o2 );
-                       }
-                       if  ( (type1 == POINTTYPE) && (type2 == LINETYPE) )
-                       {
-                               this_dist = distance_pt_line( (POINT3D *)o1, (LINE3D *)o2 );
-                       }
-                       if  ( (type1 == POINTTYPE) && (type2 == POLYGONTYPE) )
-                       {
-                               this_dist = distance_pt_poly( (POINT3D *)o1, (POLYGON3D *)o2 );
-                       }
-                       if  ( (type1 == LINETYPE) && (type2 == LINETYPE) )
-                       {
-                               this_dist = distance_line_line( (LINE3D *)o1, (LINE3D *)o2 );
-                       }
-                       if  ( (type1 == LINETYPE) && (type2 == POLYGONTYPE) )
-                       {
-                               this_dist = distance_line_poly( (LINE3D *)o1, (POLYGON3D *)o2 );
-                       }
-                       if  ( (type1 == POLYGONTYPE) && (type2 == POLYGONTYPE) )
-                       {
-                               this_dist = distance_poly_poly( (POLYGON3D *)o1, (POLYGON3D *)o2 );
-                       }
-                               //trival versions based on above dist(a,b) = dist(b,a)
-
-                       if  ( (type1 == LINETYPE) && (type2 == POINTTYPE) )
-                       {
-                               this_dist = distance_pt_line( (POINT3D *)o2, (LINE3D *)o1 );
-                       }
-                       if  ( (type1 == POLYGONTYPE) && (type2 == POINTTYPE) )
-                       {
-                               this_dist = distance_pt_poly( (POINT3D *)o2, (POLYGON3D *)o1 );
-                       }
-                       if  ( (type1 == POLYGONTYPE) && (type2 == LINETYPE) )
-                       {
-                               this_dist = distance_line_poly( (LINE3D *)o2, (POLYGON3D *)o1 );
-                       }
-
-                       if (dist_set)
-                       {
-                               dist = min(dist,this_dist);
-                       }
-                       else
-                       {
-                               dist = this_dist;   //first one through
-                               dist_set = TRUE;
-                       }
-
-                       if (dist <= 0.0)
-                               PG_RETURN_FLOAT8( (double) 0.0); // no need to look for things closer
-               }
-       }
-       if (dist <0)
-               dist = 0; //computational error, may get -0.00000000001
-       PG_RETURN_FLOAT8(dist);
-}
-
-
-//expand_bbox(bbox3d, d)
-// returns a new bbox which is exanded d unit in all directions
-PG_FUNCTION_INFO_V1(expand_bbox);
-Datum expand_bbox(PG_FUNCTION_ARGS)
-{
-       BOX3D  *bbox   = (BOX3D *) PG_GETARG_POINTER(0);
-       double  d          = PG_GETARG_FLOAT8(1);
-       BOX3D    *result = (BOX3D *) palloc(sizeof(BOX3D));
-
-
-       result->LLB.x = bbox->LLB.x - d;
-       result->LLB.y = bbox->LLB.y - d;
-       result->LLB.z = bbox->LLB.z - d;
-
-
-       result->URT.x = bbox->URT.x + d;
-       result->URT.y = bbox->URT.y + d;
-       result->URT.z = bbox->URT.z + d;
-
-
-       PG_RETURN_POINTER(result);
-}
-
-// makes a polygon of the expanded features bvol - 1st point = LL 3rd=UR
-// 2d only
-// create new geometry of type polygon, 1 ring, 5 points
-PG_FUNCTION_INFO_V1(expand_geometry);
-Datum expand_geometry(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       double d = PG_GETARG_FLOAT8(1);
-       GEOMETRY *result;
-       POLYGON3D *poly;
-       POINT3D pts[5]; //5 points around box
-       int pts_per_ring[1];
-       int poly_size;
-
-       //use LLB's z value (we're going to set is3d to false)
-
-       //0,1,2,3,4 --> CCW order,  4,3,2,1,0 --> CW order
-       set_point( &pts[4], geom->bvol.LLB.x - d, geom->bvol.LLB.y - d,
-               geom->bvol.LLB.z - d );
-       set_point( &pts[3], geom->bvol.URT.x + d, geom->bvol.LLB.y - d,
-               geom->bvol.LLB.z - d );
-       set_point( &pts[2], geom->bvol.URT.x + d, geom->bvol.URT.y + d,
-               geom->bvol.LLB.z - d);
-       set_point( &pts[1], geom->bvol.LLB.x - d, geom->bvol.URT.y + d,
-               geom->bvol.LLB.z - d);
-       memcpy(&pts[0], &pts[4], sizeof(POINT3D));
-
-       pts_per_ring[0] = 5; //ring has 5 points
-
-       //make a polygon
-       poly = make_polygon(1, pts_per_ring, pts, 5, &poly_size);
-
-       result = make_oneobj_geometry(poly_size, (char *)poly, POLYGONTYPE, FALSE,geom->SRID, geom->scale, geom->offsetX, geom->offsetY);
-
-       PG_RETURN_POINTER(result);
-
-}
-
-//startpoint(geometry) :- if geometry is a linestring, return the first
-//point.  Otherwise, return NULL.
-
-PG_FUNCTION_INFO_V1(startpoint);
-Datum startpoint(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               POINT3D                 *pt;
-               LINE3D                  *line;
-               int32                           *offsets1;
-
-       if ( (geom1->type != LINETYPE) && (geom1->type != MULTILINETYPE) )
-               PG_RETURN_NULL();
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-
-       line = (LINE3D *) ( (char *) geom1 +offsets1[0]);
-
-       pt = &line->points[0];
-
-       PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                                        (char *) pt,
-                                                          POINTTYPE,  geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
-                               );
-}
-
-//endpoint(geometry) :- if geometry is a linestring, return the last
-//point.  Otherwise, return NULL.
-
-PG_FUNCTION_INFO_V1(endpoint);
-Datum endpoint(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               POINT3D                 *pt;
-               LINE3D                  *line;
-               int32                           *offsets1;
-
-
-
-       if ( (geom1->type != LINETYPE) && (geom1->type != MULTILINETYPE) )
-               PG_RETURN_NULL();
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-
-       line = (LINE3D *) ( (char *) geom1 +offsets1[0]);
-
-
-       pt = &line->points[line->npoints-1];
-
-       PG_RETURN_POINTER(
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                                        (char *) pt,
-                                                          POINTTYPE,  geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
-                               );
-}
-
-
-
-//isclosed(geometry) :- if geometry is a linestring then returns
-//startpoint == endpoint.  If its not a linestring then return NULL.  If
-//its a multilinestring, return true only if all the sub-linestrings have
-//startpoint=endpoint.
-//calculations always done in 3d (even if you do a force2d)
-
-
-PG_FUNCTION_INFO_V1(isclosed);
-Datum isclosed(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               POINT3D                 *pt1,*pt2;
-               LINE3D                  *line;
-               int32                           *offsets1;
-               int                             t;
-
-       if  (!((geom1->type == LINETYPE) || (geom1->type == MULTILINETYPE) ))
-               PG_RETURN_NULL();
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-
-       for (t=0; t< geom1->nobjs; t++)
-       {
-               line = (LINE3D *) ( (char *) geom1 +offsets1[t]);
-               pt1 = &line->points[0];
-               pt2 = &line->points[line->npoints-1];
-
-               if ( (pt1->x != pt2->x) || (pt1->y != pt2->y) || (pt1->z != pt2->z) )
-                       PG_RETURN_BOOL(FALSE);
-       }
-       PG_RETURN_BOOL(TRUE);
-}
-
-#if ! USE_GEOS
-PG_FUNCTION_INFO_V1(centroid);
-Datum centroid(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               int32                           *offsets1;
-               POINT3D                 *pts,*cent;
-               POLYGON3D                       *poly;
-               int                             t,v;
-               int                             num_points,num_points_tot;
-               double                  tot_x,tot_y,tot_z;
-               GEOMETRY                        *result;
-
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       if  (!((geom1->type == POLYGONTYPE) || (geom1->type == MULTIPOLYGONTYPE) ))
-               PG_RETURN_NULL();
-
-       //find the centroid
-       num_points_tot = 0;
-               tot_x = 0; tot_y =0; tot_z=0;
-
-       for (t=0;t<geom1->nobjs;t++)
-       {
-               poly = (POLYGON3D *) ( (char *) geom1 +offsets1[t]);
-               pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-               pts = (POINT3D *) MAXALIGN(pts);
-               num_points =poly->npoints[0];
-
-               // just do the outer ring
-       //      for (u=0;u<poly->nrings;u++)
-       //      {
-       //              num_points += poly->npoints[u];
-       //      }
-
-               num_points_tot += num_points-1; //last point = 1st point
-               for (v=0;v<num_points-1;v++)
-               {
-                       tot_x  += pts[v].x;
-                       tot_y  += pts[v].y;
-                       tot_z  += pts[v].z;
-               }
-       }
-       cent = palloc(sizeof(POINT3D));
-       set_point(cent, tot_x/num_points_tot, tot_y/num_points_tot,tot_z/num_points_tot);
-        result = (
-                               make_oneobj_geometry(sizeof(POINT3D),
-                                                        (char *) cent,
-                                                          POINTTYPE,  geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
-                               );
-       pfree(cent);
-       PG_RETURN_POINTER(result);
-
-}
-#endif // ! defined USE_GEOS
-
-// max_distance(geom,geom)  (both geoms must be linestrings)
-//find max distance between l1 and l2
-// method: for each point in l1, find distance to l2.
-//             return max distance
-//
-// note: max_distance(l1,l2) != max_distance(l2,l1)
-// returns double
-
-PG_FUNCTION_INFO_V1(max_distance);
-Datum max_distance(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                      *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               LINE3D                  *l1,*l2;
-
-               int32                   *offsets1,*offsets2;
-
-               int                     t;
-               POINT3D         *pt;
-
-               double          result,dist;
-
-       elog(ERROR, "This function is unimplemented yet");
-       PG_RETURN_NULL();
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       // only works with lines
-       if  (  (geom1->type != LINETYPE) || (geom2->type != LINETYPE) )
-               PG_RETURN_NULL();
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-       offsets2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+ sizeof(int32) * geom2->nobjs ) ;
-
-       l1 =  (LINE3D *) ( (char *) geom1 +offsets1[0]  );
-       l2 =  (LINE3D *) ( (char *) geom2 +offsets2[0]  ) ;
-
-       result = -9999; // all distances should be positive
-
-       for(t=0;t<l1->npoints;t++) //for each point in l1
-       {
-               pt = &l1->points[t];
-               dist =  distance_pt_line(pt, l2);
-
-               if (dist > result)
-               {
-                       result = dist;
-               }
-       }
-
-       if (result <0.0)
-               result = 0;
-
-       PG_RETURN_FLOAT8(result);
-}
-
-// optimistic_overlap(Polygon P1, Multipolygon MP2, double dist)
-// returns true if P1 overlaps MP2
-//   method: bbox check - is separation < dist?  no - return false (quick)
-//                                               yes  - return distance(P1,MP2) < dist
-
-PG_FUNCTION_INFO_V1(optimistic_overlap);
-Datum optimistic_overlap(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                      *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-               double                  dist = PG_GETARG_FLOAT8(2);
-               BOX3D                           g1_bvol;
-               double                  calc_dist;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"optimistic_overlap:Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if (geom1->type != POLYGONTYPE)
-       {
-               elog(ERROR,"optimistic_overlap: first arg isnt a polygon\n");
-               PG_RETURN_NULL();
-       }
-
-       if ( (geom2->type != POLYGONTYPE) &&  (geom2->type != MULTIPOLYGONTYPE) )
-       {
-               elog(ERROR,"optimistic_overlap: 2nd arg isnt a [multi-]polygon\n");
-               PG_RETURN_NULL();
-       }
-
-       //bbox check
-
-       memcpy(&g1_bvol, &geom1->bvol, sizeof(BOX3D) );
-
-       g1_bvol.LLB.x = g1_bvol.LLB.x - dist;
-       g1_bvol.LLB.y = g1_bvol.LLB.y - dist;
-
-       g1_bvol.URT.x = g1_bvol.URT.x + dist;
-       g1_bvol.URT.y = g1_bvol.URT.y + dist;
-
-       //xmin = LLB.x, xmax = URT.x
-
-
-       if (  (g1_bvol.LLB.x > geom2->bvol.URT.x) ||
-               (g1_bvol.URT.x < geom2->bvol.LLB.x) ||
-               (g1_bvol.LLB.y > geom2->bvol.URT.y) ||
-               (g1_bvol.URT.y < geom2->bvol.LLB.y)
-          )
-       {
-               PG_RETURN_BOOL(FALSE);  //bbox not overlap
-       }
-
-       //compute distances
-               //should be a fast calc if they actually do intersect
-       calc_dist =     DatumGetFloat8 (DirectFunctionCall2(distance,   PointerGetDatum( geom1 ),       PointerGetDatum( geom2 )));
-
-       PG_RETURN_BOOL(calc_dist < dist);
-}
-
-//returns a list of points for a single polygon
-// foreach segment
-//  (1st and last points will be unaltered, but
-//   there will be more points inbetween if segment length is
-POINT3D        *segmentize_ring(POINT3D        *points, double dist, int num_points_in, int *num_points_out)
-{
-       double  seg_distance;
-       int     max_points, offset_new,offset_old;
-       POINT3D *result,*r;
-       bool    keep_going;
-       POINT3D *last_point, *next_point;
-
-
-               //initial storage
-       max_points = 1000;
-       offset_new=0; //start at beginning of points list
-       result = (POINT3D *) palloc (sizeof(POINT3D) * max_points);
-
-       memcpy(result, points, sizeof(POINT3D) ); //1st point
-       offset_new++;
-
-       last_point = points;
-       offset_old = 1;
-
-       keep_going = 1;
-       while(keep_going)
-       {
-               next_point = &points[offset_old];
-
-                       //distance last->next > dist
-               seg_distance = sqrt(
-                       (next_point->x-last_point->x)*(next_point->x-last_point->x) +
-                       (next_point->y-last_point->y)*(next_point->y-last_point->y) );
-               if (offset_new >= max_points)
-               {
-                       //need to add new points to result
-                       r = result;
-                       result = (POINT3D *) palloc (sizeof(POINT3D) * max_points *2);//double size
-                       memcpy(result,r, sizeof(POINT3D)*max_points);
-                       max_points *=2;
-                       pfree(r);
-               }
-
-               if (seg_distance > dist)
-               {
-                       //add a point at the distance location
-                       // and set last_point to this loc
-
-                       result[offset_new].x = last_point->x + (next_point->x-last_point->x)/seg_distance * dist;
-                       result[offset_new].y = last_point->y + (next_point->y-last_point->y)/seg_distance * dist;
-                       last_point = &result[offset_new];
-                       offset_new ++;
-               }
-               else
-               {
-                       //everything fine, just add the next_point and pop forward
-                       result[offset_new].x = next_point->x;
-                       result[offset_new].y = next_point->y;
-                       offset_new++;
-                       offset_old++;
-                       last_point = next_point;
-               }
-               keep_going = (offset_old < num_points_in);
-       }
-       *num_points_out = offset_new;
-       return result;
-}
-
-// select segmentize('POLYGON((0 0, 0 10, 5 5, 0 0))',1);
-
-//segmentize(GEOMETRY P1, double maxlen)
-//given a [multi-]polygon, return a new polygon with each segment at most a given length
-PG_FUNCTION_INFO_V1(segmentize);
-Datum segmentize(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                *result = NULL, *result2;
-               double                  maxdist = PG_GETARG_FLOAT8(1);
-               int32                   *offsets1,*p_npoints_ring;
-               int                             g1_i,r;
-               POLYGON3D               *p,*poly;
-               POINT3D                 *polypts;
-               int                             num_polypts;
-               POINT3D                 *all_polypts;
-               int                             all_num_polypts,all_num_polypts_max;
-               POINT3D                 *p_points,*rr;
-               int                             new_size;
-               bool                    first_one;
-               int                             poly_size;
-               BOX3D                   *bbox;
-
-       first_one = 1;
-
-
-       if ( (geom1->type != POLYGONTYPE) &&  (geom1->type != MULTIPOLYGONTYPE) )
-       {
-               elog(ERROR,"segmentize: 1st arg isnt a [multi-]polygon\n");
-               PG_RETURN_NULL();
-       }
-
-
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-
-       for (g1_i=0; g1_i < geom1->nobjs; g1_i++)
-       {
-
-               all_num_polypts = 0;
-               all_num_polypts_max = 1000;
-               all_polypts = (POINT3D *) palloc (sizeof(POINT3D) * all_num_polypts_max );
-
-               p = (POLYGON3D*)((char *) geom1 +offsets1[g1_i]) ;  // the polygon
-
-               p_npoints_ring = (int32 *) palloc(sizeof(int32) * p->nrings);
-
-               p_points = (POINT3D *) ( (char *)&(p->npoints[p->nrings] )  );
-               p_points = (POINT3D *) MAXALIGN(p_points);
-
-               for (r=0;r<p->nrings;r++)  //foreach ring in the polygon
-               {
-                       polypts = segmentize_ring(p_points, maxdist, p->npoints[r], &num_polypts);
-                       if ( (all_num_polypts + num_polypts) < all_num_polypts_max )
-                       {
-                               //just add
-                               memcpy( &all_polypts[all_num_polypts], polypts, sizeof(POINT3D) *num_polypts );
-                               all_num_polypts += num_polypts;
-                       }
-                       else
-                       {
-                               //need more space
-                               new_size = all_num_polypts_max + num_polypts + 1000;
-                               rr = (POINT3D*) palloc(sizeof(POINT3D) * new_size);
-                               memcpy(rr,all_polypts, sizeof(POINT3D) *all_num_polypts);
-                               memcpy(&rr[all_num_polypts], polypts , sizeof(POINT3D) *num_polypts);
-                               pfree(all_polypts);
-                               all_polypts = rr;
-                               all_num_polypts += num_polypts;
-                       }
-                       //set points in ring value
-                       pfree(polypts);
-                       p_npoints_ring[r] = num_polypts;
-               } //for each ring
-
-               poly = make_polygon(p->nrings, p_npoints_ring, all_polypts, all_num_polypts, &poly_size);
-
-               if (first_one)
-               {
-                       first_one = 0;
-                       result = make_oneobj_geometry(poly_size, (char *)poly, POLYGONTYPE, FALSE,geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY);
-                       pfree(poly);
-                       pfree(all_polypts);
-               }
-               else
-               {
-                       result2 = add_to_geometry(result,poly_size, (char *) poly, POLYGONTYPE);
-                       bbox = bbox_of_geometry( result2 ); // make bounding box
-                       memcpy( &result2->bvol, bbox, sizeof(BOX3D) ); // copy bounding box
-                       pfree(bbox); // free bounding box
-                       pfree(result);
-                       result = result2;
-                       pfree(poly);
-                       pfree(all_polypts);
-               }
-
-       } // foreach polygon
-       PG_RETURN_POINTER(result);
-}
-
-/*
- * This is a geometry array constructor
- * for use as aggregates sfunc.
- * Will have * as input an array of Geometry pointers and a Geometry.
- * Will DETOAST given geometry and put a pointer to it
- * in the given array. DETOASTED value is first copied
- * to a safe memory context to avoid premature deletion.
- */
-PG_FUNCTION_INFO_V1(geom_accum);
-Datum geom_accum(PG_FUNCTION_ARGS)
-{
-       ArrayType *array;
-       int nelems, nbytes;
-       Datum datum;
-       GEOMETRY *geom;
-       ArrayType *result;
-       Pointer **pointers;
-       MemoryContext oldcontext;
-
-       datum = PG_GETARG_DATUM(0);
-       if ( (Pointer *)datum == NULL ) {
-               array = NULL;
-               nelems = 0;
-               //elog(NOTICE, "geom_accum: NULL array, nelems=%d", nelems);
-       } else {
-               array = (ArrayType *) PG_DETOAST_DATUM_COPY(datum);
-               nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
-       }
-
-       datum = PG_GETARG_DATUM(1);
-       // Do nothing, return state array
-       if ( (Pointer *)datum == NULL )
-       {
-               //elog(NOTICE, "geom_accum: NULL geom, nelems=%d", nelems);
-               PG_RETURN_ARRAYTYPE_P(array);
-       }
-
-       /*
-        * Switch to * flinfo->fcinfo->fn_mcxt
-        * memory context to be sure both detoasted
-        * geometry AND array of pointers to it
-        * last till the call to unite_finalfunc.
-        */
-       oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-
-       /* Make a DETOASTED copy of input geometry */
-       geom = (GEOMETRY *)PG_DETOAST_DATUM_COPY(datum);
-
-       //elog(NOTICE, "geom_accum: adding %p (nelems=%d)", geom, nelems);
-
-       /*
-        * Might use a more optimized version instead of repalloc'ing
-        * at every iteration. This is not the bottleneck anyway.
-        *              --strk(TODO);
-        */
-       ++nelems;
-       nbytes = ARR_OVERHEAD(1) + sizeof(Pointer *) * nelems;
-       if ( ! array ) {
-               result = (ArrayType *) palloc(nbytes);
-               result->size = nbytes;
-               result->ndim = 1;
-               *((int *) ARR_DIMS(result)) = nelems;
-       } else {
-               result = (ArrayType *) repalloc(array, nbytes);
-               result->size = nbytes;
-               result->ndim = 1;
-               *((int *) ARR_DIMS(result)) = nelems;
-       }
-
-       pointers = (Pointer **)ARR_DATA_PTR(result);
-       pointers[nelems-1] = (Pointer *)geom;
-
-       /* Go back to previous memory context */
-       MemoryContextSwitchTo(oldcontext);
-
-
-       PG_RETURN_ARRAYTYPE_P(result);
-
-}
-
-/*
- * collect_garray ( GEOMETRY[] ) returns a geometry which contains
- * all the sub_objects from all of the geometries in given array.
- *
- * returned geometry is the simplest possible, based on the types
- * of the collected objects
- * ie. if all are of either X or multiX, then a multiX is returned
- * bboxonly types are treated as null geometries (no sub_objects)
- */
-PG_FUNCTION_INFO_V1( collect_garray );
-Datum collect_garray ( PG_FUNCTION_ARGS )
-{
-       Datum datum;
-       ArrayType *array;
-       int nelems, srid=-1, is3d=0;
-       GEOMETRY **geoms;
-       GEOMETRY *result=NULL, *geom, *tmp;
-       int i, o;
-       BOX3D *bbox;
-
-       /* Get input datum */
-       datum = PG_GETARG_DATUM(0);
-
-       /* Return null on null input */
-       if ( (Pointer *)datum == NULL ) PG_RETURN_NULL();
-
-       /* Get actual ArrayType */
-       array = (ArrayType *) PG_DETOAST_DATUM(datum);
-
-       /* Get number of geometries in array */
-       nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
-
-       /* Return null on 0-elements input array */
-       if ( nelems == 0 ) PG_RETURN_NULL();
-
-       /* Get pointer to GEOMETRY pointers array */
-       geoms = (GEOMETRY **)ARR_DATA_PTR(array);
-
-       /* Return the only present element of a 1-element array */
-       if ( nelems == 1 ) PG_RETURN_POINTER(geoms[0]);
-
-       /* Iterate over all geometries in array */
-       for (i=0; i<nelems; i++)
-       {
-               int32 *offsets;
-
-               geom = geoms[i];
-
-               /* Skip NULL array elements (are them possible?) */
-               if ( geom == NULL ) continue;
-
-               /* Use first NOT-NULL GEOMETRY as the base */
-               if ( ! result )
-               {
-                       /* Remember first geometry's SRID for later checks */
-                       srid = geom->SRID;
-
-                       /* Get first geometry's is3d flag as base is3d */
-                       is3d = geom->is3d;
-
-                       result = (GEOMETRY *)palloc(geom->size);
-                       if ( ! result ) {
-       elog(ERROR, "collect_garray: out of virtual memory");
-       PG_RETURN_NULL();
-                       }
-                       memcpy(result, geom, geom->size);
-
-                       /*
-                        * I belive memory associated with geometries
-                        * in array can be safely removed. Comment
-                        * this out if you get memory faults!
-                        * TODO: inspect this (as long as passed
-                        * array is the result of geom_accum this
-                        * is true because geom_accum will DETOAST_COPY
-                        * while for direct user call I do not know)
-                        */
-                       pfree(geom);
-
-                       continue;
-               }
-
-               /* Skip geometry if it contains no sub-objects */
-               if ( ! geom->nobjs )
-               {
-                       if ( geom->is3d ) is3d = 1; // should I care ?
-                       pfree(geom); // se note above
-                       continue;
-               }
-
-               /*
-                * If we are here this means we are in front of a
-                * good (non empty) geometry beside the first
-                */
-
-               /* Fist let's check for SRID compatibility */
-               if ( geom->SRID != srid )
-               {
-       elog(ERROR, "Operation on GEOMETRIES with different SRIDs");
-       PG_RETURN_NULL();
-               }
-
-               /*
-                * Set result is3d flag to true if at least one
-                * of geometries in set has is set to true
-                */
-               if ( geom->is3d ) is3d = 1;
-
-               /* Get to sub-objects offset */
-               offsets = (int32 *)(((char *)&(geom->objType[0])) +
-                               sizeof(int32) * geom->nobjs ) ;
-
-               /* Iterate over geometry sub-objects */
-               for (o=0; o<geom->nobjs; o++)
-               {
-                       int size, type;
-                       char *obj;
-
-                       /* Get object pointer */
-                       obj = (char *) geom+offsets[o];
-
-                       /* Get object type */
-                       type = geom->objType[o];
-
-                       /* Get object size (fast way) */
-                       if( o == geom->nobjs-1 ) {
-                               size = geom->size - offsets[o];
-                       } else {
-                               size = offsets[o+1] - offsets[o];
-                       }
-
-                       /*
-                        * Add sub-object to base geometry,
-                        * replace base geometry with new one.
-                        */
-                       tmp = add_to_geometry(result, size, obj, type);
-                       pfree( result );
-                       result = tmp;
-               }
-               pfree(geom); // se note above
-       }
-
-       /* Check we got something in our result */
-       if ( result == NULL ) PG_RETURN_NULL();
-
-       /*
-        * We should now have a big fat geometry composed of all
-        * sub-objects from all geometries in array
-        */
-
-       /* Set is3d flag */
-       result->is3d = is3d;
-
-       /* Construct bounding volume */
-       bbox = bbox_of_geometry( result ); // make
-       memcpy( &result->bvol, bbox, sizeof(BOX3D) ); // copy
-       pfree( bbox ); // release
-
-       PG_RETURN_POINTER( result );
-}
-
-// collector( geom, geom ) returns a geometry which contains
-// all the sub_objects from both of the argument geometries
-
-// returned geometry is the simplest possible, based on the types
-// of the colelct objects
-// ie. if all are of either X or multiX, then a multiX is returned
-// bboxonly types are treated as null geometries (no sub_objects)
-PG_FUNCTION_INFO_V1( collector );
-Datum collector( PG_FUNCTION_ARGS )
-{
-       Pointer         geom1_ptr = PG_GETARG_POINTER(0);
-       Pointer         geom2_ptr =  PG_GETARG_POINTER(1);
-       GEOMETRY        *geom1, *geom2, *temp, *result;
-       BOX3D           *bbox;
-       int32           i, size, *offsets2;
-
-       // return null if both geoms are null
-       if ( (geom1_ptr == NULL) && (geom2_ptr == NULL) )
-       {
-               PG_RETURN_NULL();
-       }
-
-       // return a copy of the second geom if only first geom is null
-       if (geom1_ptr == NULL)
-       {
-               geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-               result = (GEOMETRY *)palloc( geom2->size );
-               memcpy( result, geom2, geom2->size );
-               PG_RETURN_POINTER(result);
-       }
-
-       // return a copy of the first geom if only second geom is null
-       if (geom2_ptr == NULL)
-       {
-               geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               result = (GEOMETRY *)palloc( geom1->size );
-               memcpy( result, geom1, geom1->size );
-               PG_RETURN_POINTER(result);
-       }
-
-       geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       if ( geom1->SRID != geom2->SRID )
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if (geom1->nobjs ==0)
-       {
-               geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-               result = (GEOMETRY *)palloc( geom2->size );
-               memcpy( result, geom2, geom2->size );
-               PG_RETURN_POINTER(result);
-       }
-       if (geom2->nobjs ==0)
-       {
-               geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               result = (GEOMETRY *)palloc( geom1->size );
-               memcpy( result, geom1, geom1->size );
-               PG_RETURN_POINTER(result);
-       }
-
-       result = (GEOMETRY *)palloc( geom1->size );
-       memcpy( result, geom1, geom1->size );
-
-       offsets2 = (int32 *)( ((char *)&(geom2->objType[0])) + sizeof( int32 ) * geom2->nobjs ) ;
-
-       for (i=0; i<geom2->nobjs; i++)
-       {
-               if( i == geom2->nobjs-1 )
-               {
-                       size = geom2->size - offsets2[i];
-               }
-               else
-               {
-                       size = offsets2[i+1] - offsets2[i];
-               }
-               temp = add_to_geometry( result, size, ((char *) geom2 + offsets2[i]), geom2->objType[i] );
-               pfree( result );
-               result = temp;
-       }
-
-       result->is3d = geom1->is3d || geom2->is3d;
-       bbox = bbox_of_geometry( result ); // make bounding box
-       memcpy( &result->bvol, bbox, sizeof(BOX3D) ); // copy bounding box
-       pfree( bbox ); // free bounding box
-
-       PG_RETURN_POINTER( result );
-}
-
-PG_FUNCTION_INFO_V1(box3d_xmin);
-Datum box3d_xmin(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->LLB.x);
-}
-
-PG_FUNCTION_INFO_V1(box3d_ymin);
-Datum box3d_ymin(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->LLB.y);
-}
-
-PG_FUNCTION_INFO_V1(box3d_zmin);
-Datum box3d_zmin(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->LLB.z);
-}
-
-PG_FUNCTION_INFO_V1(box3d_xmax);
-Datum box3d_xmax(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->URT.x);
-}
-
-PG_FUNCTION_INFO_V1(box3d_ymax);
-Datum box3d_ymax(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->URT.y);
-}
-
-PG_FUNCTION_INFO_V1(box3d_zmax);
-Datum box3d_zmax(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-
-       PG_RETURN_FLOAT8(box1->URT.z);
-}
-
-PG_FUNCTION_INFO_V1(box3dtobox);
-Datum box3dtobox(PG_FUNCTION_ARGS)
-{
-       BOX3D *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-       BOX *out;
-       out = convert_box3d_to_box(box1);
-       PG_RETURN_POINTER(out);
-}
-
-
-PG_FUNCTION_INFO_V1(isempty);
-Datum isempty(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1= (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-
-       if (geom1->nobjs ==0)
-               PG_RETURN_BOOL(TRUE);
-       PG_RETURN_BOOL(FALSE);
-}
-
-
-// converts multi* types with 1 element to the single-element version.
-// ie. MULTIPOINT(0 0) --> POINT(0 0)
-void compressType(GEOMETRY *g)
-{
-       if (g->nobjs ==1)
-       {
-               if (g->type == MULTIPOINTTYPE)
-               {
-                       g->type = POINTTYPE;
-                       return;
-               }
-               if (g->type == MULTILINETYPE)
-               {
-                       g->type = LINETYPE;
-                       return;
-               }
-               if (g->type == MULTIPOLYGONTYPE)
-               {
-                       g->type = POLYGONTYPE;
-                       return;
-               }
-
-       }
-}
-
-
-// converts single-type (point,linestring,polygon)
-// to multi* types with 1 element
-// ie. POINT(0 0) --> MULTIPOINT(0 0)
-//
-//postgis09=# select fluffType('POINT(0 0)');
-//        flufftype
-//-------------------------
-// SRID=-1;MULTIPOINT(0 0)
-//(1 row)
-//
-//postgis09=# select fluffType('LINESTRING(0 0, 1 1)');
-//             flufftype
-//------------------------------------
-// SRID=-1;MULTILINESTRING((0 0,1 1))
-//(1 row)
-
-PG_FUNCTION_INFO_V1(fluffType);
-Datum fluffType(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom1= (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                          *g;
-
-               g = (GEOMETRY*) palloc( *((int *) geom1) );
-               memcpy(g,geom1, *((int *) geom1));
-
-                       if (g->type == POINTTYPE)
-                       {
-                               g->type = MULTIPOINTTYPE;
-                       }
-                       if (g->type == LINETYPE)
-                       {
-                               g->type = MULTILINETYPE;
-                       }
-                       if (g->type == POLYGONTYPE)
-                       {
-                               g->type = MULTIPOLYGONTYPE;
-                       }
-
-       PG_FREE_IF_COPY(geom1,0);
-       PG_RETURN_POINTER(g);
-}
-
-PG_FUNCTION_INFO_V1(postgis_lib_version);
-Datum postgis_lib_version(PG_FUNCTION_ARGS)
-{
-       char *ver = POSTGIS_LIB_VERSION;
-       text *result;
-       result = (text *) palloc(VARHDRSZ  + strlen(ver));
-       VARATT_SIZEP(result) = VARHDRSZ + strlen(ver) ;
-       memcpy(VARDATA(result), ver, strlen(ver));
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(postgis_scripts_released);
-Datum postgis_scripts_released(PG_FUNCTION_ARGS)
-{
-       char *ver = POSTGIS_SCRIPTS_VERSION;
-       text *result;
-       result = (text *) palloc(VARHDRSZ  + strlen(ver));
-       VARATT_SIZEP(result) = VARHDRSZ + strlen(ver) ;
-       memcpy(VARDATA(result), ver, strlen(ver));
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(postgis_uses_stats);
-Datum postgis_uses_stats(PG_FUNCTION_ARGS)
-{
-#ifdef USE_STATS
-       PG_RETURN_BOOL(TRUE);
-#else
-       PG_RETURN_BOOL(FALSE);
-#endif
-}
diff --git a/hwgeom/postgis_geos.c b/hwgeom/postgis_geos.c
deleted file mode 100644 (file)
index 1713368..0000000
+++ /dev/null
@@ -1,2142 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.39  2004/08/23 15:37:16  strk
- * Changed SCRIPTS_VERSION to 0.0.1
- *
- * Revision 1.38  2004/07/28 16:10:59  strk
- * Changed all version functions to return text.
- * Renamed postgis_scripts_version() to postgis_scripts_installed()
- * Added postgis_scripts_released().
- * Added postgis_full_version().
- *
- * Revision 1.37  2004/07/28 13:37:43  strk
- * Added postgis_uses_stats and postgis_scripts_version.
- * Experimented with PIP short-circuit in within/contains functions.
- * Documented new version functions.
- *
- * Revision 1.36  2004/07/27 17:51:50  strk
- * short-circuit test for 'contains'
- *
- * Revision 1.35  2004/07/27 17:49:59  strk
- * Added short-circuit test for the within function.
- *
- * Revision 1.34  2004/07/22 16:58:08  strk
- * Updated to reflect geos version string split.
- *
- * Revision 1.33  2004/07/22 16:20:10  strk
- * Added postgis_lib_version() and postgis_geos_version()
- *
- * Revision 1.32  2004/07/01 17:02:05  strk
- * Updated to support latest GEOS (actually removed all geos-version related
- * switches).
- * Fixed an access to unallocated memory.
- *
- * Revision 1.31  2004/06/16 19:59:36  strk
- * Changed GEOS_VERSION to POSTGIS_GEOS_VERSION to avoid future clashes
- *
- * Revision 1.30  2004/06/16 19:37:54  strk
- * Added cleanup needed for GEOS > 1.0
- *
- * Revision 1.29  2004/06/16 18:47:59  strk
- * Added code to detect geos version.
- * Added appropriate includes in geos connectors.
- *
- * Revision 1.28  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.27  2004/02/12 10:34:49  strk
- * changed USE_GEOS check from ifdef / ifndef to if / if !
- *
- * Revision 1.26  2003/12/12 12:03:29  strk
- * More debugging output, some code cleanup.
- *
- * Revision 1.25  2003/12/12 10:28:50  strk
- * added GEOSnoop OUTPUT debugging info
- *
- * Revision 1.24  2003/12/12 10:08:24  strk
- * Added GEOSnoop function and some optional debugging output for
- * geos<->postgis converter (define DEBUG_CONVERTER at top postgis_geos.c)
- *
- * Revision 1.23  2003/11/05 18:25:08  strk
- * moved #ifdef USE_GEOS below prototypes, added NULL implementation of unite_garray
- *
- * Revision 1.22  2003/11/05 18:02:41  strk
- * renamed unite_finalfunc to unite_garray
- *
- * Revision 1.21  2003/11/04 19:06:08  strk
- * added missing first geom pfree in unite_finalfunc
- *
- * Revision 1.20  2003/10/29 15:53:10  strk
- * geoscentroid() removed. both geos and pgis versions are called 'centroid'.
- * only one version will be compiled based on USE_GEOS flag.
- *
- * Revision 1.19  2003/10/29 13:59:40  strk
- * Added geoscentroid function.
- *
- * Revision 1.18  2003/10/28 15:16:17  strk
- * unite_sfunc() from postgis_geos.c renamed to geom_accum() and moved in postgis_fn.c
- *
- * Revision 1.17  2003/10/28 10:59:55  strk
- * handled NULL state array in unite_finalfunc, cleaned up some spurios code
- *
- * Revision 1.16  2003/10/27 23:44:54  strk
- * unite_sfunc made always copy input array in long lived memory context.
- * It should now work with safer memory.
- *
- * Revision 1.15  2003/10/27 20:13:05  strk
- * Made GeomUnion release memory soon, Added fastunion support functions
- *
- * Revision 1.14  2003/10/24 21:52:35  strk
- * Modified strcmp-based if-else with switch-case in GEOS2POSTGIS()
- * using new GEOSGeometryTypeId() interface.
- *
- * Revision 1.13  2003/10/24 08:28:49  strk
- * Fixed memory leak in GEOSGetCoordinates(), made sure that GEOS2POSTGIS
- * free type string even in case of collapsed geoms. Made sure that geomunion
- * release memory in case of exception thrown by GEOSUnion. Sooner release
- * of palloced memory in PolyFromGeometry (pts_per_ring).
- *
- * Revision 1.12  2003/10/16 20:16:18  dblasby
- * Added NOTICE_HANDLER function.  For some reason this didnt get properly
- * committed last time.
- *
- * Revision 1.11  2003/10/14 23:19:19  dblasby
- * GEOS2POSTGIS - added protection to pfree(NULL) for multi* geoms
- *
- * Revision 1.10  2003/10/03 16:45:37  dblasby
- * added pointonsurface() as a sub.  Some memory management fixes/tests.
- * removed a few NOTICEs.
- *
- * Revision 1.9  2003/09/16 20:27:12  dblasby
- * added ability to delete geometries.
- *
- * Revision 1.8  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.7  2003/08/06 19:31:18  dblasby
- * Added the WKB parser.  Added all the functions like
- * PolyFromWKB(<WKB>,[<SRID>]).
- *
- * Added all the functions like PolyFromText(<WKT>,[<SRID>])
- *
- * Minor problem in GEOS library fixed.
- *
- * Revision 1.6  2003/08/05 18:27:21  dblasby
- * Added null implementations of new GEOS-returning-geometry functions (ie.
- * buffer).
- *
- * Revision 1.5  2003/08/01 23:58:08  dblasby
- * added the functionality to convert GEOS->PostGIS geometries.  Added those geos
- * functions to postgis.
- *
- * Revision 1.4  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-
-//--------------------------------------------------------------------------
-//
-//#define DEBUG
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-#include "utils/array.h"
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "utils/builtins.h"
-
-//#include "postgis_geos_version.h"
-
- /*
-  * Define this to have have many notices printed
-  * during postgis->geos and geos->postgis conversions
-  */
-#undef DEBUG_CONVERTER
-#undef DEBUG_POSTGIS2GEOS
-#undef DEBUG_GEOS2POSTGIS
-
-
-typedef  struct Geometry Geometry;
-
-
-extern const char * createGEOSPoint(POINT3D *pt);
-extern void initGEOS(int maxalign);
-extern char *GEOSrelate(Geometry *g1, Geometry*g2);
-extern char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat);
-extern  char GEOSrelateDisjoint(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateTouches(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateIntersects(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateCrosses(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateWithin(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateContains(Geometry *g1, Geometry*g2);
-extern  char GEOSrelateOverlaps(Geometry *g1, Geometry*g2);
-
-extern char *GEOSasText(Geometry *g1);
-extern char GEOSisEmpty(Geometry *g1);
-extern char *GEOSGeometryType(Geometry *g1);
-extern int GEOSGeometryTypeId(Geometry *g1);
-extern char *GEOSversion();
-extern char *GEOSjtsport();
-
-
-extern void GEOSdeleteChar(char *a);
-extern void GEOSdeleteGeometry(Geometry *a);
-
-extern  Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d);
-extern  Geometry *PostGIS2GEOS_linestring(LINE3D *line,int SRID, bool is3d);
-extern  Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d);
-extern  Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d);
-extern Geometry *PostGIS2GEOS_multilinestring(LINE3D **lines,int nlines, int SRID, bool is3d);
-extern Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d);
-extern Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID);
-extern Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d);
-
-extern char GEOSisvalid(Geometry *g1);
-
-
-
-extern char *throw_exception(Geometry *g);
-extern Geometry *GEOSIntersection(Geometry *g1, Geometry *g2);
-
-
-extern POINT3D  *GEOSGetCoordinate(Geometry *g1);
-extern POINT3D  *GEOSGetCoordinates(Geometry *g1);
-extern int      GEOSGetNumCoordinate(Geometry *g1);
-extern Geometry        *GEOSGetGeometryN(Geometry *g1, int n);
-extern Geometry        *GEOSGetExteriorRing(Geometry *g1);
-extern Geometry        *GEOSGetInteriorRingN(Geometry *g1,int n);
-extern int     GEOSGetNumInteriorRings(Geometry *g1);
-extern int      GEOSGetSRID(Geometry *g1);
-extern int      GEOSGetNumGeometries(Geometry *g1);
-
-extern  Geometry *GEOSBuffer(Geometry *g1,double width);
-extern  Geometry *GEOSConvexHull(Geometry *g1);
-extern  Geometry *GEOSDifference(Geometry *g1,Geometry *g2);
-extern  Geometry *GEOSBoundary(Geometry *g1);
-extern  Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2);
-extern  Geometry *GEOSUnion(Geometry *g1,Geometry *g2);
-extern   char GEOSequals(Geometry *g1, Geometry*g2);
-
-extern  char GEOSisSimple(Geometry *g1);
-extern char GEOSisRing(Geometry *g1);
-
-extern Geometry *GEOSpointonSurface(Geometry *g1);
-extern Geometry *GEOSGetCentroid(Geometry *g);
-
-
-Datum relate_full(PG_FUNCTION_ARGS);
-Datum relate_pattern(PG_FUNCTION_ARGS);
-Datum disjoint(PG_FUNCTION_ARGS);
-Datum touches(PG_FUNCTION_ARGS);
-Datum intersects(PG_FUNCTION_ARGS);
-Datum crosses(PG_FUNCTION_ARGS);
-Datum within(PG_FUNCTION_ARGS);
-Datum contains(PG_FUNCTION_ARGS);
-Datum overlaps(PG_FUNCTION_ARGS);
-Datum isvalid(PG_FUNCTION_ARGS);
-
-
-Datum buffer(PG_FUNCTION_ARGS);
-Datum intersection(PG_FUNCTION_ARGS);
-Datum convexhull(PG_FUNCTION_ARGS);
-Datum difference(PG_FUNCTION_ARGS);
-Datum boundary(PG_FUNCTION_ARGS);
-Datum symdifference(PG_FUNCTION_ARGS);
-Datum geomunion(PG_FUNCTION_ARGS);
-Datum unite_garray(PG_FUNCTION_ARGS);
-
-
-Datum issimple(PG_FUNCTION_ARGS);
-Datum isring(PG_FUNCTION_ARGS);
-Datum geomequals(PG_FUNCTION_ARGS);
-Datum pointonsurface(PG_FUNCTION_ARGS);
-
-Datum GEOSnoop(PG_FUNCTION_ARGS);
-
-
-Geometry *POSTGIS2GEOS(GEOMETRY *g);
-void errorIfGeometryCollection(GEOMETRY *g1, GEOMETRY *g2);
-GEOMETRY *GEOS2POSTGIS(Geometry *g, char want3d );
-
-POLYGON3D *PolyFromGeometry(Geometry *g, int *size);
-LINE3D *LineFromGeometry(Geometry *g, int *size);
-void NOTICE_MESSAGE(char *msg);
-
-#if USE_GEOS
-
-//-----------------------------------------------
-// return a GEOS Geometry from a POSTGIS GEOMETRY
-//----------------------------------------------
-
-
-
-void NOTICE_MESSAGE(char *msg)
-{
-       elog(NOTICE,msg);
-}
-
-
-/*
- * Resize an ArrayType of 1 dimension to contain num (Pointer *) elements
- * array will be repalloc'ed
- */
-static ArrayType *
-resize_ptrArrayType(ArrayType *a, int num)
-{
-       int nelems = ArrayGetNItems(ARR_NDIM(a), ARR_DIMS(a));
-       int nbytes = ARR_OVERHEAD(1) + sizeof(Pointer *) * num;
-
-       if (num == nelems) return a;
-
-       a = (ArrayType *) repalloc(a, nbytes);
-
-       a->size = nbytes;
-       a->ndim = 1;
-
-       *((int *) ARR_DIMS(a)) = num;
-       return a;
-}
-
-
-/*
- * This is the final function for union/fastunite/geomunion
- * aggregate (still discussing the name). Will have
- * as input an array of Geometry pointers.
- * Will iteratively call GEOSUnion on the GEOS-converted
- * versions of them and return PGIS-converted version back.
- * Changing combination order *might* speed up performance.
- *
- * Geometries in the array are pfree'd as soon as possible.
- *
- */
-PG_FUNCTION_INFO_V1(unite_garray);
-Datum unite_garray(PG_FUNCTION_ARGS)
-{
-       Datum datum;
-       ArrayType *array;
-       int is3d = 0;
-       int nelems, i;
-       GEOMETRY **geoms, *result, *pgis_geom;
-       Geometry *g1, *g2, *geos_result;
-#ifdef DEBUG
-       static int call=1;
-#endif
-
-#ifdef DEBUG
-       call++;
-#endif
-
-       datum = PG_GETARG_DATUM(0);
-
-       /* Null array, null geometry (should be empty?) */
-       if ( (Pointer *)datum == NULL ) PG_RETURN_NULL();
-
-       array = (ArrayType *) PG_DETOAST_DATUM(datum);
-
-       nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
-
-#ifdef DEBUG
-       elog(NOTICE, "unite_garray: number of elements: %d", nelems);
-#endif
-
-       if ( nelems == 0 ) PG_RETURN_NULL();
-
-       geoms = (GEOMETRY **)ARR_DATA_PTR(array);
-
-       /* One-element union is the element itself */
-       if ( nelems == 1 ) PG_RETURN_POINTER(geoms[0]);
-
-       /* Ok, we really need geos now ;) */
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       if ( geoms[0]->is3d ) is3d = 1;
-       geos_result = POSTGIS2GEOS(geoms[0]);
-       pfree(geoms[0]);
-       for (i=1; i<nelems; i++)
-       {
-               pgis_geom = geoms[i];
-               
-               g1 = POSTGIS2GEOS(pgis_geom);
-               /*
-                * If we free this memory now we'll have
-                * more space for the growing result geometry.
-                * We don't need it anyway.
-                */
-               pfree(pgis_geom);
-
-#ifdef DEBUG
-               elog(NOTICE, "unite_garray(%d): adding geom %d to union",
-                               call, i);
-#endif
-
-               g2 = GEOSUnion(g1,geos_result);
-               if ( g2 == NULL )
-               {
-                       GEOSdeleteGeometry(g1);
-                       GEOSdeleteGeometry(geos_result);
-                       elog(ERROR,"GEOS union() threw an error!");
-               }
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(geos_result);
-               geos_result = g2;
-       }
-
-       result = GEOS2POSTGIS(geos_result, is3d);
-       GEOSdeleteGeometry(geos_result);
-       if ( result == NULL )
-       {
-               elog(ERROR, "GEOS2POSTGIS returned an error");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       compressType(result);
-
-       PG_RETURN_POINTER(result);
-
-}
-
-
-//select geomunion('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
-PG_FUNCTION_INFO_V1(geomunion);
-Datum geomunion(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       int is3d = geom1->is3d || geom2->is3d;
-
-       Geometry *g1,*g2,*g3;
-       GEOMETRY *result;
-
-       initGEOS(MAXIMUM_ALIGNOF);
-//elog(NOTICE,"in geomunion");
-
-       g1 = POSTGIS2GEOS(geom1);
-       g2 = POSTGIS2GEOS(geom2);
-
-//elog(NOTICE,"g1=%s",GEOSasText(g1));
-//elog(NOTICE,"g2=%s",GEOSasText(g2));
-       g3 = GEOSUnion(g1,g2);
-
-//elog(NOTICE,"g3=%s",GEOSasText(g3));
-
-       PG_FREE_IF_COPY(geom1, 0);
-       PG_FREE_IF_COPY(geom2, 1);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS union() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-//elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, is3d);
-
-       GEOSdeleteGeometry(g3);
-
-       if (result == NULL)
-       {
-               elog(ERROR,"GEOS union() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       compressType(result);  // convert multi* to single item if appropriate
-       PG_RETURN_POINTER(result);
-}
-
-
-// select symdifference('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
-PG_FUNCTION_INFO_V1(symdifference);
-Datum symdifference(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               Geometry *g1,*g2,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g2 =    POSTGIS2GEOS(geom2 );
-               g3 =    GEOSSymDifference(g1,g2);
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS symdifference() threw an error!");
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               PG_RETURN_NULL(); //never get here
-       }
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS symdifference() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-}
-
-
-PG_FUNCTION_INFO_V1(boundary);
-Datum boundary(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-               Geometry *g1,*g3;
-               GEOMETRY *result;
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g3 =    GEOSBoundary(g1);
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS bounary() threw an error!");
-               GEOSdeleteGeometry(g1);
-               PG_RETURN_NULL(); //never get here
-       }
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS bounary() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(convexhull);
-Datum convexhull(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               Geometry *g1,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g3 =    GEOSConvexHull(g1);
-
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS convexhull() threw an error!");
-               GEOSdeleteGeometry(g1);
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS convexhull() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-
-}
-
-PG_FUNCTION_INFO_V1(buffer);
-Datum buffer(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               double                  size   = PG_GETARG_FLOAT8(1);
-               Geometry *g1,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g3 =    GEOSBuffer(g1,size);
-
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS buffer() threw an error!");
-               GEOSdeleteGeometry(g1);
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS buffer() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-
-
-               compressType(result);  // convert multi* to single item if appropriate
-               PG_RETURN_POINTER(result);
-
-}
-
-
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((25 5, 35 5, 35 7, 25 7, 25 5))');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POINT(5 5)');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','LINESTRING(5 5, 10 10)');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','MULTIPOINT(5 5, 7 7, 9 9, 10 10, 11 11)');
-//select intersection('POLYGON(( 0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5 ),(6 6,6.5 6, 6.5 6.5,6 6.5,6 6))');
-
-
-////select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','MULTIPOINT(5 5, 7 7, 9 9, 10 10, 11 11)');
-// select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','MULTILINESTRING((5 5, 10 10),(1 1, 2 2) )');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','MULTILINESTRING((5 5, 10 10),(1 1, 2 2) )');
-//select intersection('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','MULTIPOLYGON(((5 5, 15 5, 15 7, 5 7, 5 5)),((1 1,1 2,2 2,1 2, 1 1)))');
-PG_FUNCTION_INFO_V1(intersection);
-Datum intersection(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               Geometry *g1,*g2,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-//elog(NOTICE,"intersection() START");
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g2 =    POSTGIS2GEOS(geom2 );
-
-//elog(NOTICE,"               constructed geometrys - calling geos");
-
-//elog(NOTICE,"g1 = %s",GEOSasText(g1));
-//elog(NOTICE,"g2 = %s",GEOSasText(g2));
-
-
-//if (g1==NULL)
-//     elog(NOTICE,"g1 is null");
-//if (g2==NULL)
-//     elog(NOTICE,"g2 is null");
-//elog(NOTICE,"g2 is valid = %i",GEOSisvalid(g2));
-//elog(NOTICE,"g1 is valid = %i",GEOSisvalid(g1));
-
-
-               g3 =    GEOSIntersection(g1,g2);
-
-//elog(NOTICE,"               intersection finished");
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS Intersection() threw an error!");
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS Intersection() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-}
-
-//select difference('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','POLYGON((5 5, 15 5, 15 7, 5 7, 5 5))');
-PG_FUNCTION_INFO_V1(difference);
-Datum difference(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               Geometry *g1,*g2,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g2 =    POSTGIS2GEOS(geom2 );
-               g3 =    GEOSDifference(g1,g2);
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS difference() threw an error!");
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS difference() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g2);
-               GEOSdeleteGeometry(g3);
-
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-}
-
-
-//select pointonsurface('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))');
-PG_FUNCTION_INFO_V1(pointonsurface);
-Datum pointonsurface(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-               Geometry *g1,*g3;
-               GEOMETRY *result;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-               g3 =    GEOSpointonSurface(g1);
-
-       if (g3 == NULL)
-       {
-               elog(ERROR,"GEOS pointonsurface() threw an error!");
-               GEOSdeleteGeometry(g1);
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-
-//     elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
-
-       result = GEOS2POSTGIS(g3, geom1->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-               elog(ERROR,"GEOS pointonsurface() threw an error (result postgis geometry formation)!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-               GEOSdeleteGeometry(g1);
-               GEOSdeleteGeometry(g3);
-
-               compressType(result);  // convert multi* to single item if appropriate
-
-               PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(centroid);
-Datum centroid(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom, *result;
-       Geometry *geosgeom, *geosresult;
-
-       geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       geosgeom = POSTGIS2GEOS(geom);
-
-       geosresult = GEOSGetCentroid(geosgeom);
-       if ( geosresult == NULL )
-       {
-               GEOSdeleteGeometry(geosgeom);
-               elog(ERROR,"GEOS getCentroid() threw an error!");
-               PG_RETURN_NULL(); 
-       }
-
-       result = GEOS2POSTGIS(geosresult, geom->is3d);
-       if (result == NULL)
-       {
-               GEOSdeleteGeometry(geosgeom);
-               GEOSdeleteGeometry(geosresult);
-               elog(ERROR,"Error in GEOS-PGIS conversion");
-               PG_RETURN_NULL(); 
-       }
-       GEOSdeleteGeometry(geosgeom);
-       GEOSdeleteGeometry(geosresult);
-
-       PG_RETURN_POINTER(result);
-}
-
-
-
-//----------------------------------------------
-
-
-
-void errorIfGeometryCollection(GEOMETRY *g1, GEOMETRY *g2)
-{
-       if (  (g1->type == COLLECTIONTYPE) || (g2->type == COLLECTIONTYPE) )
-               elog(ERROR,"Relate Operation called with a GEOMETRYCOLLECTION type.  This is unsupported");
-}
-
-PG_FUNCTION_INFO_V1(isvalid);
-Datum isvalid(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               bool result;
-               Geometry *g1;
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-               g1 =    POSTGIS2GEOS(geom1 );
-
-               result = GEOSisvalid(g1);
-               GEOSdeleteGeometry(g1);
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS isvalid() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-// overlaps(GEOMETRY g1,GEOMETRY g2)
-// returns  if GEOS::g1->overlaps(g2) returns true
-// throws an error (elog(ERROR,...)) if GEOS throws an error
-PG_FUNCTION_INFO_V1(overlaps);
-Datum overlaps(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-       Geometry *g1,*g2;
-       bool result;
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-
-       result = GEOSrelateOverlaps(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS overlaps() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       PG_RETURN_BOOL(result);
-}
-
-
-
-PG_FUNCTION_INFO_V1(contains);
-Datum contains(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       Geometry *g1,*g2;
-       bool result;
-       //POINT3D *testpoint;
-       //POLYGON3D *poly;
-
-       errorIfGeometryCollection(geom1,geom2);
-
-       /*
-        * short-circuit 1: if geom2 bounding box is not completely inside
-        * geom1 bounding box we can prematurely return FALSE
-        */
-       if ( geom2->bvol.LLB.x < geom1->bvol.LLB.x ) PG_RETURN_BOOL(FALSE);
-       if ( geom2->bvol.URT.x > geom1->bvol.URT.x ) PG_RETURN_BOOL(FALSE);
-       if ( geom2->bvol.LLB.y < geom1->bvol.LLB.y ) PG_RETURN_BOOL(FALSE);
-       if ( geom2->bvol.URT.y > geom1->bvol.URT.y ) PG_RETURN_BOOL(FALSE);
-
-       /*
-        * short-circuit 2: if geom1 is a polygon and any corner of
-        * geom2 bounding box is not 'within' geom1 we can prematurely
-        * return FALSE
-        */
-       //if ( geom1->type == POLYGONTYPE )
-       //{
-       //      poly = (POLYGON3D *)geom1->objData;
-       //      testpoint.x = geom2->bvol.LLB.x;
-       //      testpoint.y = geom2->bvol.LLB.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom2->bvol.LLB.x;
-       //      testpoint.y = geom2->bvol.URT.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom2->bvol.URT.x;
-       //      testpoint.y = geom2->bvol.URT.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom2->bvol.URT.x;
-       //      testpoint.y = geom2->bvol.LLB.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //}
-
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-
-       result = GEOSrelateContains(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS contains() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-PG_FUNCTION_INFO_V1(within);
-Datum within(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       Geometry *g1,*g2;
-       bool result;
-       //POINT3D testpoint;
-       //POLYGON3D *poly;
-
-       errorIfGeometryCollection(geom1,geom2);
-
-
-       /*
-        * short-circuit 1: if geom1 bounding box is not completely inside
-        * geom2 bounding box we can prematurely return FALSE
-        */
-       if ( geom1->bvol.LLB.x < geom2->bvol.LLB.x ) PG_RETURN_BOOL(FALSE);
-       if ( geom1->bvol.URT.x > geom2->bvol.URT.x ) PG_RETURN_BOOL(FALSE);
-       if ( geom1->bvol.LLB.y < geom2->bvol.LLB.y ) PG_RETURN_BOOL(FALSE);
-       if ( geom1->bvol.URT.y > geom2->bvol.URT.y ) PG_RETURN_BOOL(FALSE);
-
-#if 1
-       /*
-        * short-circuit 2: if geom2 is a polygon and any corner of
-        * geom1 bounding box is not 'within' geom2 we can prematurely
-        * return FALSE
-        */
-       //if ( geom2->type == POLYGONTYPE )
-       //{
-       //      poly = (POLYGON3D *)geom2->objData;
-       //      testpoint.x = geom1->bvol.LLB.x;
-       //      testpoint.y = geom1->bvol.LLB.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom1->bvol.LLB.x;
-       //      testpoint.y = geom1->bvol.URT.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom1->bvol.URT.x;
-       //      testpoint.y = geom1->bvol.URT.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //      testpoint.x = geom1->bvol.URT.x;
-       //      testpoint.y = geom1->bvol.LLB.y;
-       //      if ( !point_within_polygon(&testpoint, poly) )
-       //              PG_RETURN_BOOL(FALSE);
-       //}
-#endif
-
-       initGEOS(MAXIMUM_ALIGNOF);
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-       result = GEOSrelateWithin(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS within() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-
-PG_FUNCTION_INFO_V1(crosses);
-Datum crosses(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-       Geometry *g1,*g2;
-       bool result;
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-
-       result = GEOSrelateCrosses(g1,g2);
-
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS crosses() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-
-PG_FUNCTION_INFO_V1(intersects);
-Datum intersects(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       Geometry *g1,*g2;
-       bool result;
-
-
-
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-
-       result = GEOSrelateIntersects(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS intersects() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-PG_FUNCTION_INFO_V1(touches);
-Datum touches(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-       Geometry *g1,*g2;
-       bool result;
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-
-       result = GEOSrelateTouches(g1,g2);
-
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS touches() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-PG_FUNCTION_INFO_V1(disjoint);
-Datum disjoint(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-       Geometry *g1,*g2;
-       bool result;
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-       result = GEOSrelateDisjoint(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS disjoin() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       PG_RETURN_BOOL(result);
-}
-
-
-PG_FUNCTION_INFO_V1(relate_pattern);
-Datum relate_pattern(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       char *patt;
-       bool result;
-
-       Geometry *g1,*g2;
-
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-       patt =  DatumGetCString(DirectFunctionCall1(textout,
-                        PointerGetDatum(PG_GETARG_DATUM(2))));
-
-       result = GEOSrelatePattern(g1,g2,patt);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-       pfree(patt);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS relate_pattern() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       PG_RETURN_BOOL(result);
-
-
-}
-
-
-
-PG_FUNCTION_INFO_V1(relate_full);
-Datum relate_full(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       Geometry *g1,*g2;
-       char    *relate_str;
-       int len;
-       char *result;
-
-//elog(NOTICE,"in relate_full()");
-
-       errorIfGeometryCollection(geom1,geom2);
-
-
-       initGEOS(MAXIMUM_ALIGNOF);
-
-//elog(NOTICE,"GEOS init()");
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-//elog(NOTICE,"constructed geometries ");
-
-
-
-
-
-if ((g1==NULL) || (g2 == NULL))
-       elog(NOTICE,"g1 or g2 are null");
-
-//elog(NOTICE,GEOSasText(g1));
-//elog(NOTICE,GEOSasText(g2));
-
-//elog(NOTICE,"valid g1 = %i", GEOSisvalid(g1));
-//elog(NOTICE,"valid g2 = %i",GEOSisvalid(g2));
-
-//elog(NOTICE,"about to relate()");
-
-
-               relate_str = GEOSrelate(g1, g2);
-
-//elog(NOTICE,"finished relate()");
-
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-
-
-       if (relate_str == NULL)
-       {
-               //free(relate_str);
-               elog(ERROR,"GEOS relate() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-
-       len = strlen(relate_str) + 4;
-
-       result= palloc(len);
-       *((int *) result) = len;
-
-       memcpy(result +4, relate_str, len-4);
-
-       free(relate_str);
-
-
-       PG_RETURN_POINTER(result);
-}
-
-//==============================
-
-PG_FUNCTION_INFO_V1(geomequals);
-Datum geomequals(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-       Geometry *g1,*g2;
-       bool result;
-
-       errorIfGeometryCollection(geom1,geom2);
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       g1 =    POSTGIS2GEOS(geom1 );
-       g2 =    POSTGIS2GEOS(geom2 );
-
-
-       result = GEOSequals(g1,g2);
-       GEOSdeleteGeometry(g1);
-       GEOSdeleteGeometry(g2);
-
-       if (result == 2)
-       {
-               elog(ERROR,"GEOS equals() threw an error!");
-               PG_RETURN_NULL(); //never get here
-       }
-
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(issimple);
-Datum issimple(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       Geometry *g1;
-       int result;
-
-       if (geom->nobjs == 0)
-               PG_RETURN_BOOL(true);
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-       //elog(NOTICE,"GEOS init()");
-
-               g1 =    POSTGIS2GEOS(geom );
-
-               result = GEOSisSimple(g1);
-               GEOSdeleteGeometry(g1);
-
-
-                       if (result == 2)
-                       {
-                               elog(ERROR,"GEOS issimple() threw an error!");
-                               PG_RETURN_NULL(); //never get here
-                       }
-
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(isring);
-Datum isring(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       Geometry *g1;
-       int result;
-
-       if (geom->type != LINETYPE)
-       {
-               elog(ERROR,"isring() should only be called on a LINE");
-       }
-
-       if (geom->nobjs == 0)
-               PG_RETURN_BOOL(false);
-
-               initGEOS(MAXIMUM_ALIGNOF);
-
-       //elog(NOTICE,"GEOS init()");
-
-               g1 =    POSTGIS2GEOS(geom );
-
-               result = GEOSisRing(g1);
-               GEOSdeleteGeometry(g1);
-
-
-                       if (result == 2)
-                       {
-                               elog(ERROR,"GEOS isring() threw an error!");
-                               PG_RETURN_NULL(); //never get here
-                       }
-
-       PG_RETURN_BOOL(result);
-}
-
-
-
-//===================================================
-
-POLYGON3D *PolyFromGeometry(Geometry *g, int *size)
-{
-
-               int ninteriorrings;
-               POINT3D *pts;
-               int             *pts_per_ring;
-               int t;
-               POLYGON3D *poly;
-               int npoints;
-
-               ninteriorrings = GEOSGetNumInteriorRings(g);
-
-               npoints =       GEOSGetNumCoordinate(g);
-               pts = GEOSGetCoordinates(g);
-               if (npoints <3)
-               {
-                       GEOSdeleteChar( (char*) pts);
-                       return NULL;
-               }
-
-               pts_per_ring = palloc(sizeof(int) *  (ninteriorrings+1));
-               pts_per_ring[0] = GEOSGetNumCoordinate(GEOSGetExteriorRing(g));
-
-               for (t=0;t<ninteriorrings;t++)
-               {
-
-                       pts_per_ring[t+1] = GEOSGetNumCoordinate(GEOSGetInteriorRingN(g,t));
-               }
-
-
-
-               poly = make_polygon( ninteriorrings+1, pts_per_ring,
-                                                       pts, GEOSGetNumCoordinate(g), size);
-
-
-
-               GEOSdeleteChar( (char*) pts);
-               pfree(pts_per_ring);
-               return poly;
-}
-
-
-
-LINE3D *LineFromGeometry(Geometry *g,int *size)
-{
-//     int t;
-               POINT3D *pts = GEOSGetCoordinates(g);
-
-               LINE3D  *line;
-               int npoints = GEOSGetNumCoordinate(g);
-
-
-               if (npoints <2)
-               {
-                       GEOSdeleteChar( (char*) pts);
-                       return NULL;
-               }
-
-               line = make_line(npoints, pts, size);
-//elog(NOTICE,"line::");
-//for (t=0;t<npoints;t++)
-//{
-//     elog(NOTICE,"point (in): %g,%g,%g",  pts[t].x,pts[t].y,pts[t].z);
-//     elog(NOTICE,"point (line): %g,%g,%g",line->points[t].x,line->points[t].y,line->points[t].z);
-//}
-               GEOSdeleteChar( (char*) pts);
-               return line;
-}
-
-
-
-
-GEOMETRY *
-GEOS2POSTGIS(Geometry *g,char want3d)
-{
-       int type = GEOSGeometryTypeId(g) ;
-       GEOMETRY *result = NULL;
-       POINT3D *pts;
-       LINE3D *line;
-       BOX3D *bbox ;
-       GEOMETRY *geom, *g2, *r;
-       POLYGON3D *poly;
-       GEOMETRY *g_new,*g_old;
-       int ngeoms,t,size;
-
-       switch (type)
-       {
-               /* From slower to faster.. compensation rule :) */
-
-               case COLLECTIONTYPE:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a COLLECTION");
-#endif
-                       //this is more difficult because GEOS allows GCs of GCs
-                       ngeoms = GEOSGetNumGeometries(g);
-                       if (ngeoms ==0)
-                       {
-                               result =  makeNullGeometry(GEOSGetSRID(g));
-                               return result;
-                       }
-                       if (ngeoms == 1)
-                       {
-                               return GEOS2POSTGIS(GEOSGetGeometryN(g,0),
-                                       want3d);  // short cut!
-                       }
-                       geom = GEOS2POSTGIS(GEOSGetGeometryN(g,0) , want3d);
-                       for (t=1;t<ngeoms;t++)
-                       {
-                               g2 = GEOS2POSTGIS(GEOSGetGeometryN(g,t),
-                                       want3d);
-                               r = geom;
-#if 1
-                               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(collector,
-                                       PointerGetDatum(r),
-                                       PointerGetDatum(g2)));
-#else
-                               geom = collector_raw(r, g2);
-#endif
-                               pfree(r);
-                               pfree(g2);
-                       }
-                       return geom;
-
-               case MULTIPOLYGONTYPE:
-                       ngeoms =        GEOSGetNumGeometries(g);
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a MULTIPOLYGON");
-#endif // DEBUG_GEOS2POSTGIS
-                       if (ngeoms ==0)
-                       {
-                               result =  makeNullGeometry(GEOSGetSRID(g));
-                               result->type = MULTIPOLYGONTYPE;
-                               return result;
-                       }
-                       for (t=0;t<ngeoms;t++)
-                       {
-                               poly = PolyFromGeometry(GEOSGetGeometryN(g,t) ,&size);
-                               if (t==0)
-                               {
-                                       result = make_oneobj_geometry(size,
-                                                               (char *) poly,
-                                                                  MULTIPOLYGONTYPE,  want3d, GEOSGetSRID(g),1.0, 0.0, 0.0
-                                                       );
-                               }
-                               else
-                               {
-                                       g_old = result;
-                                       result =        add_to_geometry(g_old,size, (char*) poly, POLYGONTYPE);
-                                       pfree(g_old);
-                               }
-                               pfree(poly);
-                       }
-                       // make bounding box
-                       bbox = bbox_of_geometry( result );
-                       // copy bounding box
-                       memcpy( &result->bvol, bbox, sizeof(BOX3D) );
-                       // free bounding box
-                       pfree( bbox );
-                       return result;
-
-               case MULTILINETYPE:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a MULTILINE");
-#endif
-                       ngeoms = GEOSGetNumGeometries(g);
-                       if (ngeoms ==0)
-                       {
-                               result =  makeNullGeometry(GEOSGetSRID(g));
-                               result->type = MULTILINETYPE;
-                               return result;
-                       }
-
-                       line = LineFromGeometry(GEOSGetGeometryN(g,0), &size);
-                       result = make_oneobj_geometry(size, (char *)line,
-                               MULTILINETYPE,  want3d,
-                               GEOSGetSRID(g),1.0, 0.0, 0.0);
-#ifdef DEBUG_GEOS2POSTGIS
-       elog(NOTICE,"GEOS2POSTGIS: t0: %s",geometry_to_text(result));
-       elog(NOTICE,"    size = %i", result->size);
-#endif
-
-                       for (t=1;t<ngeoms;t++)
-                       {
-                               line = LineFromGeometry(GEOSGetGeometryN(g,t),
-                                               &size);
-                               g_old = result;
-                               result = add_to_geometry(g_old,size,
-                                               (char*) line, LINETYPE);
-#ifdef DEBUG_GEOS2POSTGIS
-       elog(NOTICE,"GEOS2POSTGIS: t%d: %s", t, geometry_to_text(result));
-       elog(NOTICE,"    size = %i", result->size);
-#endif
-                               pfree(g_old);
-                       }
-                       bbox = bbox_of_geometry( result ); // make bounding box
-                       memcpy( &result->bvol, bbox, sizeof(BOX3D) ); // copy bounding box
-                       pfree( bbox ); // free bounding box
-#ifdef DEBUG_GEOS2POSTGIS
-       elog(NOTICE,"GEOS2POSTGIS: end: %s",geometry_to_text(result));
-       elog(NOTICE,"    size = %i", result->size);
-#endif
-
-                       return result;
-
-               case MULTIPOINTTYPE:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a MULTIPOINT");
-#endif
-                       g_new = NULL;
-                       ngeoms = GEOSGetNumGeometries(g);
-                       if (ngeoms ==0)
-                       {
-                               result =  makeNullGeometry(GEOSGetSRID(g));
-                               result->type = MULTIPOINTTYPE;
-                               return result;
-                       }
-                       pts = GEOSGetCoordinates(g);
-                       g_old = make_oneobj_geometry(sizeof(POINT3D),
-                               (char *) pts, MULTIPOINTTYPE, want3d,
-                               GEOSGetSRID(g),1.0, 0.0, 0.0);
-                       for (t=1;t<ngeoms;t++)
-                       {
-                               g_new = add_to_geometry(g_old, sizeof(POINT3D),
-                                       (char*)&pts[t], POINTTYPE);
-                               pfree(g_old);
-                               g_old =g_new;
-                       }
-                       GEOSdeleteChar( (char*) pts);
-                       // make bounding box
-                       bbox = bbox_of_geometry( g_new );
-                       // copy bounding box
-                       memcpy( &g_new->bvol, bbox, sizeof(BOX3D) );
-                       // free bounding box
-                       pfree( bbox );
-                       return g_new;
-
-               case POLYGONTYPE:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a POLYGON");
-#endif
-                       poly = PolyFromGeometry(g,&size);
-                       if (poly == NULL) return NULL;
-                       result = make_oneobj_geometry(size,
-                               (char *) poly, POLYGONTYPE, want3d,
-                               GEOSGetSRID(g),1.0, 0.0, 0.0);
-                       return result;
-
-               case LINETYPE:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a LINE");
-#endif
-                       line = LineFromGeometry(g,&size);
-                       if (line == NULL) return NULL;
-                       result = make_oneobj_geometry(size,
-                               (char *) line, LINETYPE, want3d,
-                               GEOSGetSRID(g),1.0, 0.0, 0.0);
-                       return result;
-
-               case POINTTYPE: 
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's a POINT");
-#endif
-                       pts = GEOSGetCoordinate(g);
-                       result = make_oneobj_geometry(sizeof(POINT3D),
-                               (char *) pts, POINTTYPE, want3d,
-                               GEOSGetSRID(g), 1.0, 0.0, 0.0);
-                       GEOSdeleteChar( (char*) pts);
-                       return result;
-
-               default:
-#ifdef DEBUG_GEOS2POSTGIS
-                       elog(NOTICE, "GEOS2POSTGIS: It's UNKNOWN!");
-#endif
-                       return NULL;
-
-       }
-}
-
-
-
-//BBOXONLYTYPE -> returns as a 2d polygon
-Geometry *
-POSTGIS2GEOS(GEOMETRY *g)
-{
-       POINT3D *pt;
-       LINE3D *line;
-       POLYGON3D *poly;
-       POLYGON3D **polys;
-       LINE3D **lines;
-       POINT3D **points;
-       Geometry **geoms;
-       Geometry *geos;
-       char     *obj;
-       int      obj_type;
-       int t;
-       Geometry        *result;
-
-       int32 *offsets1 = (int32 *) ( ((char *) &(g->objType[0] ))+ sizeof(int32) * g->nobjs ) ;
-
-       switch(g->type)
-       {
-               case POINTTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a POINT");
-#endif
-                       pt = (POINT3D*) ((char *) g +offsets1[0]) ;
-                       result =  PostGIS2GEOS_point(pt,g->SRID,g->is3d);
-                       if (result == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return result;
-                       break;
-
-               case LINETYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a LINE");
-#endif
-                       line = (LINE3D*) ((char *) g +offsets1[0]) ;
-                       result =  PostGIS2GEOS_linestring(line,g->SRID,g->is3d);
-                       if (result == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return result;
-                       break;
-
-               case POLYGONTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a POLYGON");
-#endif
-                       poly = (POLYGON3D*) ((char *) g +offsets1[0]) ;
-                       result =  PostGIS2GEOS_polygon(poly,g->SRID,g->is3d);
-                       if (result == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return result;
-                       break;
-
-               case MULTIPOLYGONTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a MULTIPOLYGON");
-#endif
-                       //make an array of POLYGON3Ds
-                       polys = NULL;
-                       if (g->nobjs >0)
-                               polys = (POLYGON3D**) palloc(sizeof (POLYGON3D*) * g->nobjs);
-                       for (t=0;t<g->nobjs;t++)
-                       {
-                               polys[t] =      (POLYGON3D*) ((char *) g +offsets1[t]) ;
-                       }
-                       geos= PostGIS2GEOS_multipolygon(polys, g->nobjs, g->SRID,g->is3d);
-                       if (polys != NULL) pfree(polys);
-                       if (geos == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return geos;
-                       break;
-
-               case MULTILINETYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a MULTILINE");
-#endif
-                       //make an array of LINES3D
-                       lines = NULL;
-                       if (g->nobjs >0)
-                               lines = (LINE3D**) palloc(sizeof (LINE3D*) * g->nobjs);
-                       for (t=0;t<g->nobjs;t++)
-                       {
-#ifdef DEBUG_POSTGIS2GEOS
-               elog(NOTICE, "Line %d has offset %d", t, offsets1[t]);
-#endif
-                               lines[t] = (LINE3D*) ((char *)g+offsets1[t]) ;
-                       }
-                       geos= PostGIS2GEOS_multilinestring(lines, g->nobjs, g->SRID,g->is3d);
-                       if (lines != NULL) pfree(lines);
-                       if (geos == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return geos;
-                       break;
-
-               case MULTIPOINTTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a MULTIPOINT");
-#endif
-                       //make an array of POINT3Ds
-                       points = NULL;
-                       if (g->nobjs >0)
-                               points = (POINT3D**) palloc(sizeof (POINT3D*) * g->nobjs);
-                       for (t=0;t<g->nobjs;t++)
-                       {
-                               points[t] =     (POINT3D*) ((char *) g +offsets1[t]) ;
-                       }
-                       geos= PostGIS2GEOS_multipoint(points, g->nobjs,g->SRID,g->is3d);
-                       if (points != NULL) pfree(points);
-                       if (geos == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return geos;
-                       break;
-
-               case BBOXONLYTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a BBOXONLY");
-#endif
-                       result =   PostGIS2GEOS_box3d(&g->bvol, g->SRID);
-                       if (result == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return result;
-                       break;
-
-               case COLLECTIONTYPE:
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: it's a COLLECTION");
-#endif
-                       //make an array of GEOS Geometries
-                       geoms = NULL;
-                       if (g->nobjs >0)
-                               geoms = (Geometry**) palloc(sizeof (Geometry*) * g->nobjs);
-                       for (t=0;t<g->nobjs;t++)
-                       {
-                               obj = ((char *) g +offsets1[t]);
-                               obj_type =  g->objType[t];
-                               switch (obj_type)
-                               {
-                                       case POINTTYPE:
-                                               pt = (POINT3D*) obj ;
-                                               geoms[t] = PostGIS2GEOS_point(pt,g->SRID,g->is3d);
-                                               if (geoms[t] == NULL)
-                                               {
-                                                       pfree(geoms);
-                                                       elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                                                       return NULL;
-                                               }
-                                               break;
-                                       case LINETYPE:
-                                               line = (LINE3D*) obj ;
-                                               geoms[t] = PostGIS2GEOS_linestring(line,g->SRID,g->is3d);
-                                               if (geoms[t] == NULL)
-                                               {
-                                                       pfree(geoms);
-                                                       elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                                                       return NULL;
-                                               }
-                                               break;
-                                       case POLYGONTYPE:
-                                               poly = (POLYGON3D*) obj ;
-                                               geoms[t] = PostGIS2GEOS_polygon(poly,g->SRID,g->is3d);
-                                               if (geoms[t] == NULL)
-                                               {
-                                                       pfree(geoms);
-                                                       elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                                                       return NULL;
-                                               }
-                                               break;
-                               }
-                       }
-#ifdef DEBUG_POSTGIS2GEOS
-                       elog(NOTICE, "POSTGIS2GEOS: COLLECTION has %d objs, srid %d and is %s 3d", g->nobjs, g->SRID, g->is3d ? "" : "not");
-#endif
-                       geos = PostGIS2GEOS_collection(geoms,g->nobjs,g->SRID,g->is3d);
-                       if (geoms != NULL) pfree(geoms);
-                       if (geos == NULL)
-                       {
-                               elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
-                       }
-                       return geos;
-                       break;
-
-       }
-       return NULL;
-}
-
-PG_FUNCTION_INFO_V1(GEOSnoop);
-Datum GEOSnoop(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom;
-       Geometry *geosgeom;
-       GEOMETRY *result;
-       
-       initGEOS(MAXIMUM_ALIGNOF);
-
-       geom = (GEOMETRY *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-#ifdef DEBUG_CONVERTER
-       elog(NOTICE, "GEOSnoop: IN: %s", geometry_to_text(geom));
-#endif
-
-       geosgeom = POSTGIS2GEOS(geom);
-       if ( (Pointer *)geom != (Pointer *)PG_GETARG_DATUM(0) ) pfree(geom);
-
-       result = GEOS2POSTGIS(geosgeom, geom->is3d);
-       GEOSdeleteGeometry(geosgeom);
-
-#ifdef DEBUG_CONVERTER
-       elog(NOTICE, "GEOSnoop: OUT: %s", geometry_to_text(result));
-#endif
-
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(postgis_geos_version);
-Datum postgis_geos_version(PG_FUNCTION_ARGS)
-{
-       char *ver = GEOSversion();
-       text *result;
-       result = (text *) palloc(VARHDRSZ  + strlen(ver));
-       VARATT_SIZEP(result) = VARHDRSZ + strlen(ver) ;
-       memcpy(VARDATA(result), ver, strlen(ver));
-       free(ver);
-       PG_RETURN_POINTER(result);
-}
-
-//----------------------------------------------------------------------------
-// NULL implementation here
-// ---------------------------------------------------------------------------
-#else // ndef USE_GEOS
-
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "fmgr.h"
-
-
-Datum relate_full(PG_FUNCTION_ARGS);
-Datum relate_pattern(PG_FUNCTION_ARGS);
-Datum disjoint(PG_FUNCTION_ARGS);
-Datum touches(PG_FUNCTION_ARGS);
-Datum intersects(PG_FUNCTION_ARGS);
-Datum crosses(PG_FUNCTION_ARGS);
-Datum within(PG_FUNCTION_ARGS);
-Datum contains(PG_FUNCTION_ARGS);
-Datum overlaps(PG_FUNCTION_ARGS);
-Datum isvalid(PG_FUNCTION_ARGS);
-
-
-Datum buffer(PG_FUNCTION_ARGS);
-Datum intersection(PG_FUNCTION_ARGS);
-Datum convexhull(PG_FUNCTION_ARGS);
-Datum difference(PG_FUNCTION_ARGS);
-Datum boundary(PG_FUNCTION_ARGS);
-Datum symdifference(PG_FUNCTION_ARGS);
-Datum geomunion(PG_FUNCTION_ARGS);
-
-PG_FUNCTION_INFO_V1(intersection);
-Datum intersection(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"intersection:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(convexhull);
-Datum convexhull(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"convexhull:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(difference);
-Datum difference(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"difference:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(boundary);
-Datum boundary(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"boundary:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(symdifference);
-Datum symdifference(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"symdifference:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(geomunion);
-Datum geomunion(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"geomunion:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-PG_FUNCTION_INFO_V1(buffer);
-Datum buffer(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"buffer:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-
-
-PG_FUNCTION_INFO_V1(relate_full);
-Datum relate_full(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"relate_full:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(relate_pattern);
-Datum relate_pattern(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"relate_pattern:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(disjoint);
-Datum disjoint(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"disjoint:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(intersects);
-Datum intersects(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"intersects:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(touches);
-Datum touches(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"touches:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(crosses);
-Datum crosses(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"crosses:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(within);
-Datum within(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"within:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(contains);
-Datum contains(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"contains:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(overlaps);
-Datum overlaps(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"overlaps:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(isvalid);
-Datum isvalid(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"isvalid:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-PG_FUNCTION_INFO_V1(issimple);
-Datum issimple(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"issimple:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(geomequals);
-Datum geomequals(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"geomequals:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-PG_FUNCTION_INFO_V1(isring);
-Datum isring(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"isring:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-PG_FUNCTION_INFO_V1(pointonsurface);
-Datum pointonsurface(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"pointonsurface:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-PG_FUNCTION_INFO_V1(unite_garray);
-Datum unite_garray(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"unite_garray:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL(); // never get here
-}
-
-PG_FUNCTION_INFO_V1(GEOSnoop);
-Datum GEOSnoop(PG_FUNCTION_ARGS)
-{
-       elog(ERROR,"GEOSnoop:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL();
-}
-
-PG_FUNCTION_INFO_V1(postgis_geos_version);
-Datum postgis_geos_version(PG_FUNCTION_ARGS)
-{
-       //elog(ERROR,"GEOSversion:: operation not implemented - compile PostGIS with GEOS support");
-       PG_RETURN_NULL();
-}
-
-#endif
-
diff --git a/hwgeom/postgis_geos_wrapper.cpp b/hwgeom/postgis_geos_wrapper.cpp
deleted file mode 100644 (file)
index 49e3558..0000000
+++ /dev/null
@@ -1,1551 +0,0 @@
-//  g++ postgis_GEOSwrapper.cpp -c -I/usr/local/include  -I/usr/local/include/geos -I/usr/local/src/postgresql-7.2.3//src/include
-
-/*
-* $Log$
-* Revision 1.1  2004/09/20 07:50:06  strk
-* prepared to contain old internal representation code
-*
-* Revision 1.27  2004/07/22 16:58:08  strk
-* Updated to reflect geos version string split.
-*
-* Revision 1.26  2004/07/22 16:20:10  strk
-* Added postgis_lib_version() and postgis_geos_version()
-*
-* Revision 1.25  2004/07/17 09:52:48  strk
-* GEOS multi-version support switches implemented with GEOS_LAST_INTERFACE
-*
-* Revision 1.24  2004/07/08 19:33:51  strk
-* Updated to respect CoordinateSequence GEOS interface switch.
-*
-* Revision 1.23  2004/07/02 13:33:23  strk
-* Changed GEOS header inclusion mechanism to be more polite
-*
-* Revision 1.22  2004/07/01 17:02:26  strk
-* Updated to support latest GEOS API.
-*
-* Revision 1.21  2004/06/16 19:59:36  strk
-* Changed GEOS_VERSION to POSTGIS_GEOS_VERSION to avoid future clashes
-*
-* Revision 1.20  2004/06/16 19:37:54  strk
-* Added cleanup needed for GEOS > 1.0
-*
-* Revision 1.19  2004/06/16 18:47:59  strk
-* Added code to detect geos version.
-* Added appropriate includes in geos connectors.
-*
-* Revision 1.18  2004/04/27 07:44:26  strk
-* Removed use of geometryFactory->toGeometry(), indicated by Martin Davis
-* as being intended for internal use only. Created a linear ring instead
-* (the function converts a box3d to a geos geometry).
-*
-* Revision 1.17  2003/12/12 13:34:20  strk
-* added missing 'const' in prototypes
-*
-* Revision 1.16  2003/12/12 12:03:30  strk
-* More debugging output, some code cleanup.
-*
-* Revision 1.15  2003/11/12 16:36:04  strk
-* delete all caught exceptions after use
-*
-* Revision 1.14  2003/10/29 13:58:28  strk
-* Added GEOSGetCentroid() function
-*
-* Revision 1.13  2003/10/24 21:33:21  strk
-* Added GEOSGeometryTypeId(Geometry *) wrapper function.
-* Added GEOSGetCoordinates_Polygon(Polygon *) as an experimental optimized
-* version of GEOSGetCoordinates(Geometry *); More to add ...
-*
-* Revision 1.12  2003/10/24 14:29:53  strk
-* GEOSGetCoordinates() reverted to getCoordinates() call so to be compatible
-* to all type of geometries (not only LineStrings)
-*
-* Revision 1.11  2003/10/24 08:28:50  strk
-* Fixed memory leak in GEOSGetCoordinates(), made sure that GEOS2POSTGIS
-* free type string even in case of collapsed geoms. Made sure that geomunion
-* release memory in case of exception thrown by GEOSUnion. Sooner release
-* of palloced memory in PolyFromGeometry (pts_per_ring).
-*
-* Revision 1.10  2003/10/20 19:50:49  strk
-* Removed some memory leaks in PostGIS2* converters.
-*
-*/
-
-
-#include <stdio.h>
-
-#include <string>
-#include <iostream>
-#include <fstream>
-
-#include "postgis_geos_version.h"
-#include "geos/geom.h"
-#include "geos/util.h"
-
-using namespace geos;
-
-//WARNING THIS *MUST* BE SET CORRECTLY.
-int MAXIMUM_ALIGNOF = -999999;    // to be set during initialization - this will be either 4 (intel) or 8 (sparc)
-
-//for getting things to align properly  double are on 8byte align on solaris machines, and 4bytes on intel
-
-#define TYPEALIGN(ALIGNVAL,LEN) (((long)(LEN) + (ALIGNVAL-1)) & ~(ALIGNVAL-1))
-#define MAXALIGN(LEN)           TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
-
-typedef  int int32;
-
-typedef struct
-{
-       double          x,y,z;  //for lat/long   x=long, y=lat
-} POINT3D;
-
-typedef struct
-{
-       POINT3D         LLB,URT; /* corner POINT3Ds on long diagonal */
-} BOX3D;
-
-typedef struct
-{
-       int32   npoints; // how many points in the line
-       int32   junk;      // double-word alignment
-       POINT3D         points[1]; // array of actual points
-} LINE3D;
-
-
-typedef struct
-{
-       int32   nrings;  // how many rings in this polygon
-       int32           npoints[1]; //how many points in each ring
-       /* could be 4 byes of filler here to make sure points[] is
-         double-word aligned*/
-       POINT3D         points[1]; // array of actual points
-} POLYGON3D;
-
-
-#define        POINTTYPE       1
-#define        LINETYPE        2
-#define        POLYGONTYPE     3
-#define        MULTIPOINTTYPE  4
-#define        MULTILINETYPE   5
-#define        MULTIPOLYGONTYPE        6
-#define        COLLECTIONTYPE  7
-
-//###########################################################
-
-extern "C" char *GEOSrelate(Geometry *g1, Geometry*g2);
-extern "C" void initGEOS(int maxalign);
-
-
-extern "C" void GEOSdeleteChar(char *a);
-extern "C" void GEOSdeleteGeometry(Geometry *a);
-extern "C" char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat);
-extern "C" char GEOSrelateDisjoint(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateTouches(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateIntersects(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateCrosses(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateWithin(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateContains(Geometry *g1, Geometry*g2);
-extern "C" char GEOSrelateOverlaps(Geometry *g1, Geometry*g2);
-extern "C" char *GEOSversion();
-extern "C" char *GEOSjtsport();
-
-extern "C" Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d);
-extern "C" Geometry *PostGIS2GEOS_linestring(const LINE3D *line,int SRID, bool is3d);
-extern "C" Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d);
-extern "C" Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d);
-extern "C" Geometry *PostGIS2GEOS_multilinestring(const LINE3D **lines,int nlines, int SRID, bool is3d);
-extern "C" Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d);
-
-extern "C" Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID);
-extern "C" Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d);
-
-extern "C" char GEOSisvalid(Geometry *g1);
-
-
-extern "C" char *GEOSasText(Geometry *g1);
-extern "C" char GEOSisEmpty(Geometry *g1);
-extern "C" char *GEOSGeometryType(Geometry *g1);
-extern "C" int GEOSGeometryTypeId(Geometry *g1);
-
-
-extern "C" char *throw_exception(Geometry *g);
-
-extern "C" Geometry *GEOSIntersection(Geometry *g1,Geometry *g1);
-extern "C" Geometry *GEOSBuffer(Geometry *g1,double width);
-extern "C" Geometry *GEOSConvexHull(Geometry *g1);
-extern "C" Geometry *GEOSDifference(Geometry *g1,Geometry *g2);
-extern "C" Geometry *GEOSBoundary(Geometry *g1);
-extern "C" Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2);
-extern "C" Geometry *GEOSUnion(Geometry *g1,Geometry *g2);
-
-
-extern "C" POINT3D  *GEOSGetCoordinate(Geometry *g1);
-extern "C" POINT3D  *GEOSGetCoordinates_Polygon(Polygon *g1);
-extern "C" POINT3D  *GEOSGetCoordinates(Geometry *g1);
-extern "C" int      GEOSGetNumCoordinate(Geometry *g1);
-extern "C" const Geometry *GEOSGetGeometryN(Geometry *g1, int n);
-extern "C" const Geometry *GEOSGetExteriorRing(Geometry *g1);
-extern "C" const Geometry *GEOSGetInteriorRingN(Geometry *g1, int n);
-extern "C" int      GEOSGetNumInteriorRings(Geometry *g1);
-extern "C" int      GEOSGetSRID(Geometry *g1);
-extern "C" int      GEOSGetNumGeometries(Geometry *g1);
-
-extern "C" char GEOSisSimple(Geometry *g1);
-extern "C" char GEOSequals(Geometry *g1, Geometry*g2);
-
-extern "C" char GEOSisRing(Geometry *g1);
-
-extern "C" Geometry *GEOSpointonSurface(Geometry *g1);
-
-extern "C" Geometry *GEOSGetCentroid(Geometry *g1);
-
-extern "C" void NOTICE_MESSAGE(char *msg);
-
-
-
-//###########################################################
-#if GEOS_LAST_INTERFACE < 2
-# define CoordinateSequence CoordinateList
-# define DefaultCoordinateSequence BasicCoordinateList
-#endif
-
-GeometryFactory *geomFactory = NULL;
-
-
-void initGEOS (int maxalign)
-{
-       if (geomFactory == NULL)
-       {
-               geomFactory = new GeometryFactory( new PrecisionModel(), -1); // NOTE: SRID will have to be changed after geometry creation
-               MAXIMUM_ALIGNOF = maxalign;
-       }
-}
-
-// ------------------------------------------------------------------------------
-// geometry constuctors - return NULL if there was an error
-//-------------------------------------------------------------------------------
-
-
-
-               //note: you lose the 3d from this!
-Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID)
-{
-       DefaultCoordinateSequence  *cl = new DefaultCoordinateSequence(5);
-       try {
-               Geometry *g;
-               Coordinate c;
-               c.x = box->LLB.x; c.y = box->LLB.y;
-               cl->setAt(c, 0);
-               c.x = box->LLB.x; c.y = box->URT.y;
-               cl->setAt(c, 1);
-               c.x = box->URT.x; c.y = box->URT.y;
-               cl->setAt(c, 2);
-               c.x = box->URT.x; c.y = box->LLB.y;
-               cl->setAt(c, 3);
-               c.x = box->LLB.x; c.y = box->LLB.y;
-               cl->setAt(c, 4);
-
-               g = geomFactory->createLinearRing(cl);
-#if GEOS_LAST_INTERFACE < 2
-               delete cl;
-#endif
-               if (g==NULL) return NULL;
-               g->setSRID(SRID);
-               return g;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete cl;
-               return NULL;
-       }
-       catch (...)
-       {
-               delete cl;
-               return NULL;
-       }
-}
-
-Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms,int SRID, bool is3d)
-{
-       try
-       {
-               Geometry *g;
-               int t;
-               vector<Geometry *> *subGeos=new vector<Geometry *>;
-
-               for (t =0; t< ngeoms; t++)
-               {
-                       subGeos->push_back(geoms[t]);
-               }
-               g = geomFactory->buildGeometry(subGeos);
-#if GEOS_LAST_INTERFACE < 2
-               delete subGeos;
-#endif
-               if (g==NULL)
-                       return NULL;
-               g->setSRID(SRID);
-               return g;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *PostGIS2GEOS_point(POINT3D *point,int SRID, bool is3d)
-{
-       try
-       {
-                       Coordinate *c;
-
-                       if (is3d)
-                               c = new Coordinate(point->x, point->y);
-                       else
-                               c = new Coordinate(point->x, point->y, point->z);
-                       Geometry *g = geomFactory->createPoint(*c);
-                       delete c;
-                       if (g==NULL)
-                               return NULL;
-                       g->setSRID(SRID);
-                       return g;
-               }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-
-/*
- * This function must return an all-new allocated object
- */
-Geometry *
-PostGIS2GEOS_linestring(const LINE3D *line,int SRID, bool is3d)
-{
-       try{
-               int t;
-               Coordinate c;
-
-               //build coordinatelist & pre-allocate space
-               DefaultCoordinateSequence  *coords = new DefaultCoordinateSequence(line->npoints);
-               if (is3d)
-               {
-                       for (t=0;t<line->npoints;t++)
-                       {
-                               c.x = line->points[t].x;
-                               c.y = line->points[t].y;
-                               c.z = line->points[t].z;
-                               coords->setAt( c ,t);
-                       }
-               }
-               else  //make 2d points
-               {
-                       for (t=0;t<line->npoints;t++)
-                       {
-                               c.x = line->points[t].x;
-                               c.y = line->points[t].y;
-                               c.z = DoubleNotANumber;
-                               coords->setAt( c ,t);
-                       }
-               }
-               Geometry *g = geomFactory->createLineString(coords);
-#if GEOS_LAST_INTERFACE < 2
-               delete coords;
-#endif
-               if (g==NULL) return NULL;
-               g->setSRID(SRID);
-               return g;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-//polygons is an array of pointers to polygons
-Geometry *PostGIS2GEOS_multipolygon(POLYGON3D **polygons,int npolys, int SRID, bool is3d)
-{
-       try
-       {
-                       int t;
-                       vector<Geometry *> *subPolys=NULL;
-                       Geometry *g;
-
-                       subPolys=new vector<Geometry *>;
-
-                       for (t =0; t< npolys; t++)
-                       {
-                               subPolys->push_back(PostGIS2GEOS_polygon(polygons[t], SRID,is3d ));
-                       }
-                       g = geomFactory->createMultiPolygon(subPolys);
-#if GEOS_LAST_INTERFACE < 2
-                       delete subPolys;
-#endif
-
-                       if (g== NULL)
-                               return NULL;
-                       g->setSRID(SRID);
-                       return g;
-               }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-//lines is an array of pointers to line3d
-Geometry *
-PostGIS2GEOS_multilinestring(const LINE3D **lines, int nlines, int SRID, bool is3d)
-{
-       try
-       {
-               int t;
-               vector<Geometry *> *subLines = new vector<Geometry *>;
-               Geometry *g;
-
-               for (t =0; t< nlines; t++)
-               {
-                       subLines->push_back(PostGIS2GEOS_linestring(lines[t],
-                                               SRID,is3d ));
-               }
-               g = geomFactory->createMultiLineString(subLines);
-#if GEOS_LAST_INTERFACE < 2
-               delete subLines;
-#endif
-               if (g==NULL) return NULL;
-               g->setSRID(SRID);
-               return g;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *PostGIS2GEOS_multipoint(POINT3D **points,int npoints, int SRID, bool is3d)
-{
-       try
-       {
-                       int t;
-                       vector<Geometry *> *subPoints =new vector<Geometry *>;
-                       Geometry *g;
-
-                       for (t =0; t< npoints; t++)
-                       {
-                               subPoints->push_back(PostGIS2GEOS_point(points[t], SRID,is3d ));
-                       }
-                       g = geomFactory->createMultiPoint(subPoints);
-#if GEOS_LAST_INTERFACE < 2
-                       delete subPoints;
-#endif
-                       if (g==NULL)
-                               return NULL;
-                       g->setSRID(SRID);
-                       return g;
-               }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-
-}
-
-
-Geometry *PostGIS2GEOS_polygon(POLYGON3D *polygon,int SRID, bool is3d)
-{
-       try
-       {
-               POINT3D *pts;
-               Coordinate c;
-               int  ring,t;
-               Geometry *g;
-               LinearRing *outerRing;
-               LinearRing *innerRing;
-               DefaultCoordinateSequence *cl;
-               int pointOffset =0; // first point that we're looking at.  a POLYGON3D has all its points smooshed together
-               vector<Geometry *> *innerRings=new vector<Geometry *>;
-
-
-               pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] )  );
-               pts = (POINT3D *) MAXALIGN(pts);
-
-                       // make outerRing
-                       cl = new DefaultCoordinateSequence(polygon->npoints[0]);
-                       if (is3d)
-                       {
-                               for(t=0;t<polygon->npoints[0];t++)
-                               {
-                                               c.x = pts[t].x;
-                                               c.y = pts[t].y;
-                                               c.z = pts[t].z;
-                                               cl->setAt( c ,t);
-                               }
-                       }
-                       else
-                       {
-                               for(t=0;t<polygon->npoints[0];t++)
-                               {
-                                               c.x = pts[t].x;
-                                               c.y = pts[t].y;
-                                               c.z = DoubleNotANumber;
-                                               cl->setAt( c ,t);
-                               }
-                       }
-                       outerRing = (LinearRing*) geomFactory->createLinearRing(cl);
-#if GEOS_LAST_INTERFACE < 2
-                       delete cl;
-#endif
-                       if (outerRing == NULL)
-                               return NULL;
-                       outerRing->setSRID(SRID);
-                       pointOffset = polygon->npoints[0];
-
-               for(ring =1; ring< polygon->nrings; ring++)
-               {
-                       cl = new DefaultCoordinateSequence(polygon->npoints[ring]);
-                       if (is3d)
-                       {
-                               for(t=0;t<polygon->npoints[ring];t++)
-                               {
-                                               c.x = pts[t+pointOffset].x;
-                                               c.y = pts[t+pointOffset].y;
-                                               c.z = pts[t+pointOffset].z;
-                                               cl->setAt( c ,t);
-                               }
-                       }
-                       else
-                       {
-                               for(t=0;t<polygon->npoints[ring];t++)
-                               {
-                                               c.x = pts[t+pointOffset].x;
-                                               c.y = pts[t+pointOffset].y;
-                                               c.z = DoubleNotANumber;
-                                               cl->setAt( c ,t);
-                               }
-                       }
-                       innerRing = (LinearRing *) geomFactory->createLinearRing(cl);
-#if GEOS_LAST_INTERFACE < 2
-                       delete cl;
-#endif
-                       if (innerRing == NULL)
-                       {
-                               delete outerRing;
-                               return NULL;
-                       }
-                       innerRing->setSRID(SRID);
-                       innerRings->push_back(innerRing);
-                       pointOffset += polygon->npoints[ring];
-               }
-
-               g = geomFactory->createPolygon(outerRing, innerRings);
-               if (g==NULL)
-                       return NULL;
-               g->setSRID(SRID);
-               return g;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-//-----------------------------------------------------------
-// relate()-related functions
-//  return 0 = false, 1 = true, 2 = error occured
-//-----------------------------------------------------------
-
-char GEOSrelateDisjoint(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->disjoint(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSrelateTouches(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result =  g1->touches(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSrelateIntersects(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->intersects(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSrelateCrosses(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->crosses(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSrelateWithin(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->within(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-// call g1->contains(g2)
-// returns 0 = false
-//         1 = true
-//         2 = error was trapped
-char GEOSrelateContains(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->contains(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSrelateOverlaps(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->overlaps(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-
-//-------------------------------------------------------------------
-// low-level relate functions
-//------------------------------------------------------------------
-
-char GEOSrelatePattern(Geometry *g1, Geometry*g2,char *pat)
-{
-       try {
-               bool result;
-               string s = pat;
-               result = g1->relate(g2,pat);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char *GEOSrelate(Geometry *g1, Geometry*g2)
-{
-
-       try {
-
-               IntersectionMatrix *im = g1->relate(g2);
-
-               string s;
-               char *result;
-               if (im == NULL)
-                               return NULL;
-
-               s= im->toString();
-               result = (char*) malloc( s.length() + 1);
-               strcpy(result, s.c_str() );
-
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-
-
-//-----------------------------------------------------------------
-// isValid
-//-----------------------------------------------------------------
-
-
-char GEOSisvalid(Geometry *g1)
-{
-       try {
-               bool result;
-               result =g1->isValid();
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-
-}
-
-
-//-----------------------------------------------------------------
-// general purpose
-//-----------------------------------------------------------------
-
-char GEOSequals(Geometry *g1, Geometry*g2)
-{
-       try {
-               bool result;
-               result = g1->equals(g2);
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-
-
-char *GEOSasText(Geometry *g1)
-{
-       try
-       {
-               string s = g1->toString();
-
-
-               char *result;
-               result = (char*) malloc( s.length() + 1);
-               strcpy(result, s.c_str() );
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-char GEOSisEmpty(Geometry *g1)
-{
-       try
-       {
-               return g1->isEmpty();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSisSimple(Geometry *g1)
-{
-       try
-       {
-               return g1->isSimple();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-char GEOSisRing(Geometry *g1)
-{
-       try
-       {
-               return (( (LinearRing*)g1)->isRing());
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 2;
-       }
-
-       catch (...)
-       {
-               return 2;
-       }
-}
-
-
-
-//free the result of this
-char *GEOSGeometryType(Geometry *g1)
-{
-       try
-       {
-               string s = g1->getGeometryType();
-
-
-               char *result;
-               result = (char*) malloc( s.length() + 1);
-               strcpy(result, s.c_str() );
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-// Return postgis geometry type index
-int GEOSGeometryTypeId(Geometry *g1)
-{
-       try
-       {
-               GeometryTypeId id = g1->getGeometryTypeId();
-               switch (id)
-               {
-                       case GEOS_POINT:
-                               return POINTTYPE;
-                       case GEOS_LINESTRING:
-                               return LINETYPE;
-                       case GEOS_POLYGON:
-                               return POLYGONTYPE;
-                       case GEOS_MULTIPOINT:
-                               return MULTIPOINTTYPE;
-                       case GEOS_MULTILINESTRING:
-                               return MULTILINETYPE;
-                       case GEOS_MULTIPOLYGON:
-                               return MULTIPOLYGONTYPE;
-                       case GEOS_GEOMETRYCOLLECTION:
-                               return COLLECTIONTYPE;
-                       default:
-                               return 0;
-               }
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return -1;
-       }
-
-       catch (...)
-       {
-               return -1;
-       }
-}
-
-
-
-
-//-------------------------------------------------------------------
-// GEOS functions that return geometries
-//-------------------------------------------------------------------
-
-Geometry *GEOSIntersection(Geometry *g1,Geometry *g2)
-{
-       try
-       {
-               Geometry *g3 = g1->intersection(g2);
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSBuffer(Geometry *g1,double width)
-{
-       try
-       {
-               Geometry *g3 = g1->buffer(width);
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSConvexHull(Geometry *g1)
-{
-       try
-       {
-               Geometry *g3 = g1->convexHull();
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSDifference(Geometry *g1,Geometry *g2)
-{
-       try
-       {
-               Geometry *g3 = g1->difference(g2);
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSBoundary(Geometry *g1)
-{
-       try
-       {
-               Geometry *g3 = g1->getBoundary();
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2)
-{
-       try
-       {
-               Geometry *g3 = g1->symDifference(g2);
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSUnion(Geometry *g1,Geometry *g2)
-{
-       try
-       {
-               Geometry *g3 = g1->Union(g2);
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-
-Geometry *GEOSpointonSurface(Geometry *g1)
-{
-       try
-       {
-               Geometry *g3 = g1->getInteriorPoint();
-               return g3;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch (...)
-       {
-               return NULL;
-       }
-}
-
-
-
-
-
-//-------------------------------------------------------------------
-// memory management functions
-//------------------------------------------------------------------
-
-
-//BUG:: this leaks memory, but delete kills the PrecisionModel for ALL the geometries
-void GEOSdeleteGeometry(Geometry *a)
-{
-       try{
-               delete a;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               //return NULL;
-       }
-
-       catch(...)
-       {
-               // do nothing!
-       }
-}
-
-void GEOSdeleteChar(char *a)
-{
-       try{
-          free(a);
-       }
-       catch (GEOSException *ge) // ???
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               //return NULL;
-       }
-
-       catch(...)
-       {
-               // do nothing!
-       }
-}
-
-
-//-------------------------------------------------------------------
-//GEOS => POSTGIS conversions
-//-------------------------------------------------------------------
-
-
-// free the result when done!
-// g1 must be a point
-POINT3D  *GEOSGetCoordinate(Geometry *g1)
-{
-       try{
-               POINT3D         *result = (POINT3D*) malloc (sizeof(POINT3D));
-               const Coordinate *c =g1->getCoordinate();
-
-               result->x = c->x;
-               result->y = c->y;
-               result->z = c->z;
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-
-}
-
-
-//must free the result when done
-// result is an array length g1->getNumCoordinates()
-POINT3D  *GEOSGetCoordinates(Geometry *g1)
-{
-       if ( g1->getGeometryTypeId() == GEOS_POLYGON )
-       {
-               return GEOSGetCoordinates_Polygon((Polygon *)g1);
-       }
-
-       try {
-               int numPoints = g1->getNumPoints();
-               POINT3D *result = (POINT3D*) malloc (sizeof(POINT3D) * numPoints );
-               int t;
-               CoordinateSequence *cl = g1->getCoordinates();
-               Coordinate              c;
-
-               for (t=0;t<numPoints;t++)
-               {
-                       c =cl->getAt(t);
-
-                       result[t].x = c.x;
-                       result[t].y = c.y;
-                       result[t].z = c.z;
-               }
-
-               delete cl;
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-
-}
-
-// A somewhat optimized version for polygon types.
-POINT3D  *GEOSGetCoordinates_Polygon(Polygon *g1)
-{
-       try {
-               int t, r, outidx=0;
-               const CoordinateSequence *cl;
-               Coordinate c;
-               const LineString *lr;
-               int npts, nrings;
-               POINT3D *result;
-               
-               npts = g1->getNumPoints();
-               result = (POINT3D*) malloc (sizeof(POINT3D) * npts);
-               
-               // Exterior ring 
-               lr = g1->getExteriorRing();
-               cl = lr->getCoordinatesRO();
-               npts = lr->getNumPoints();
-               for (t=0; t<npts; t++)
-               {
-                       c = cl->getAt(t);
-
-                       result[outidx].x = c.x;
-                       result[outidx].y = c.y;
-                       result[outidx].z = c.z;
-                       outidx++;
-               }
-
-               // Interior rings
-               nrings = g1->getNumInteriorRing();
-               for (r=0; r<nrings; r++)
-               {
-                       lr = g1->getInteriorRingN(r);
-                       cl = lr->getCoordinatesRO();
-                       npts = lr->getNumPoints();
-                       for (t=0; t<npts; t++)
-                       {
-                               c = cl->getAt(t);
-                               result[outidx].x = c.x;
-                               result[outidx].y = c.y;
-                               result[outidx].z = c.z;
-                               outidx++;
-                       }
-               }
-
-               return result;
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-
-}
-
-
-
-
-int      GEOSGetNumCoordinate(Geometry *g1)
-{
-       try{
-               return g1->getNumPoints();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 0;
-       }
-
-       catch(...)
-       {
-               return 0;
-       }
-}
-
-int      GEOSGetNumInteriorRings(Geometry *g1)
-{
-       try{
-               Polygon *p = (Polygon *) g1;
-               return p->getNumInteriorRing();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 0;
-       }
-
-       catch(...)
-       {
-               return 0;
-       }
-}
-
-
-//only call on GCs (or multi*)
-int      GEOSGetNumGeometries(Geometry *g1)
-{
-       try{
-               GeometryCollection *gc = (GeometryCollection *) g1;
-               return gc->getNumGeometries();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 0;
-       }
-
-       catch(...)
-       {
-               return 0;
-       }
-}
-
-
-//call only on GEOMETRYCOLLECTION or MULTI*
-const Geometry *GEOSGetGeometryN(Geometry *g1, int n)
-{
-       try{
-               const GeometryCollection *gc = (GeometryCollection *) g1;
-               return gc->getGeometryN(n);
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-}
-
-
-//call only on polygon
-const Geometry *GEOSGetExteriorRing(Geometry *g1)
-{
-       try{
-               Polygon *p = (Polygon *) g1;
-               return p->getExteriorRing();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 0;
-       }
-
-       catch(...)
-       {
-               return 0;
-       }
-}
-
-//call only on polygon
-const Geometry *GEOSGetInteriorRingN(Geometry *g1,int n)
-{
-       try{
-               Polygon *p = (Polygon *) g1;
-               return p->getInteriorRingN(n);
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-}
-
-Geometry *GEOSGetCentroid(Geometry *g)
-{
-       try{
-               return g->getCentroid();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return NULL;
-       }
-
-       catch(...)
-       {
-               return NULL;
-       }
-}
-
-
-int      GEOSGetSRID(Geometry *g1)
-{
-       try{
-               return g1->getSRID();
-       }
-       catch (GEOSException *ge)
-       {
-               NOTICE_MESSAGE((char *)ge->toString().c_str());
-               delete ge;
-               return 0;
-       }
-
-       catch(...)
-       {
-               return 0;
-       }
-}
-
-char *
-GEOSversion()
-{
-#if GEOS_LAST_INTERFACE < 2
-       /*
-        * GEOS upgrade needs postgis re-build, so this static
-        * assignment is not going to be a problem
-        */
-       char *res = strdup("1.0.0");
-#else
-       string version = geosversion();
-       char *res = strdup(version.c_str());
-#endif
-       return res;
-}
-
-char *
-GEOSjtsport()
-{
-#if GEOS_LAST_INTERFACE < 2
-       /*
-        * GEOS upgrade needs postgis re-build, so this static
-        * assignment is not going to be a problem
-        */
-       char *res = strdup("1.3");
-#else
-       string version = jtsport();
-       char *res = strdup(version.c_str());
-#endif
-       return res;
-}
-
-
diff --git a/hwgeom/postgis_gist_71.c b/hwgeom/postgis_gist_71.c
deleted file mode 100644 (file)
index b2391b2..0000000
+++ /dev/null
@@ -1,599 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.4  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.3  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.2  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-//Norman Vine found this problem for compiling under cygwin
-//  it defines BYTE_ORDER and LITTLE_ENDIAN
-
-#ifdef __CYGWIN__
-#include <sys/param.h>       // FOR ENDIAN DEFINES
-#endif
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-// #define DEBUG_GIST
-
-
-//for GIST index
-typedef char* (*BINARY_UNION)(char*, char*, int*);
-typedef float (*SIZE_BOX)(char*);
-typedef Datum (*RDF)(PG_FUNCTION_ARGS);
-
-GISTENTRY *ggeometry_compress(PG_FUNCTION_ARGS);
-GEOMETRYKEY *ggeometry_union(PG_FUNCTION_ARGS);
-GIST_SPLITVEC * ggeometry_picksplit(PG_FUNCTION_ARGS);
-bool ggeometry_consistent(PG_FUNCTION_ARGS);
-float * ggeometry_penalty(PG_FUNCTION_ARGS);
-bool * ggeometry_same(PG_FUNCTION_ARGS);
-
-char * ggeometry_binary_union(char *r1, char *r2, int *sizep);
-float size_geometrykey( char *pk );
-
-Datum ggeometry_inter(PG_FUNCTION_ARGS);
-
-/*
-** Common rtree-function (for all ops)
-*/
-char * rtree_union(bytea *entryvec, int *sizep, BINARY_UNION bu);
-float * rtree_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result, BINARY_UNION bu, SIZE_BOX sb);
-GIST_SPLITVEC * rtree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, int keylen, BINARY_UNION bu, RDF interop, SIZE_BOX sb);
-bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy);
-
-
-GISTENTRY *rtree_decompress(PG_FUNCTION_ARGS);
-
-
-//restriction in the GiST && operator
-
-Datum postgis_gist_sel(PG_FUNCTION_ARGS)
-{
-        PG_RETURN_FLOAT8(0.000005);
-}
-
-
-BOX    *convert_box3d_to_box(BOX3D *in)
-{
-               BOX     *out = palloc (sizeof (BOX) );
-
-               out->high.x = in->URT.x;
-               out->high.y = in->URT.y;
-
-               out->low.x = in->LLB.x;
-               out->low.y = in->LLB.y;
-
-       return out;
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_compress);
-GISTENTRY *ggeometry_compress(PG_FUNCTION_ARGS)
-{
-       GISTENTRY *entry=(GISTENTRY*)PG_GETARG_POINTER(0);
-       GISTENTRY *retval;
-
-       if ( entry->leafkey) {
-               retval = palloc(sizeof(GISTENTRY));
-               if ( entry->pred ) {
-
-                       GEOMETRY *in;
-                       GEOMETRYKEY *r;
-                       BOX     *thebox;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_compress called on geometry\n");
-#endif
-
-                       in = (GEOMETRY*)PG_DETOAST_DATUM(PointerGetDatum(entry->pred));
-
-       if (in->nobjs ==0)  // this is the EMPTY geometry
-       {
-                       //elog(NOTICE,"found an empty geometry");
-                       // dont bother adding this to the index
-                       PG_RETURN_POINTER(entry);
-       }
-
-                       r = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
-                       r->size = sizeof(GEOMETRYKEY);
-                       r->SRID = in->SRID;
-                       thebox = convert_box3d_to_box(&in->bvol);
-                       memcpy( (void*)&(r->key), (void*)thebox, sizeof(BOX) );
-                       if ( (char*)in != entry->pred )
-                       {
-                               pfree( in );
-                               pfree(thebox);
-                       }
-
-                       gistentryinit(*retval, (char*)r, entry->rel, entry->page,
-                               entry->offset, sizeof(GEOMETRYKEY),FALSE);
-
-               } else {
-                       gistentryinit(*retval, NULL, entry->rel, entry->page,
-                               entry->offset, 0,FALSE);
-               }
-       } else {
-               retval = entry;
-       }
-       return( retval );
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_consistent);
-bool ggeometry_consistent(PG_FUNCTION_ARGS)
-{
-    GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
-    GEOMETRY *query       = (GEOMETRY*)            PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
-    BOX                *thebox;
-    /*
-    ** if entry is not leaf, use gbox_internal_consistent,
-    ** else use gbox_leaf_consistent
-    */
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_consistent called\n");
-#endif
-
-    if ( ! (entry->pred && query) )
-       return FALSE;
-
-       thebox = convert_box3d_to_box( &(query->bvol) );
-
-       if(    ((GEOMETRYKEY *)(entry->pred))->SRID != query->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs (ggeometry_consistent)\n");
-               PG_RETURN_BOOL(FALSE);
-       }
-
-    PG_RETURN_BOOL(rtree_internal_consistent((BOX*)&( ((GEOMETRYKEY *)(entry->pred))->key ),
-               thebox, strategy));
-}
-
-
-PG_FUNCTION_INFO_V1(ggeometry_union);
-GEOMETRYKEY *ggeometry_union(PG_FUNCTION_ARGS)
-{
-       GEOMETRYKEY             *result;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_union called\n");
-#endif
-
-       result = (GEOMETRYKEY*)
-               rtree_union(
-                       (bytea*) PG_GETARG_POINTER(0),
-                       (int*) PG_GETARG_POINTER(1),
-                       ggeometry_binary_union
-               );
-
-    return result;
-}
-
-
-PG_FUNCTION_INFO_V1(ggeometry_penalty);
-float *ggeometry_penalty(PG_FUNCTION_ARGS)
-{
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_penalty called\n");
-#endif
-
-    return rtree_penalty(
-       (GISTENTRY*) PG_GETARG_POINTER(0),
-       (GISTENTRY*) PG_GETARG_POINTER(1),
-       (float*) PG_GETARG_POINTER(2),
-       ggeometry_binary_union,
-       size_geometrykey
-    );
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_picksplit);
-GIST_SPLITVEC *ggeometry_picksplit(PG_FUNCTION_ARGS)
-{
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_picksplit called\n");
-#endif
-
-
-    return rtree_picksplit(
-       (bytea*)PG_GETARG_POINTER(0),
-       (GIST_SPLITVEC*)PG_GETARG_POINTER(1),
-       sizeof(GEOMETRYKEY),
-       ggeometry_binary_union,
-       ggeometry_inter,
-       size_geometrykey
-    );
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_same);
-bool *ggeometry_same(PG_FUNCTION_ARGS)
-{
-
-  GEOMETRYKEY *b1 = (GEOMETRYKEY*) PG_GETARG_POINTER(0);
-  GEOMETRYKEY *b2 = (GEOMETRYKEY*) PG_GETARG_POINTER(1);
-
-  bool *result = (bool*) PG_GETARG_POINTER(2);
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_same called\n");
-#endif
-
-
-  if ( b1 && b2 )
-       *result = DatumGetBool( DirectFunctionCall2( box_same,
-               PointerGetDatum(&(b1->key)),
-               PointerGetDatum(&(b2->key))) );
-  else
-       *result = ( b1==NULL && b2==NULL ) ? TRUE : FALSE;
-  return(result);
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_inter);
-Datum ggeometry_inter(PG_FUNCTION_ARGS) {
-       GEOMETRYKEY *b1 = (GEOMETRYKEY*) PG_GETARG_POINTER(0);
-       GEOMETRYKEY*b2 = (GEOMETRYKEY*) PG_GETARG_POINTER(1);
-       char *interd;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_inter called\n");
-#endif
-
-
-       interd = DatumGetPointer(DirectFunctionCall2(
-                       rt_box_inter,
-                       PointerGetDatum( &(b1->key) ),
-                       PointerGetDatum( &(b2->key) )) );
-
-       if (interd) {
-               GEOMETRYKEY *tmp = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
-               tmp->size = sizeof(GEOMETRYKEY);
-
-               memcpy( (void*)&(tmp->key), (void*)interd, sizeof(BOX) );
-               tmp->SRID = b1->SRID;
-               pfree( interd );
-               PG_RETURN_POINTER( tmp );
-       } else
-               PG_RETURN_POINTER( NULL );
-}
-
-char *ggeometry_binary_union(char *r1, char *r2, int *sizep)
-{
-    GEOMETRYKEY *retval;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: ggeometry_binary_union called\n");
-#endif
-
-    if ( ! (r1 && r2) ) {
-       if ( r1 ) {
-               retval = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
-               memcpy( (void*)retval, (void*)r1, sizeof(GEOMETRYKEY) );
-               *sizep = sizeof(GEOMETRYKEY);
-       } else if ( r2 ) {
-               retval = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
-               memcpy( (void*)retval, (void*)r2, sizeof(GEOMETRYKEY) );
-               *sizep = sizeof(GEOMETRYKEY);
-       } else {
-               *sizep = 0;
-               retval = NULL;
-       }
-    } else {
-       BOX *key = (BOX*)DatumGetPointer( DirectFunctionCall2(
-               rt_box_union,
-               PointerGetDatum( &(((GEOMETRYKEY*)r1)->key) ),
-               PointerGetDatum( &(((GEOMETRYKEY*)r2)->key) )) );
-       retval = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
-       retval->SRID = ((GEOMETRYKEY *) r1)->SRID;
-       memcpy( (void*)&(retval->key), (void*)key, sizeof(BOX) );
-       pfree( key );
-       *sizep = retval->size = sizeof(GEOMETRYKEY);
-    }
-    return (char*)retval;
-}
-
-
-float size_geometrykey( char *pk ) {
-
-#ifdef DEBUG_GIST2
-       printf("GIST: size_geometrykey called\n");
-#endif
-
-    if ( pk ) {
-       float size;
-       DirectFunctionCall2( rt_box_size,
-               PointerGetDatum( &(((GEOMETRYKEY*)pk)->key) ),
-               PointerGetDatum( &size ) );
-       return size;
-    } else
-       return 0.0;
-}
-
-char *rtree_union(bytea *entryvec, int *sizep, BINARY_UNION bu)
-{
-    int numranges, i;
-    char *out, *tmp;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: rtree_union called\n");
-#endif
-
-    numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY);
-    tmp = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[0]).pred;
-    out = NULL;
-
-    for (i = 1; i < numranges; i++) {
-       out = (*bu)(tmp, (char *)
-                                (((GISTENTRY *)(VARDATA(entryvec)))[i]).pred,
-                                sizep);
-       if (i > 1 && tmp) pfree(tmp);
-       tmp = out;
-    }
-
-    return(out);
-}
-
-float *rtree_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result, BINARY_UNION bu, SIZE_BOX sb)
-{
-    char * ud;
-    float tmp1;
-    int sizep;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: rtree_penalty called\n");
-#endif
-
-
-
-    ud = (*bu)( origentry->pred, newentry->pred, &sizep );
-    tmp1 = (*sb)( ud );
-    if (ud) pfree(ud);
-
-    *result = tmp1 - (*sb)( origentry->pred );
-    return(result);
-}
-
-/*
-** The GiST PickSplit method
-** We use Guttman's poly time split algorithm
-*/
-GIST_SPLITVEC *rtree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, int keylen, BINARY_UNION bu, RDF interop, SIZE_BOX sb)
-{
-    OffsetNumber i, j;
-    char *datum_alpha, *datum_beta;
-    char *datum_l, *datum_r;
-    char *union_d, *union_dl, *union_dr;
-    char *inter_d;
-    bool firsttime;
-    float size_alpha, size_beta, size_union, size_inter;
-    float size_waste, waste;
-    float size_l, size_r;
-    int nbytes;
-    int sizep;
-    OffsetNumber seed_1 = 0, seed_2 = 0;
-    OffsetNumber *left, *right;
-    OffsetNumber maxoff;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: rtree_picsplit called\n");
-#endif
-
-    maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 2;
-    nbytes =  (maxoff + 2) * sizeof(OffsetNumber);
-    v->spl_left = (OffsetNumber *) palloc(nbytes);
-    v->spl_right = (OffsetNumber *) palloc(nbytes);
-
-    firsttime = true;
-    waste = 0.0;
-
-    for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) {
-       datum_alpha = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
-       for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) {
-           datum_beta = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[j].pred);
-
-           /* compute the wasted space by unioning these guys */
-           /* size_waste = size_union - size_inter; */
-           union_d = (*bu)( datum_alpha, datum_beta, &sizep );
-           if ( union_d ) {
-               size_union = (*sb)(union_d);
-               pfree(union_d);
-           } else
-               size_union = 0.0;
-
-           if ( datum_alpha && datum_beta ) {
-               inter_d = DatumGetPointer(DirectFunctionCall2(
-                       interop,
-                       PointerGetDatum( datum_alpha ),
-                       PointerGetDatum( datum_beta )) );
-               if ( inter_d ) {
-                       size_inter = (*sb)(inter_d);
-                       pfree(inter_d);
-               } else
-                       size_inter = 0.0;
-           } else
-               size_inter = 0.0;
-
-           size_waste = size_union - size_inter;
-
-           /*
-            *  are these a more promising split that what we've
-            *  already seen?
-            */
-
-           if (size_waste > waste || firsttime) {
-               waste = size_waste;
-               seed_1 = i;
-               seed_2 = j;
-               firsttime = false;
-           }
-       }
-    }
-
-    left = v->spl_left;
-    v->spl_nleft = 0;
-    right = v->spl_right;
-    v->spl_nright = 0;
-
-    if ( ((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred ) {
-       datum_l = (char*) palloc( keylen );
-       memcpy( (void*)datum_l, (void*)(((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred ), keylen );
-    } else
-       datum_l = NULL;
-    size_l  = (*sb)( datum_l );
-    if ( ((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred ) {
-       datum_r = (char*) palloc( keylen );
-       memcpy( (void*)datum_r, (void*)(((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred ), keylen );
-    } else
-       datum_r = NULL;
-    size_r  = (*sb)( datum_r );
-
-    /*
-     *  Now split up the regions between the two seeds.  An important
-     *  property of this split algorithm is that the split vector v
-     *  has the indices of items to be split in order in its left and
-     *  right vectors.  We exploit this property by doing a merge in
-     *  the code that actually splits the page.
-     *
-     *  For efficiency, we also place the new index tuple in this loop.
-     *  This is handled at the very end, when we have placed all the
-     *  existing tuples and i == maxoff + 1.
-     */
-
-    maxoff = OffsetNumberNext(maxoff);
-    for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
-
-       /*
-        *  If we've already decided where to place this item, just
-        *  put it on the right list.  Otherwise, we need to figure
-        *  out which page needs the least enlargement in order to
-        *  store the item.
-        */
-
-       if (i == seed_1) {
-           *left++ = i;
-           v->spl_nleft++;
-           continue;
-       } else if (i == seed_2) {
-           *right++ = i;
-           v->spl_nright++;
-           continue;
-       }
-
-       /* okay, which page needs least enlargement? */
-       datum_alpha = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
-       union_dl = (*bu)( datum_l, datum_alpha, &sizep );
-       union_dr = (*bu)( datum_r, datum_alpha, &sizep );
-       size_alpha = (*sb)( union_dl );
-       size_beta  = (*sb)( union_dr );
-
-       /* pick which page to add it to */
-       if (size_alpha - size_l < size_beta - size_r) {
-           pfree(datum_l);
-           pfree(union_dr);
-           datum_l = union_dl;
-           size_l = size_alpha;
-           *left++ = i;
-           v->spl_nleft++;
-       } else {
-           pfree(datum_r);
-           pfree(union_dl);
-           datum_r = union_dr;
-           size_r = size_alpha;
-           *right++ = i;
-           v->spl_nright++;
-       }
-    }
-    *left = *right = FirstOffsetNumber;        /* sentinel value, see dosplit() */
-
-    v->spl_ldatum = datum_l;
-    v->spl_rdatum = datum_r;
-
-    return( v );
-}
-
-
-bool rtree_internal_consistent(BOX *key,
-                       BOX *query,
-                       StrategyNumber strategy)
-{
-    bool retval;
-
-#ifdef DEBUG_GIST2
-       printf("GIST: rtree_internal_consist called\n");
-#endif
-
-    switch(strategy) {
-    case RTLeftStrategyNumber:
-    case RTOverLeftStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overleft, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTOverlapStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTOverRightStrategyNumber:
-    case RTRightStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_right, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTSameStrategyNumber:
-    case RTContainsStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_contain, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTContainedByStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    default:
-      retval = FALSE;
-    }
-    return(retval);
-}
-
-PG_FUNCTION_INFO_V1(rtree_decompress);
-GISTENTRY *rtree_decompress(PG_FUNCTION_ARGS)
-{
-    return((GISTENTRY*)PG_GETARG_POINTER(0));
-}
-
-
diff --git a/hwgeom/postgis_gist_72.c b/hwgeom/postgis_gist_72.c
deleted file mode 100644 (file)
index 1d68bd1..0000000
+++ /dev/null
@@ -1,738 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.19  2004/08/19 06:15:58  strk
- * USE_VERSION gets 80 where it got 75
- *
- * Revision 1.18  2004/06/09 10:19:06  strk
- * Moved changes needed for PG75 inside postgis_gist_72.c using #if switches.
- *
- * Revision 1.17  2004/06/03 08:19:20  strk
- * yet another Infinite check used: finite() - which checks for NaN,-Inf,+Inf
- *
- * Revision 1.16  2004/06/03 08:13:11  strk
- * Simplified INFINITY checks by use of isinf()
- *
- * Revision 1.15  2004/06/03 07:58:11  strk
- * Infinite coordinate geoms omitted from index
- *
- * Revision 1.14  2004/06/02 23:54:09  strk
- * Made equality checks the default in picksplit to catch also NaN results (INF geoms)
- *
- * Revision 1.13  2004/06/02 23:29:08  strk
- * reverted Inf handling modification (conceptually bogus)
- *
- * Revision 1.12  2004/06/02 22:43:54  strk
- * handled special case of Inf boxes as GiST keys in picksplit
- *
- * Revision 1.11  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.10  2004/04/08 17:05:20  dblasby
- * Somehow the memory leak changes I made got removed - I've re-added them.
- *
- * Revision 1.9  2004/04/08 17:00:27  dblasby
- * Changed ggeometry_consistent to be aware of NULL queries.  Ie.
- * select * from <table> where the_geom &&  null::geometry;
- *
- * This tends to happen when you're joining two tables using && and the table
- * has NULLs in it.
- *
- * Revision 1.8  2004/03/05 18:16:47  strk
- * Applied Mark Cave-Ayland patch
- *
- * Revision 1.7  2004/02/25 13:17:31  strk
- * RTContainedBy and RTOverlap strategries implemented locally with a pgbox_overlap function
- *
- * Revision 1.6  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.5  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************
- *
- * GiST indexing functions for pgsql >= 7.2
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-#define DEBUG_GIST
-
-//for GIST index
-typedef char* (*BINARY_UNION)(char*, char*, int*);
-typedef float (*SIZE_BOX)(char*);
-typedef Datum (*RDF)(PG_FUNCTION_ARGS);
-
-
-BOX *convert_box3d_to_box(BOX3D *in);
-Datum ggeometry_compress(PG_FUNCTION_ARGS);
-Datum ggeometry_consistent(PG_FUNCTION_ARGS);
-static bool rtree_internal_consistent(BOX *key, BOX *query,StrategyNumber strategy);
-static bool rtree_leaf_consistent(BOX *key, BOX *query,StrategyNumber strategy);
-Datum rtree_decompress(PG_FUNCTION_ARGS);
-Datum gbox_union(PG_FUNCTION_ARGS);
-Datum gbox_picksplit(PG_FUNCTION_ARGS);
-Datum gbox_penalty(PG_FUNCTION_ARGS);
-Datum gbox_same(PG_FUNCTION_ARGS);
-static float size_box(Datum box);
-extern void convert_box3d_to_box_p(BOX3D *in,BOX *out);
-
-
-int debug = 0;
-
-//puts result in pre-allocated "out"
-void convert_box3d_to_box_p(BOX3D *in,BOX *out)
-{
-
-               out->high.x = in->URT.x;
-               out->high.y = in->URT.y;
-
-               out->low.x = in->LLB.x;
-               out->low.y = in->LLB.y;
-}
-
-
-BOX    *convert_box3d_to_box(BOX3D *in)
-{
-               BOX     *out = palloc (sizeof (BOX) );
-
-               out->high.x = in->URT.x;
-               out->high.y = in->URT.y;
-
-               out->low.x = in->LLB.x;
-               out->low.y = in->LLB.y;
-
-       return out;
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_compress);
-Datum ggeometry_compress(PG_FUNCTION_ARGS)
-{
-       GISTENTRY *entry=(GISTENTRY*)PG_GETARG_POINTER(0);
-       GISTENTRY *retval;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: ggeometry_compress called on geometry\n");
-       fflush( stdout );
-#endif
-
-       if ( entry->leafkey)
-       {
-               retval = palloc(sizeof(GISTENTRY));
-               if ( DatumGetPointer(entry->key) != NULL )
-               {
-
-                       GEOMETRY *in;
-                       BOX     *r;
-
-
-                       in = (GEOMETRY*)PG_DETOAST_DATUM( entry->key );
-
-                       if (in->nobjs ==0)  // this is the EMPTY geometry
-                       {
-                               //elog(NOTICE,"found an empty geometry");
-                               // dont bother adding this to the index
-                               PG_RETURN_POINTER(entry);
-                       }
-
-                       if ( ! finite(in->bvol.URT.x) ||
-                               ! finite(in->bvol.URT.y) ||
-                               ! finite(in->bvol.LLB.x) ||
-                               ! finite(in->bvol.LLB.y) )
-                       {
-                               //elog(NOTICE, "found infinite geometry");
-                               PG_RETURN_POINTER(entry);
-                       }
-
-                       r = convert_box3d_to_box(&in->bvol);
-                       if ( in != (GEOMETRY*)DatumGetPointer(entry->key) )
-                       {
-                               pfree( in );
-                       }
-
-                       gistentryinit(*retval, PointerGetDatum(r),
-                               entry->rel, entry->page,
-                               entry->offset, sizeof(BOX),
-                               FALSE);
-
-               }
-               else
-               {
-                       gistentryinit(*retval, (Datum) 0, entry->rel,
-                               entry->page, entry->offset, 0,FALSE);
-               }
-       }
-       else
-       {
-               retval = entry;
-       }
-       PG_RETURN_POINTER(retval);
-}
-
-PG_FUNCTION_INFO_V1(ggeometry_consistent);
-Datum ggeometry_consistent(PG_FUNCTION_ARGS)
-{
-    GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
-    GEOMETRY *query ;
-    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
-    BOX                thebox;
-       bool result;
-
-elog(NOTICE, "**** ggeometry_consistent call");
-
-   /*
-    ** if entry is not leaf, use rtree_internal_consistent,
-    ** else use rtree_leaf_consistent
-    */
-
-   if (   ( (Pointer *) PG_GETARG_DATUM(1) ) == NULL)
-    {
-               //elog(NOTICE,"ggeometry_consistent:: got null query!");
-               PG_RETURN_BOOL(false); // null query - this is screwy!
-       }
-
-       query = (GEOMETRY*) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: ggeometry_consistent called\n");
-       fflush( stdout );
-#endif
-
-       if ( ! (DatumGetPointer(entry->key) != NULL && query) )
-               PG_RETURN_BOOL(FALSE);
-
-       convert_box3d_to_box_p( &(query->bvol) , &thebox);
-
-       if (GIST_LEAF(entry))
-               result = rtree_leaf_consistent((BOX *) DatumGetPointer(entry->key), &thebox, strategy );
-       else
-               result = rtree_internal_consistent((BOX *) DatumGetPointer(entry->key), &thebox, strategy );
-
-       PG_FREE_IF_COPY(query, 1);
-       PG_RETURN_BOOL(result);
-}
-
-
-static bool
-rtree_internal_consistent(BOX *key,
-                       BOX *query,
-                       StrategyNumber strategy)
-{
-    bool retval;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: rtree_internal_consist called\n");
-       fflush( stdout );
-#endif
-
-    switch(strategy) {
-    case RTLeftStrategyNumber:
-    case RTOverLeftStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overleft, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTOverlapStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTOverRightStrategyNumber:
-    case RTRightStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overright, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTSameStrategyNumber:
-    case RTContainsStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_contain, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    case RTContainedByStrategyNumber:
-      retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) );
-      break;
-    default:
-      retval = FALSE;
-    }
-    return(retval);
-}
-
-
-static bool
-rtree_leaf_consistent(BOX *key,
-                       BOX *query,
-                       StrategyNumber strategy)
-{
-    bool retval;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: rtree_leaf_consist called\n");
-       fflush( stdout );
-#endif
-
-       switch (strategy)
-       {
-               case RTLeftStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_left, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTOverLeftStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTOverlapStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTOverRightStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_overright, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTRightStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTSameStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTContainsStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_contain, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               case RTContainedByStrategyNumber:
-                       retval = DatumGetBool(DirectFunctionCall2(box_contained, PointerGetDatum(key), PointerGetDatum(query)));
-                       break;
-               default:
-                       retval = FALSE;
-       }
-       return (retval);
-}
-
-
-PG_FUNCTION_INFO_V1(rtree_decompress);
-Datum rtree_decompress(PG_FUNCTION_ARGS)
-{
-       elog(NOTICE, "rtree_decompress called");
-    PG_RETURN_POINTER(PG_GETARG_POINTER(0));
-}
-
-/*
-** The GiST Union method for boxes
-** returns the minimal bounding box that encloses all the entries in entryvec
-*/
-PG_FUNCTION_INFO_V1(gbox_union);
-Datum gbox_union(PG_FUNCTION_ARGS)
-{
-#if USE_VERSION < 80
-       bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
-#else
-       GistEntryVector    *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-#endif
-       int                *sizep = (int *) PG_GETARG_POINTER(1);
-       int                     numranges,
-                               i;
-       BOX                *cur,
-                          *pageunion;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: gbox_union called\n");
-       fflush( stdout );
-#endif
-
-#if USE_VERSION < 80
-       numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
-       cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[0].key);
-#else
-       numranges = entryvec->n;
-       cur = DatumGetBoxP(entryvec->vector[0].key);
-#endif
-       pageunion = (BOX *) palloc(sizeof(BOX));
-       memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
-
-       for (i = 1; i < numranges; i++)
-       {
-#if USE_VERSION < 80
-               cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
-#else
-               cur = DatumGetBoxP(entryvec->vector[i].key);
-#endif
-               if (pageunion->high.x < cur->high.x)
-                       pageunion->high.x = cur->high.x;
-               if (pageunion->low.x > cur->low.x)
-                       pageunion->low.x = cur->low.x;
-               if (pageunion->high.y < cur->high.y)
-                       pageunion->high.y = cur->high.y;
-               if (pageunion->low.y > cur->low.y)
-                       pageunion->low.y = cur->low.y;
-       }
-       *sizep = sizeof(BOX);
-
-       PG_RETURN_POINTER(pageunion);
-}
-
-/*
-** The GiST Penalty method for boxes
-** As in the R-tree paper, we use change in area as our penalty metric
-*/
-PG_FUNCTION_INFO_V1(gbox_penalty);
-Datum gbox_penalty(PG_FUNCTION_ARGS)
-{
-       GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
-       GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
-       float      *result = (float *) PG_GETARG_POINTER(2);
-       Datum           ud;
-       float           tmp1;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: gbox_penalty called\n");
-       fflush( stdout );
-#endif
-
-       ud = DirectFunctionCall2(rt_box_union, origentry->key, newentry->key);
-       tmp1 = size_box(ud);
-       if (DatumGetPointer(ud) != NULL)
-               pfree(DatumGetPointer(ud));
-
-       *result = tmp1 - size_box(origentry->key);
-       PG_RETURN_POINTER(result);
-}
-
-typedef struct {
-       BOX     *key;
-       int     pos;
-} KBsort;
-
-static int
-compare_KB(const void* a, const void* b) {
-       BOX *abox = ((KBsort*)a)->key;
-       BOX *bbox = ((KBsort*)b)->key;
-       float sa = (abox->high.x - abox->low.x) * (abox->high.y - abox->low.y);
-       float sb = (bbox->high.x - bbox->low.x) * (bbox->high.y - bbox->low.y);
-
-       if ( sa==sb ) return 0;
-       return ( sa>sb ) ? 1 : -1;
-}
-
-/*
-** The GiST PickSplit method
-** New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
-** C.H.Ang and T.C.Tan
-*/
-PG_FUNCTION_INFO_V1(gbox_picksplit);
-Datum
-gbox_picksplit(PG_FUNCTION_ARGS)
-{
-#if USE_VERSION < 80
-       bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
-#else
-       GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-#endif
-       GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
-       OffsetNumber i;
-       OffsetNumber *listL,
-                          *listR,
-                          *listB,
-                          *listT;
-       BOX                *unionL,
-                          *unionR,
-                          *unionB,
-                          *unionT;
-       int                     posL,
-                               posR,
-                               posB,
-                               posT;
-       BOX                     pageunion;
-       BOX                *cur;
-       char            direction = ' ';
-       bool            allisequal = true;
-       OffsetNumber maxoff;
-       int                     nbytes;
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: gbox_picksplit called\n");
-       fflush( stdout );
-#endif
-
-       posL = posR = posB = posT = 0;
-#if USE_VERSION < 80
-       maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1;
-       cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[FirstOffsetNumber].key);
-#else
-       maxoff = entryvec->n - 1;
-       cur = DatumGetBoxP(entryvec->vector[FirstOffsetNumber].key);
-#endif
-
-       memcpy((void *) &pageunion, (void *) cur, sizeof(BOX));
-
-       /* find MBR */
-       for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i))
-       {
-#if USE_VERSION < 80
-               cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
-#else
-               cur = DatumGetBoxP(entryvec->vector[i].key);
-#endif
-               if ( allisequal == true &&  (
-                               pageunion.high.x != cur->high.x ||
-                               pageunion.high.y != cur->high.y ||
-                               pageunion.low.x != cur->low.x ||
-                               pageunion.low.y != cur->low.y
-                       ) )
-                       allisequal = false;
-
-               if (pageunion.high.x < cur->high.x)
-                       pageunion.high.x = cur->high.x;
-               if (pageunion.low.x > cur->low.x)
-                       pageunion.low.x = cur->low.x;
-               if (pageunion.high.y < cur->high.y)
-                       pageunion.high.y = cur->high.y;
-               if (pageunion.low.y > cur->low.y)
-                       pageunion.low.y = cur->low.y;
-       }
-
-       nbytes = (maxoff + 2) * sizeof(OffsetNumber);
-       listL = (OffsetNumber *) palloc(nbytes);
-       listR = (OffsetNumber *) palloc(nbytes);
-       unionL = (BOX *) palloc(sizeof(BOX));
-       unionR = (BOX *) palloc(sizeof(BOX));
-       if (allisequal)
-       {
-#if USE_VERSION < 80
-               cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[OffsetNumberNext(FirstOffsetNumber)].key);
-#else
-               cur = DatumGetBoxP(entryvec->vector[OffsetNumberNext(FirstOffsetNumber)].key);
-#endif
-               if (memcmp((void *) cur, (void *) &pageunion, sizeof(BOX)) == 0)
-               {
-                       v->spl_left = listL;
-                       v->spl_right = listR;
-                       v->spl_nleft = v->spl_nright = 0;
-                       memcpy((void *) unionL, (void *) &pageunion, sizeof(BOX));
-                       memcpy((void *) unionR, (void *) &pageunion, sizeof(BOX));
-
-                       for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
-                       {
-                               if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
-                               {
-                                       v->spl_left[v->spl_nleft] = i;
-                                       v->spl_nleft++;
-                               }
-                               else
-                               {
-                                       v->spl_right[v->spl_nright] = i;
-                                       v->spl_nright++;
-                               }
-                       }
-                       v->spl_ldatum = BoxPGetDatum(unionL);
-                       v->spl_rdatum = BoxPGetDatum(unionR);
-
-                       PG_RETURN_POINTER(v);
-               }
-       }
-
-       listB = (OffsetNumber *) palloc(nbytes);
-       listT = (OffsetNumber *) palloc(nbytes);
-       unionB = (BOX *) palloc(sizeof(BOX));
-       unionT = (BOX *) palloc(sizeof(BOX));
-
-#define ADDLIST( list, unionD, pos, num ) do { \
-       if ( pos ) { \
-               if ( unionD->high.x < cur->high.x ) unionD->high.x      = cur->high.x; \
-               if ( unionD->low.x      > cur->low.x  ) unionD->low.x   = cur->low.x; \
-               if ( unionD->high.y < cur->high.y ) unionD->high.y      = cur->high.y; \
-               if ( unionD->low.y      > cur->low.y  ) unionD->low.y   = cur->low.y; \
-       } else { \
-                       memcpy( (void*)unionD, (void*) cur, sizeof( BOX ) );  \
-       } \
-       list[pos] = num; \
-       (pos)++; \
-} while(0)
-
-       for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
-       {
-#if USE_VERSION < 80
-               cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
-#else
-               cur = DatumGetBoxP(entryvec->vector[i].key);
-#endif
-               if (cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x)
-                       ADDLIST(listL, unionL, posL,i);
-               else
-                       ADDLIST(listR, unionR, posR,i);
-
-               if (cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y)
-                       ADDLIST(listB, unionB, posB,i);
-               else
-                       ADDLIST(listT, unionT, posT,i);
-       }
-
-       /* bad disposition, sort by ascending and resplit */
-       if ( (posR==0 || posL==0) && (posT==0 || posB==0) ) {
-               KBsort *arr = (KBsort*)palloc( sizeof(KBsort) * maxoff );
-               posL = posR = posB = posT = 0;
-               for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
-#if USE_VERSION < 80
-                       arr[i-1].key = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
-#else
-                       arr[i-1].key = DatumGetBoxP(entryvec->vector[i].key);
-#endif
-                       arr[i-1].pos = i;
-               }
-               qsort( arr, maxoff, sizeof(KBsort), compare_KB );
-               for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
-                       cur = arr[i-1].key;
-                       if (cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x)
-                               ADDLIST(listL, unionL, posL,arr[i-1].pos);
-                       else if ( cur->low.x - pageunion.low.x > pageunion.high.x - cur->high.x ) 
-                               ADDLIST(listR, unionR, posR,arr[i-1].pos);
-                       else
-                       {
-                               if ( posL>posR )
-                                       ADDLIST(listR, unionR, posR,arr[i-1].pos);
-                               else
-                                       ADDLIST(listL, unionL, posL,arr[i-1].pos);
-                       }
-
-                       if (cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y)
-                               ADDLIST(listB, unionB, posB,arr[i-1].pos);
-                       else if ( cur->low.y - pageunion.low.y > pageunion.high.y - cur->high.y ) 
-                               ADDLIST(listT, unionT, posT,arr[i-1].pos);
-                       else
-                       {
-                               if ( posB>posT )
-                                       ADDLIST(listT, unionT, posT,arr[i-1].pos);
-                               else
-                                       ADDLIST(listB, unionB, posB,arr[i-1].pos);
-                       }
-               }
-               pfree(arr);
-       }
-
-       /* which split more optimal? */
-       if (Max(posL, posR) < Max(posB, posT))
-               direction = 'x';
-       else if (Max(posL, posR) > Max(posB, posT))
-               direction = 'y';
-       else
-       {
-               Datum           interLR = DirectFunctionCall2(rt_box_inter,
-                                                                                                 BoxPGetDatum(unionL),
-                                                                                                 BoxPGetDatum(unionR));
-               Datum           interBT = DirectFunctionCall2(rt_box_inter,
-                                                                                                 BoxPGetDatum(unionB),
-                                                                                                 BoxPGetDatum(unionT));
-               float           sizeLR,
-                                       sizeBT;
-
-               sizeLR = size_box(interLR);
-               sizeBT = size_box(interBT);
-
-               if (sizeLR < sizeBT)
-                       direction = 'x';
-               else
-                       direction = 'y';
-       }
-
-       if (direction == 'x')
-       {
-               pfree(unionB);
-               pfree(listB);
-               pfree(unionT);
-               pfree(listT);
-
-               v->spl_left = listL;
-               v->spl_right = listR;
-               v->spl_nleft = posL;
-               v->spl_nright = posR;
-               v->spl_ldatum = BoxPGetDatum(unionL);
-               v->spl_rdatum = BoxPGetDatum(unionR);
-       }
-       else
-       {
-               pfree(unionR);
-               pfree(listR);
-               pfree(unionL);
-               pfree(listL);
-
-               v->spl_left = listB;
-               v->spl_right = listT;
-               v->spl_nleft = posB;
-               v->spl_nright = posT;
-               v->spl_ldatum = BoxPGetDatum(unionB);
-               v->spl_rdatum = BoxPGetDatum(unionT);
-       }
-
-       PG_RETURN_POINTER(v);
-}
-
-/*
-** Equality method
-*/
-PG_FUNCTION_INFO_V1(gbox_same);
-Datum gbox_same(PG_FUNCTION_ARGS)
-{
-       BOX                *b1 = (BOX *) PG_GETARG_POINTER(0);
-       BOX                *b2 = (BOX *) PG_GETARG_POINTER(1);
-       bool       *result = (bool *) PG_GETARG_POINTER(2);
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: gbox_same called\n");
-       fflush( stdout );
-#endif
-
-       if (b1 && b2)
-               *result = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(b1), PointerGetDatum(b2)));
-       else
-               *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE;
-       PG_RETURN_POINTER(result);
-}
-
-static float
-size_box(Datum box)
-{
-
-#ifdef DEBUG_GIST
-       elog(NOTICE,"GIST: size_box called\n");
-       fflush( stdout );
-#endif
-
-       if (DatumGetPointer(box) != NULL)
-       {
-               float           size;
-
-               DirectFunctionCall2(rt_box_size,
-                                                       box, PointerGetDatum(&size));
-               return size;
-       }
-       else
-               return 0.0;
-}
diff --git a/hwgeom/postgis_inout.c b/hwgeom/postgis_inout.c
deleted file mode 100644 (file)
index d12ccdf..0000000
+++ /dev/null
@@ -1,4906 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.45  2004/08/11 17:07:26  strk
- * Fixed a bug in non-finite Z check
- *
- * Revision 1.44  2004/06/09 09:08:53  strk
- * changed index/rindex to strchr/strrchr
- *
- * Revision 1.43  2004/06/08 15:18:12  strk
- * Deleted prototype for isspace() in postgis.h
- * and included <ctype.h> in postgis_inout.c,
- * which is the only module calling isspace().
- * This was needed to compile postgis against PG75(CVS).
- *
- * Revision 1.42  2004/06/03 09:45:57  strk
- * infinite geoms handled in WKB parser
- *
- * Revision 1.41  2004/06/03 08:19:20  strk
- * yet another Infinite check used: finite() - which checks for NaN,-Inf,+Inf
- *
- * Revision 1.40  2004/06/03 08:13:11  strk
- * Simplified INFINITY checks by use of isinf()
- *
- * Revision 1.39  2004/06/03 07:57:29  strk
- * wkt parser throws an error on Infinite coordinates
- *
- * Revision 1.38  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.37  2004/04/27 23:47:39  dblasby
- * minor 3d geometrycollection bug fix
- *
- * Revision 1.36  2004/01/13 22:14:25  pramsey
- * Changed getint and getdouble used by WKB so that it plays nice with
- * memory alignment (solaris issue).
- *
- * Revision 1.35  2003/12/12 18:00:15  strk
- * reverted make_line patch, patched size_subobject instead - the reported bug was caused to their inconsistency
- *
- * Revision 1.34  2003/12/12 14:39:04  strk
- * Fixed a bug in make_line allocating less memory then required
- *
- * Revision 1.33  2003/12/12 12:03:30  strk
- * More debugging output, some code cleanup.
- *
- * Revision 1.32  2003/12/09 11:58:42  strk
- * Final touch to wkb binary input function
- *
- * Revision 1.31  2003/12/09 11:13:41  strk
- * WKB_recv: set StringInfo cursor to the end of StringInfo buf as required by postgres backend
- *
- * Revision 1.30  2003/12/08 17:57:36  strk
- * Binary WKB input function built only when USE_VERSION > 73. Making some modifications based on reported failures
- *
- * Revision 1.29  2003/11/28 11:06:49  strk
- * Added WKB_recv function for binary WKB input
- *
- * Revision 1.28  2003/10/06 18:09:08  dblasby
- * Fixed typo in add_to_geometry().  With very poorly aligned sub-objects, it
- * wouldnt allocate enough memory.  Fixed it so its pesimistic and will allocate
- * enough memory.
- *
- * Revision 1.27  2003/08/22 17:40:11  dblasby
- * fixed geometry_in('SRID=<int>{no ;}').
- *
- * Revision 1.26  2003/08/21 16:22:09  dblasby
- * added patch from strk@freek.keybit.net  for PG_NARGS() not being in 7.2
- *
- * Revision 1.25  2003/08/08 18:19:20  dblasby
- * Conformance changes.
- * Removed junk from postgis_debug.c and added the first run of the long
- * transaction locking support.  (this will change - dont use it)
- * conformance tests were corrected
- * some dos cr/lf removed
- * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
- * pointN(<linestring>,1) now returns the first point (used to return 2nd)
- *
- * Revision 1.24  2003/08/06 19:31:18  dblasby
- * Added the WKB parser.  Added all the functions like
- * PolyFromWKB(<WKB>,[<SRID>]).
- *
- * Added all the functions like PolyFromText(<WKT>,[<SRID>])
- *
- * Minor problem in GEOS library fixed.
- *
- * Revision 1.23  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.22  2003/07/08 18:35:54  dblasby
- * changed asbinary_specify() so that it is more aware of TEXT being
- * un-terminated.
- *
- * this is a modified patch from David Garnier <david.garnier@etudier-online.com>.
- *
- * Revision 1.21  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-
-#include "fmgr.h"
-
-
-#include "postgis.h"
-#if USE_VERSION > 73
-# include "lib/stringinfo.h" // for WKB binary input
-#endif
-#include "utils/elog.h"
-
-
-#define SHOW_DIGS_DOUBLE 16
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-// #define DEBUG_GIST
-//#define DEBUG_GIST2
-
-
-#define WKB3DOFFSET 0x80000000
-
-
-void swap_char(char    *a,char *b)
-{
-       char c;
-
-       c = *a;
-       *a=*b;
-       *b=c;
-}
-
-
-void   flip_endian_double(char         *d)
-{
-       swap_char(d+7, d);
-       swap_char(d+6, d+1);
-       swap_char(d+5, d+2);
-       swap_char(d+4, d+3);
-}
-
-void           flip_endian_int32(char          *i)
-{
-       swap_char (i+3,i);
-       swap_char (i+2,i+1);
-}
-
-
-
-//takes a point and sticks it at the end of a string
-void print_point(char *result, POINT3D *pt,bool is3d)
-{
-       char    temp[MAX_DIGS_DOUBLE*3 +6];
-
-
-       if ( (pt == NULL) || (result == NULL) )
-               return;
-
-       if (is3d)
-               sprintf(temp, "%.15g %.15g %.15g", pt->x,pt->y,pt->z);
-       else
-               sprintf(temp, "%.15g %.15g", pt->x,pt->y);
-
-       strcat(result,temp);
-
-}
-
-//result MUST BE null terminated (or result[0] = 0)
-void print_many_points(char *result, POINT3D *pt ,int npoints, bool is3d)
-{
-       int     u;
-
-       result += strlen(result);
-       if (is3d)
-       {
-               for (u=0;u<npoints;u++)
-               {
-                       if (u != 0)
-                       {
-                               result[0] = ',';
-                               result++;
-                       }
-                       result+=        sprintf(result,"%.15g %.15g %.15g", pt[u].x,pt[u].y,pt[u].z);
-               }
-       }
-       else
-       {
-               for (u=0;u<npoints;u++)
-               {
-                       if (u != 0)
-                       {
-                               result[0] = ',';
-                               result++;
-                       }
-
-                       result += sprintf(result, "%.15g %.15g",
-                                       pt[u].x, pt[u].y);
-               }
-       }
-}
-
-
-//swap two doubles
-void swap(double *d1, double *d2)
-{
-       double t;
-
-       t = *d1;
-       *d1 = *d2;
-       *d2 = t;
-}
-
-
-//returns how many points are in the first list in str
-//
-//  1. scan ahead looking for "("
-//  2. find "," until hit a ")"
-//  3. return number of points found
-//
-// NOTE: doesnt actually parse the points, so if the
-//       str contains an invalid geometry, this could give
-//        back the wrong answer.
-//
-// "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" => 2 (2nd list is not included)
-int    numb_points_in_list(char        *str)
-{
-       bool    keep_going;
-       int     points_found = 1; //no "," if only one point (and last point)
-                                       // # points = 1 + numb of ","
-
-       if ( (str == NULL) || (str[0] == 0) )
-       {
-               return 0;  //either null string or empty string
-       }
-
-       //look ahead for the "("
-
-       str = strchr(str,'(') ;
-
-       if ( (str == NULL) || (str[1] == 0) )  // str[0] = '(';
-       {
-               return 0;  //either didnt find "(" or its at the end of the string
-       }
-
-       keep_going = TRUE;
-       while (keep_going)
-       {
-               str=strpbrk(str,",)");  // look for a "," or ")"
-               keep_going = (str != NULL);
-               if (keep_going)  // found a , or )
-               {
-                       if (str[0] == ')')
-                       {
-                               //finished
-                               return points_found;
-                       }
-                       else    //str[0] = ","
-                       {
-                               points_found++;
-                               str++; //move 1 char forward
-                       }
-               }
-       }
-       return points_found; // technically it should return an error.
-}
-
-//Actually parse the points in a list
-//  "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" =>
-//                     points[0] = {1,2,3} and points[1] = {4,5,6}
-//             (2nd list is not parsed)
-//
-// parse at most max_points (points should already have enough space)
-// if any of the points are 3d, is3d is set to true, otherwise its untouched.
-//     2d points have z=0.0
-//
-// returns true if everything parses okay, otherwise false
-
-bool   parse_points_in_list(char       *str, POINT3D   *points, int32  max_points, bool *is3d)
-{
-       bool    keep_going;
-       int     numb_found= 0;
-       int     num_entities;
-
-       if ( (str == NULL) || (str[0] == 0)  || (max_points <0) || (points == NULL) )
-       {
-               return FALSE;  //either null string or empty string or other problem
-       }
-
-       if (max_points == 0)
-               return TRUE; //ask for nothing, get nothing
-
-       //look ahead for the "("
-
-       str = strchr(str,'(') ;
-
-       if ( (str == NULL) || (str[1] == 0) )  // str[0] = '(';
-       {
-               return FALSE;  //either didnt find "(" or its at the end of the string
-       }
-       str++;  //move forward one char
-
-       keep_going = TRUE;
-       while (keep_going)
-       {
-               //attempt to get the point
-               num_entities = sscanf(str,"%le %le %le", 
-                       &(points[numb_found].x),
-                       &(points[numb_found].y),
-                       &(points[numb_found].z));
-
-               if (num_entities !=3)
-               {
-                       if (num_entities !=2 )
-                       {
-                               elog(ERROR, "geom3d: parse_points_in_list() on invalid point");
-                               return FALSE; //error
-                       }
-                       else
-                       {
-                               points[numb_found].z = 0.0; //2d (only found x,y - set z =0.0)
-                       }
-               }
-               else
-               {
-                       *is3d = TRUE; //found 3 entites (x,y,z)
-               }
-
-               if ( ! finite(points[numb_found].x) ||
-                       ! finite(points[numb_found].y) )
-               {
-                       elog(ERROR, "infinite coordinate in geom");
-                       return FALSE;
-               }
-               numb_found++;
-
-               str=strpbrk(str,",)");  // look for a "," or ")"
-               if (str != NULL)
-                       str++;
-               keep_going =  ( (str != NULL) && (str[0] != ')' ) && (numb_found < max_points)  );
-       }
-       return TRUE;
-}
-
-
-//Actually parse the points in a list
-//  "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" =>
-//                     points[0] = {1,2,3} and points[1] = {4,5,6}
-//             (2nd list is not parsed)
-//
-// parse at most max_points (points should already have enough space)
-// if any of the points are 3d, is3d is set to true, otherwise its untouched.
-//     2d points have z=0.0
-//
-// returns true if everything parses okay, otherwise false
-//
-// THIS IS EXACTLY the same as parse_points_in_list(), but returns FALSE if
-// the number of points parsed is != max_points
-
-bool   parse_points_in_list_exact(char *str, POINT3D   *points, int32  max_points, bool *is3d)
-{
-       bool    keep_going;
-       int     numb_found= 0;
-
-       char    *end_of_double;
-
-       if ( (str == NULL) || (str[0] == 0)  || (max_points <0) || (points == NULL) )
-       {
-               return FALSE;  //either null string or empty string or other problem
-       }
-
-       if (max_points == 0)
-               return TRUE; //ask for nothing, get nothing
-
-       //look ahead for the "("
-
-       str = strchr(str,'(') ;
-
-       if ( (str == NULL) || (str[1] == 0) )  // str[0] = '(';
-       {
-               return FALSE;  //either didnt find "(" or its at the end of the string
-       }
-       str++;  //move forward one char
-
-       keep_going = TRUE;
-       while (keep_going)
-       {
-               //attempt to get the point
-
-                       //scanf is slow, so we use strtod()
-
-
-                       points[numb_found].x = strtod(str,&end_of_double);
-                       if (end_of_double == str)
-                       {
-                               return FALSE; //error occured (nothing parsed)
-                       }
-                       str = end_of_double;
-                       if ( ! finite(points[numb_found].x) )
-                       {
-                               elog(ERROR, "infinite coordinate in geom");
-                               return FALSE;
-                       }
-                       points[numb_found].y = strtod(str,&end_of_double);
-                       if (end_of_double == str)
-                       {
-                               return FALSE; //error occured (nothing parsed)
-                       }
-                       if ( ! finite(points[numb_found].y) )
-                       {
-                               elog(ERROR, "infinite coordinate in geom");
-                               return FALSE;
-                       }
-                       str = end_of_double;
-                       points[numb_found].z = strtod(str,&end_of_double); //will be zero if error occured
-                       if (!(end_of_double == str))
-                       {
-                               if ( ! finite(points[numb_found].z) )
-                               {
-                                       elog(ERROR, "infinite coordinate in geom");
-                                       return FALSE;
-                               }
-                               *is3d = TRUE; //found 3 entites (x,y,z)
-                       }
-                       else
-                       {
-                               points[numb_found].z = 0.0;
-                       }
-                       str = end_of_double;
-                       numb_found++;
-
-
-
-               str=strpbrk(str,",)");  // look for a "," or ")"
-               if (str != NULL)
-                       str++;
-               keep_going =  ( (str != NULL) && (str[0] != ')' ) && (numb_found < max_points)  );
-       }
-       return (numb_found == max_points);
-}
-
-
-
-
-// Find the number of sub lists in a list
-// ( (..),(..),(..) )  -> 3
-// ( ( (..),(..) ), ( (..) )) -> 2
-// ( ) -> 0
-// scan through the list, for every "(", depth (nesting) increases by 1
-//                               for every ")", depth (nesting) decreases by 1
-// if find a "(" at depth 1, then there is a sub list
-//
-// example:
-//      "(((..),(..)),((..)))"
-//depth  12333223332112333210
-//        +           +         increase here
-
-int    find_outer_list_length(char *str)
-{
-       int     current_depth = 0;
-       int     numb_lists = 0;
-
-
-       while ( (str != NULL) && (str[0] != 0) )
-       {
-               str=strpbrk(str,"()"); //look for "(" or ")"
-               if (str != NULL)
-               {
-                       if (str[0] == '(')
-                       {
-                               current_depth++;
-                               if (current_depth == 2)
-                                       numb_lists ++;
-                       }
-                       if (str[0] == ')')
-                       {
-                               current_depth--;
-                               if (current_depth == 0)
-                                       return numb_lists ;
-                       }
-                       str++;
-               }
-       }
-       return numb_lists ; // probably should give an error
-}
-
-
-// Find out how many points are in each sublist, put the result in the array npoints[]
-//  (for at most max_list sublists)
-//
-//  ( (L1),(L2),(L3) )  --> npoints[0] = points in L1,
-//                                 npoints[1] = points in L2,
-//                                 npoints[2] = points in L3
-//
-// We find these by, again, scanning through str looking for "(" and ")"
-// to determine the current depth.  We dont actually parse the points.
-
-bool   points_per_sublist( char *str, int32 *npoints, int32 max_lists)
-{
-       //scan through, noting depth and ","s
-
-       int     current_depth = 0;
-       int     current_list =-1 ;
-
-
-       while ( (str != NULL) && (str[0] != 0) )
-       {
-               str=strpbrk(str,"(),");  //find "(" or ")" or ","
-               if (str != NULL)
-               {
-                       if (str[0] == '(')
-                       {
-                               current_depth++;
-                               if (current_depth == 2)
-                               {
-                                       current_list ++;
-                                       if (current_list >=max_lists)
-                                               return TRUE;                    // too many sub lists found
-                                       npoints[current_list] = 1;
-                               }
-                               // might want to return an error if depth>2
-                       }
-                       if (str[0] == ')')
-                       {
-                               current_depth--;
-                               if (current_depth == 0)
-                                       return TRUE ;
-                       }
-                       if (str[0] == ',')
-                       {
-                               if (current_depth==2)
-                               {
-                                       npoints[current_list] ++;
-                               }
-                       }
-
-                       str++;
-               }
-       }
-       return TRUE ; // probably should give an error
-}
-
-
-
-
-//simple scan-forward to find the next "(" at the same level
-//  ( (), (),(), ),(...
-//                 + return this location
-char   *scan_to_same_level(char        *str)
-{
-
-       //scan forward in string looking for at "(" at the same level
-       // as the one its already pointing at
-
-               int     current_depth = 0;
-               bool  first_one=TRUE;
-
-
-       while ( (str != NULL) && (str[0] != 0) )
-       {
-               str=strpbrk(str,"()");
-               if (str != NULL)
-               {
-                       if (str[0] == '(')
-                       {
-                               if (!(first_one))
-                               {
-                                       if (current_depth == 0)
-                                               return str;
-                               }
-                               else
-                                       first_one = FALSE;  //ignore the first opening "("
-                               current_depth++;
-                       }
-                       if (str[0] == ')')
-                       {
-                               current_depth--;
-                       }
-
-                       str++;
-               }
-       }
-       return str ; // probably should give an error
-}
-
-
-/*
- *  BOX3D_in - takes a string rep of BOX3D and returns internal rep
- *
- *  example:
- *     "BOX3D(x1 y1 z1,x2 y2 z2)"
- * or  "BOX3D(x1 y1,x2 y2)"   z1 and z2 = 0.0
- *
- *
- */
-
-BOX3D  *parse_box3d(char *str)
-{
-
-       BOX3D      *bbox = (BOX3D *) palloc(sizeof(BOX3D));
-       bool            junk_bool;
-       bool       okay;
-       int             npoints;
-
-
-       //verify that there are exactly two points
-
-       //strip leading spaces
-       while (isspace((unsigned char) *str))
-               str++;
-//printf( "box3d_in gets '%s'\n",str);
-
-       if (strstr(str,"BOX3D") !=  str )
-       {
-                elog(ERROR,"BOX3D parser - doesnt start with BOX3D");
-                pfree(bbox);
-                return NULL;
-       }
-
-       if ((npoints = numb_points_in_list(str)) != 2)
-       {
-//printf("npoints in this bbox is %i, should be 2\n",npoints);
-                elog(ERROR,"BOX3D parser - number of points should be exactly 2");
-                pfree(bbox);
-                return NULL;
-       }
-
-       //want to parse two points, and dont care if they are 2d or 3d
-       okay =  parse_points_in_list(str, &(bbox->LLB), 2, &junk_bool);
-       if (okay == 0)
-       {
-               elog(ERROR,"box3d: couldnt parse: '%s'\n",str);
-               pfree(bbox);
-               return NULL;
-       }
-
-
-       //validate corners so LLB is mins of x,y,z and URT is maxs x,y,z
-       if (    bbox->LLB.x > bbox->URT.x)
-       {
-               swap ( &bbox->LLB.x , &bbox->URT.x ) ;
-       }
-       if (    bbox->LLB.y > bbox->URT.y)
-       {
-               swap ( &bbox->LLB.y , &bbox->URT.y );
-       }
-       if (    bbox->LLB.z > bbox->URT.z)
-       {
-               swap ( &bbox->LLB.z , &bbox->URT.z ) ;
-       }
-
-       return bbox;
-}
-
-PG_FUNCTION_INFO_V1(box3d_in);
-Datum box3d_in(PG_FUNCTION_ARGS)
-{
-       char       *str = PG_GETARG_CSTRING(0);
-       BOX3D      *bbox ;
-
-       bbox = parse_box3d(str);
-       if (bbox != NULL)
-               PG_RETURN_POINTER(bbox);
-       else
-               PG_RETURN_NULL();
-}
-
-/*
- *  Takes an internal rep of a BOX3D and returns a string rep.
- *
- *  example:
- *     "BOX3D(LLB.x LLB.y LLB.z, URT.x URT.y URT.z)"
- */
-PG_FUNCTION_INFO_V1(box3d_out);
-Datum box3d_out(PG_FUNCTION_ARGS)
-{
-       BOX3D  *bbox = (BOX3D *) PG_GETARG_POINTER(0);
-       int size;
-       char    *result;
-
-       if (bbox == NULL)
-       {
-               result = palloc(5);
-               strcat(result,"NULL");
-               PG_RETURN_CSTRING(result);
-       }
-
-       size = MAX_DIGS_DOUBLE*6+5+2+4+5+1;
-       result = (char *) palloc(size); //double digits+ "BOX3D"+ "()" + commas +null
-       sprintf(result, "BOX3D(%.15g %.15g %.15g,%.15g %.15g %.15g)",
-                       bbox->LLB.x,bbox->LLB.y,bbox->LLB.z,
-                       bbox->URT.x,bbox->URT.y,bbox->URT.z);
-
-       PG_RETURN_CSTRING(result);
-}
-
-/***************************************************************
- * these functions return the number of sub-objects inside a
- * sub-portion of a string.
- *
- * LINESTRING(), POLYGON(), POINT() allways have 1 sub object
- *
- * MULTIPOLYGON() MULTILINESTRING() MULTIPOINT() will have a variable number of sub-parts
- *           ex MULTIPOINT(1 1 1, 2 2 2,3 3 3,4 4 4) -->4 because there are 4 points in it
- *
- * GEOMETRYCOLLECTION() - need to look at each sub-object in the collection
- ***************************************************************/
-
-//number of object inside a point
-int objects_inside_point(char *str)
-{
-       return 1; //trivial points always have 1 point in them
-}
-
-
-//number of object inside a line
-int objects_inside_line(char *str)
-{
-       return 1; //trivial lines always have 1 line in them
-}
-
-//number of object inside a polygon
-int objects_inside_polygon(char *str)
-{
-       return 1; //trivial polygon always have 1 polygon in them
-}
-
-
-//bit more complicated - need to find out how many points are in this entity
-int objects_inside_multipoint(char *str)
-{
-       return numb_points_in_list(str);
-}
-
-//bit more complicated - need to find out how many lines are in this entity
-int objects_inside_multiline(char *str)
-{
-       return find_outer_list_length(str);
-}
-
-
-//bit more complicated - need to find out how many polygons are in this entity
-int objects_inside_multipolygon(char *str)
-{
-       return find_outer_list_length(str);
-}
-
-
-
-//This one is more complicated, we have to look at each of the sub-object inside
-// the collection.
-//  result = sum of ( number of objects in each of the collection's sub-objects )
-//
-// EX:   'GEOMETRYCOLLECTION( POINT(1 2 3),
-//     POINT (4 5 6) ),
-//     LINESTRING(3 4 5,1 2 3,5 6 0),
-//     MULTILINESTRING((3 4 5,1 2 3,5 6 0)),
-//     MULTIPOINT(1 2 3),
-//     MULTILINESTRING((3 4 5,1 2 3,5 6 0),(1 2 0,4 5 0,6 7 0,99 99 0)),
-//     MULTIPOLYGON ((  (3 4 5,1 2 3,5 6),(1 2, 4 5, 6 7)  ), ( (11 11, 22 22, 33 33),(44 44, 55 55, 66 66) ) )'
-//
-//     # object = # of objs in POINT (1) + # of objs in POINT (1) +   # of objs in LINESTRING (1)
-//                     + # of objs in MULTILINESTRING (1) + # of objs in MULTIPOINT  (1)
-//                     + # of objs in MULTILINESTRING (1) + # of objs in  MULTIPOLYGON  (2)
-
-int objects_inside_collection(char *str)
-{
-       int             tally = 0;
-       int             sub_size = 0;
-
-       //skip past the "geometrycollection" at begining of string
-       str += 18;
-       if (strstr(str, "GEOMETRYCOLLECTION") != NULL)
-               return -1; // collection inside collection; bad boy!
-
-       //we scan to the first letter, then pass it to objects inside
-       // to find out how many sub-objects there are.  Then move to
-       // the next object
-
-
-       while ( str != NULL)
-       {
-               //scan for a letter  (all objs start with M, P, or L
-               str = strpbrk(str,"MPL"); //search for MULTI*, POLY*, POIN*
-               if (str != NULL)
-               {
-                       //object found
-                       sub_size = objects_inside(str); //how many in this object
-                       if (sub_size == -1)
-                               return -1;//relay error
-
-                       tally += sub_size;      // running total
-
-                       //need to move to next item
-                       // by scanning past any letters
-                       str = strchr(str,'(');  //need to move to the next sub-object
-               }
-       }
-       return tally;
-}
-
-
-// Find the # of sub-objects inside the geometry
-//     Just pass it off to the other functions
-int objects_inside(char *str)
-{
-
-       char            *parenth;
-       char            *loc;
-
-
-       parenth = strchr(str,'(');
-       if (parenth == NULL)
-               return -1; //invalid string
-
-       // look only at the begining of the string
-       // the order of these "if" are important!
-
-       if (  ((loc = strstr(str, "GEOMETRYCOLLECTION")) != NULL) && (loc < parenth) )
-               return objects_inside_collection(str);
-
-       // do multi before base types (MULTIPOINT has the string "POINT" in it)
-
-       if (((loc = strstr(str,"MULTIPOINT")) != NULL) && (loc < parenth) )
-               return objects_inside_multipoint(str);
-       if (((loc = strstr(str,"MULTILINESTRING") )!= NULL) && (loc < parenth) )
-               return objects_inside_multiline(str);
-       if (((loc = strstr(str,"MULTIPOLYGON")) != NULL) && (loc < parenth) )
-               return objects_inside_multipolygon(str);
-
-       //base types
-       if (((loc = strstr(str,"POINT")) != NULL) && (loc < parenth) )
-               return objects_inside_point(str);
-       if (((loc = strstr(str,"LINESTRING")) != NULL) && (loc < parenth) )
-               return objects_inside_line(str);
-       if (((loc = strstr(str,"POLYGON")) != NULL) && (loc < parenth) )
-               return objects_inside_polygon(str);
-
-       return -1; //invalid
-
-}
-
-
-/****************************************************************************
- *  These functions actually parse the objects in the strings
- *  They all have arguments:
- *     obj_size[]  -- size (in bytes) of each the sub-objects
- *    objs[][]    -- list of pointers to the actual objects
- *    obj_types   -- type of the sub-obj (see postgis.h)
- *    nobjs       -- max number of sub-obj
- *    str              -- actual string to parse from (start at begining)
- *    offset      -- which sub-object # are we dealing with
- *    is3d     -- are any of the points in the object 3d?
- *
- *    basically, each of the functions will:
- *             + parse str to find the information required
- *             + allocate a new obj(s) and place it/them in objs to hold this info
- *             + set the obj_size for this/these sub-object
- *             + set the obj_type for this/these sub-object
- *             + increase offset so the next objects will go in the correct place
- *             + set is3d if there are any 3d points in the sub-object
- *             + return FALSE if an error occured
- ****************************************************************************/
-
-
-//parse a point - make a new POINT3D object
-bool parse_objects_inside_point(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found
-
-       objs[*offset] = palloc (sizeof(POINT3D) );
-       memset(objs[*offset], 0, sizeof(POINT3D) ); // zero memory
-       obj_types[*offset] = POINTTYPE;
-       obj_size[*offset] = sizeof(POINT3D);
-
-       str = strchr(str,'(');
-       if (str == NULL)
-               return FALSE;  // parse error
-
-//printf("about to parse the point\n");
-
-       result = parse_points_in_list_exact(str, (POINT3D*) objs[*offset] , 1, is3d);
-//printf("     +point parsed\n");
-
-       *offset = *offset + 1;
-       return (result); // pass along any parse error
-}
-
-
-//parse a multipoint object - offset may increase by >1
-// multiple sub object may be created
-bool parse_objects_inside_multipoint(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-       int     npoints;
-       int     t;
-       POINT3D *pts;
-
-       // first find out how many points are in the multi-point
-       npoints = objects_inside_multipoint(str);
-
-       if (npoints <0)
-               return FALSE; // error in parsing (should have been caught before)
-
-       if (npoints ==0)
-               return TRUE;  //no points, no nothing
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found dont do anything, relay error
-
-
-       str = strchr(str,'(');
-       if (str == NULL)
-               return FALSE;
-
-               //allocate all the new objects
-       pts = palloc( sizeof(POINT3D) * npoints);
-       for (t=0;t<npoints; t++)
-       {
-               objs[*offset + t] = palloc( sizeof(POINT3D) );
-               memset(objs[*offset+t], 0, sizeof(POINT3D) ); // zero memory
-
-               obj_types[*offset+t] = POINTTYPE;
-               obj_size[*offset+t] = sizeof(POINT3D);
-       }
-
-       //actually do the parsing into a temporary list
-       result = parse_points_in_list_exact(str, pts , npoints, is3d);
-
-
-       if (!(result))
-       {
-               pfree(pts);
-               return FALSE; //relay error
-       }
-
-       for(t=0;t<npoints;t++)
-       {
-               memcpy(objs[*offset+t], &pts[t], sizeof(POINT3D) );
-       }
-
-       pfree(pts);
-       *offset = *offset + npoints;
-       return (result);
-}
-
-
-//parse a linestring
-bool parse_objects_inside_line(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-       int     num_points;
-       bool    add_point = FALSE; // only 1 point --> make it two on top of each other
-
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found
-
-       //how many points are in this linestring?
-       num_points = numb_points_in_list(str);
-
-       if (num_points == 0)
-               return FALSE;
-
-
-       if (num_points == 1)    //not really a line
-       {
-               num_points  = 2;
-               add_point = TRUE;
-       }
-
-
-
-                                                       // -1 because object already has 1 point in it
-               objs[*offset] = palloc (sizeof(LINE3D) + sizeof(POINT3D)*(num_points-1) );
-               memset(objs[*offset], 0, sizeof(LINE3D) + sizeof(POINT3D)*(num_points-1)  ); // zero memory
-
-       obj_types[*offset] = LINETYPE;
-       obj_size[*offset] = sizeof(LINE3D) + sizeof(POINT3D)*(num_points-1) ;
-
-       str = strchr(str,'(');
-       if (str == NULL)
-               return FALSE;
-
-       ( (LINE3D *) objs[*offset] )->npoints = num_points;
-
-       if (add_point)
-       {
-               result = parse_points_in_list_exact(str, &(( (LINE3D*) objs[*offset]) ->points[0]) , num_points-1, is3d);
-       }
-       else
-       {
-               result = parse_points_in_list_exact(str, &(( (LINE3D*) objs[*offset]) ->points[0]) , num_points, is3d);
-       }
-
-       if (add_point)
-       {
-               memcpy( &(( (LINE3D*) objs[*offset]) ->points[1])   , &(( (LINE3D*) objs[*offset]) ->points[0])  , sizeof(POINT3D) );
-       }
-
-       *offset = *offset + 1;
-       return (result);
-}
-
-
-
-//parse a multi-line.  For each sub-linestring, call the parse_objects_inside_line() function
-//     'MULTILINESTRING((3 4 5,1 2 3,5 6 0),(1 2 0,4 5 0,6 7 0,99 99 0))'
-// first scan to the second "(" - this is the begining of the first linestring.
-// scan it, then move to the second linestring
-bool parse_objects_inside_multiline(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-       int     num_lines;
-       int     t;
-
-
-               //how many lines are there?
-       num_lines = objects_inside_multiline(str);
-
-
-       if (num_lines <0)
-               return FALSE;
-
-       if (num_lines ==0)
-               return TRUE;    //can be nothing
-
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found
-
-       str= strchr(str,'('); //first one
-       if (str != NULL)
-               str++;
-       str= strchr(str,'('); //2nd one
-
-       if (str == NULL)
-               return FALSE;  // couldnt find it
-
-       for (t=0;t<num_lines; t++)
-       {
-                       //pass along the work - it will update offset for us
-               result = parse_objects_inside_line(obj_size,objs, obj_types,nobjs, str,offset,is3d);
-               if (!(result))
-                       return FALSE;//relay error
-               if (str != NULL)
-                       str++;  // go past the first '(' in the linestring
-               else
-                       return FALSE; //parse error
-               str = strchr(str,'('); // go to the beginning of the next linestring
-       }
-
-       return (TRUE);  //everything okay
-}
-
-//parse a polygon
-//     POLYGON (  (3 4 5,1 2 3,5 6),(1 2, 4 5, 6 7)  )'
-
-
-bool parse_objects_inside_polygon(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-       int     num_rings;
-       int32   *npoints;
-       int32   sum_points,points_offset;
-       int     t;
-       int     size;
-       POINT3D *pts;
-       POLYGON3D       *polygon;
-
-
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found
-
-               //find out how many rings there are
-       num_rings = find_outer_list_length(str);
-
-       if (num_rings <1)
-               return FALSE; // must have at least one ring
-
-               //allocate space for how many points in each ring
-       npoints = palloc( sizeof(int32) * num_rings);
-
-               //find out how many points are in each sub-list (ring)
-       result = points_per_sublist(str,npoints, num_rings);
-
-               //how many points are inside this polygon in total?
-       sum_points =0;
-       for(t=0;  t< num_rings ; t++)
-       {
-               sum_points += npoints[t];
-               if (npoints[t] <3)
-               {
-                       elog(ERROR,"polygon has ring with <3 points.");
-                       pfree(npoints);
-                       return FALSE;
-               }
-       }
-
-               //now we can allocate the structure
-
-
-                       // -1 because the POLYGON3D already has space for 1 ring with 1 point
-                       // 4 is for possible double-word alignment
-       size = sizeof(POLYGON3D) + sizeof(int32)*(num_rings-1) +4+ sizeof(POINT3D)*(sum_points-1)  ;
-       objs[*offset] = palloc (size);
-               memset(objs[*offset], 0, size  ); // zero memory
-
-       polygon = (POLYGON3D *) objs[*offset];
-       obj_types[*offset] = POLYGONTYPE;
-       obj_size[*offset] = size;
-
-       str = strchr(str,'(');
-       if (str == NULL)
-       {
-               pfree(npoints);
-               return FALSE;
-       }
-       str++;
-
-       polygon->nrings = num_rings;
-
-               pts = (POINT3D *)  &(polygon->npoints[num_rings]); //pts[] is just past the end of npoints[]
-
-                       // make sure its double-word aligned
-
-               pts = (POINT3D *) MAXALIGN(pts);
-
-
-//printf("POLYGON is at %p, size is %i, pts is at %p (%i)\n",objs[*offset],size, pts, ((void *) pts) - ((void *)objs[*offset]) );
-//printf("npoints[0] is at %p, num_rings=%i\n", &(((POLYGON3D *) objs[*offset])->npoints[0] ), num_rings );
-
-       points_offset = 0;
-       for(t=0;t<num_rings;t++)        //for each ring
-       {
-               //set num points in this obj
-               polygon->npoints[t] = npoints[t]; // set # pts in this ring
-
-                       //use exact because it will screw up otherwise
-//printf("about to parse the actual points in ring #%i with %i points:\n",t,npoints[t]);
-               result = parse_points_in_list_exact(str,
-                                       &pts[points_offset],
-                                       npoints[t], is3d);
-//printf("     +done parsing points\n");
-
-//printf("1st points in ring is: [%g,%g,%g]\n", pts[points_offset].x ,pts[points_offset].y ,pts[points_offset].z );
-
-               if (!(result))
-               {
-                       pfree(npoints);
-                       return FALSE;   //relay error
-               }
-
-               //first and last point are the same
-               if (!  (FPeq(pts[points_offset].x , pts[points_offset + npoints[t]-1].x  )
-                        &&FPeq(pts[points_offset].y , pts[points_offset + npoints[t]-1].y   )
-                        &&FPeq(pts[points_offset].z , pts[points_offset + npoints[t]-1].z   )    )   )
-               {
-                       elog(ERROR,"polygon has ring where first point != last point");
-                       pfree(npoints);
-                       return FALSE; //invalid poly
-               }
-
-
-               points_offset += npoints[t]; //where to stick points in the next ring
-
-               str = strchr(str,'('); // where is the next ring
-               if (str == NULL)
-               {
-                       pfree(npoints);
-                       return FALSE;  //relay parse error
-               }
-               str++;
-       }
-
-       pfree(npoints);
-       *offset = *offset + 1;
-       return (result);
-}
-
-
-//     MULTIPOLYGON ((  (3 4 5,1 2 3,5 6),(1 2, 4 5, 6 7)  ), ( (11 11, 22 22, 33 33),(44 44, 55 55, 66 66) ) )'
-//     pass off work to parse_objects_inside_polygon()
-
-bool parse_objects_inside_multipolygon(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result;
-       int     num_polys;
-       int     t;
-
-       num_polys = objects_inside_multipolygon(str);  //how many polygons are inside me?
-
-//printf("parse_objects_inside_multipolygon('%s')\n",str);
-
-       if (num_polys <0)
-               return FALSE;
-
-       if (num_polys ==0)
-               return TRUE;    //ask for nothing, get nothing
-
-       if (*offset >= nobjs)
-               return FALSE;     //too many objs found
-
-       str= strchr(str,'('); //first one (begining of list of polys)
-       if (str != NULL)
-       {
-               str++;
-               str= strchr(str,'('); //2nd one (beginning of 1st poly)
-       }
-       if (str == NULL)
-               return FALSE;   //relay error
-
-       for (t=0;t<num_polys; t++)
-       {
-               if (str == NULL)
-                       return FALSE;   //relay error
-//printf("parse_inside_multipolygon: parsing a polygon #%i\n",t);
-               result = parse_objects_inside_polygon(obj_size,objs, obj_types,nobjs, str,offset,is3d);
-               if (!(result))
-                       return FALSE;   //relay error
-
-               //scan ahead to next "(" start of next polygon
-               str = scan_to_same_level(str);
-       }
-       return (TRUE);
-}
-
-
-// relay work to the above functions
-bool parse_objects(int32 *obj_size,char **objs,int32   *obj_types,int32 nobjs,char *str, int *offset, bool *is3d)
-{
-               char            *parenth;
-               char            *loc;
-
-
-//printf("parse_objects: parsing object offset=%i\n",*offset);
-
-       if (str == NULL)
-               return FALSE;
-
-       parenth = strchr(str,'(');
-       if  (parenth == NULL)
-               return FALSE; //invalid string
-
-
-       if (  ((loc = strstr(str, "GEOMETRYCOLLECTION")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_collection(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-
-       if (((loc = strstr(str,"MULTIPOINT")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_multipoint(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-
-       if (((loc = strstr(str,"MULTILINESTRING") )!= NULL) && (loc < parenth) )
-               return parse_objects_inside_multiline(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-
-       if (((loc = strstr(str,"MULTIPOLYGON")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_multipolygon(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-       if (((loc = strstr(str,"POINT")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_point(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-
-       if (((loc = strstr(str,"LINESTRING")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_line(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-       if (((loc = strstr(str,"POLYGON")) != NULL) && (loc < parenth) )
-               return parse_objects_inside_polygon(obj_size,objs, obj_types, nobjs, str, offset, is3d);
-
-
-       return FALSE; //invalid
-
-}
-
-
-
-//look for each of the object inside a collection, and send the work to parse it along
-bool parse_objects_inside_collection(int32 *obj_size,char **objs, int32 *obj_types, int32 nobjs, char *str, int *offset, bool* is3d)
-{
-       bool    result = FALSE;
-
-       str += 18; //scan past "geometrycollection"
-       if (strstr(str, "GEOMETRYCOLLECTION") != NULL)
-               return FALSE; // collection inside collection; bad boy!
-
-       while ( str != NULL)
-       {
-               //scan for a letter
-               str = strpbrk(str,"MPL"); //search for MULTI*, POLY*, POIN*
-               if (str != NULL)
-               {
-                       //object found
-                       result = parse_objects(obj_size,objs,obj_types,nobjs,str, offset, is3d);
-
-                       if (result == FALSE)
-                               return FALSE;//relay error
-
-                       //prepare to move to next item
-                       // by scanning past any letters
-                       str = strchr(str,'(');
-               }
-       }
-       return result;
-}
-
-/**************************************************************
- * Find the bounding box3d of a sub-object
- **************************************************************/
-
-//simple box encloses a point
-BOX3D  *bbox_of_point(POINT3D *pt)
-{
-       BOX3D           *the_box = (BOX3D *) palloc (sizeof(BOX3D));
-
-       the_box->LLB.x = pt->x;
-       the_box->LLB.y = pt->y;
-       the_box->LLB.z = pt->z;
-
-       the_box->URT.x = pt->x;
-       the_box->URT.y = pt->y;
-       the_box->URT.z = pt->z;
-
-       return the_box;
-}
-
-// box encloses all the points in all the rings
-BOX3D  *bbox_of_polygon(POLYGON3D *polygon)
-{
-               BOX3D           *the_box ;
-               int             numb_points =0,i;
-               POINT3D *pts,*pt;
-
-       for (i=0; i<polygon->nrings; i++)
-       {
-               numb_points +=  polygon->npoints[i];
-       }
-
-       if (numb_points <1)
-               return NULL;
-
-       pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] )  );
-       pts = (POINT3D *) MAXALIGN(pts);
-
-       the_box = bbox_of_point(&pts[0]);
-
-       for (i=1; i<numb_points;i++)
-       {
-               pt = &pts[i];
-
-               if (pt->x < the_box->LLB.x)
-                       the_box->LLB.x = pt->x;
-
-               if (pt->y < the_box->LLB.y)
-                       the_box->LLB.y = pt->y;
-
-               if (pt->z < the_box->LLB.z)
-                       the_box->LLB.z = pt->z;
-
-               if (pt->x > the_box->URT.x)
-                       the_box->URT.x = pt->x;
-
-               if (pt->y > the_box->URT.y)
-                       the_box->URT.y = pt->y;
-
-               if (pt->z > the_box->URT.z)
-                       the_box->URT.z = pt->z;
-
-       }
-       return the_box;
-}
-
-//box encloses points in line
-BOX3D  *bbox_of_line(LINE3D *line)
-{
-       BOX3D           *the_box;
-       POINT3D *pt;
-       int i;
-
-       if (line->npoints <1)
-       {
-               return NULL;
-       }
-       the_box = bbox_of_point(&line->points[0]);
-
-       for (i=1;i< line->npoints; i++)
-       {
-               pt = &line->points[i];
-               if (pt->x < the_box->LLB.x)
-                       the_box->LLB.x = pt->x;
-
-               if (pt->y < the_box->LLB.y)
-                       the_box->LLB.y = pt->y;
-
-               if (pt->z < the_box->LLB.z)
-                       the_box->LLB.z = pt->z;
-
-               if (pt->x > the_box->URT.x)
-                       the_box->URT.x = pt->x;
-
-               if (pt->y > the_box->URT.y)
-                       the_box->URT.y = pt->y;
-
-               if (pt->z > the_box->URT.z)
-                       the_box->URT.z = pt->z;
-       }
-       return the_box;
-}
-
-//merge box a and b (expand b)
-//if b is null, new one is returned
-// otherwise b is returned
-BOX3D *union_box3d(BOX3D *a, BOX3D *b)
-{
-       if (a==NULL)
-               return NULL;
-       if (b==NULL)
-       {
-               b=(BOX3D*) palloc(sizeof(BOX3D));
-               memcpy(b,a,sizeof(BOX3D) );
-               return b;
-       }
-
-
-       if (a->LLB.x < b->LLB.x)
-               b->LLB.x = a->LLB.x;
-       if (a->LLB.y < b->LLB.y)
-               b->LLB.y = a->LLB.y;
-       if (a->LLB.z < b->LLB.z)
-               b->LLB.z = a->LLB.z;
-
-       if (a->URT.x > b->URT.x)
-               b->URT.x = a->URT.x;
-       if (a->URT.y > b->URT.y)
-               b->URT.y = a->URT.y;
-       if (a->URT.z > b->URT.z)
-               b->URT.z = a->URT.z;
-       return b;
-}
-
-BOX3D  *bbox_of_geometry(GEOMETRY *geom)
-{
-       int     i;
-       int32   *offsets;
-       char    *obj;
-       BOX3D   *result=NULL;
-       BOX3D   *a_box;
-
-//printf("bbox_of_geometry(%p)\n", geom);
-
-       if (geom->nobjs <1)
-               return NULL;    //bbox of 0 objs is 0
-
-       //where are the objects living?
-       offsets = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-
-       //for each sub-object
-       for(i=0; i<geom->nobjs;i++)
-       {
-               obj = (char *) geom +offsets[i] ;
-
-
-               if (geom->objType[i] == POINTTYPE)
-               {
-//printf("box of a point\n");
-                       a_box = bbox_of_point(  (POINT3D *) obj);
-                       result= union_box3d(a_box  ,result);
-
-                       if (a_box != NULL)
-                               pfree (a_box);
-               }
-               if (geom->objType[i] == LINETYPE)
-               {
-//printf("box of a line, # points = %i\n",((LINE3D *) obj)->npoints );
-                       a_box = bbox_of_line(  (LINE3D *) obj);
-                       result = union_box3d(a_box  ,result);
-                       if (a_box != NULL)
-                               pfree (a_box);
-               }
-               if (geom->objType[i] == POLYGONTYPE)
-               {
-//printf("box of a polygon\n");
-                       a_box = bbox_of_polygon(  (POLYGON3D *) obj);
-                       result =union_box3d(a_box  ,result);
-                       if (a_box != NULL)
-                               pfree (a_box);
-               }
-       }
-       return result;
-}
-
-
-//given wkt and SRID, return a geometry
-//actually we cheat, postgres will convert the string to a geometry for us...
-PG_FUNCTION_INFO_V1(geometry_from_text);
-Datum geometry_from_text(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32                           SRID;
-
-       GEOMETRY        *result;
-
-       if ( ! PG_ARGISNULL(1) )
-               SRID = PG_GETARG_INT32(1);
-       else
-               SRID = -1;
-
-
-       result = (GEOMETRY *) palloc(geom1->size);
-       memcpy(result,geom1, geom1->size);
-
-       if (result != NULL)
-       {
-               result->SRID = SRID;
-       }
-       else
-       {
-               PG_RETURN_NULL();
-       }
-       PG_RETURN_POINTER(result);
-}
-
-
-
-// Parse a geometry object
-//
-// 1. Find information on how many sub-object there are
-// 2. create a group of sub-object and populate them
-// 3. make a large structure & populate with all the above info.
-//
-//
-PG_FUNCTION_INFO_V1(geometry_in);
-Datum geometry_in(PG_FUNCTION_ARGS)
-{
-               char       *str = PG_GETARG_CSTRING(0);
-               GEOMETRY        *geometry;
-               BOX3D           *the_bbox;
-               int32           nobjs;
-               char            **objs;
-               int32           *obj_types;
-               int32           *obj_size;
-               int             entire_size;
-               bool            is3d = FALSE;
-               bool            okay;
-               int             next_loc;
-               int32           *offsets;
-               int             t;
-               int             obj_parse_offset;
-               int             nitems;
-               int32           SRID;
-               double  scale,offx,offy;
-               BOX3D   *mybox;
-
-//printf("str=%s\n",str);
-
-
-
-               //trim white
-       while (isspace((unsigned char) *str))
-               str++;
-
-       //test to see if it starts with a SRID=
-
-       SRID = -1;
-       scale = offx = offy = 0;
-
-       if (strstr(str,"SRID="))
-       {
-               //its spatially located
-               nitems = sscanf(str,"SRID=%i;",&SRID);
-               if (nitems !=1 )
-               {
-                       //error
-                       elog(ERROR,"couldnt parse objects in GEOMETRY (SRID related)");
-                       PG_RETURN_NULL() ;
-               }
-               //delete first part of string
-               str = strchr(str,';');
-               if (str != NULL)
-                       str++;
-               else
-               {
-                       elog(ERROR,"couldnt parse objects in GEOMETRY (SRID related - no ';')");
-                       PG_RETURN_NULL() ;
-               }
-       }
-
-
-       if (strstr(str,"EMPTY"))
-       {
-               GEOMETRY *result=makeNullGeometry( SRID);
-               if (strstr(str,"MULTIPOLYGON"))
-                       result->type = MULTIPOLYGONTYPE;
-               if (strstr(str,"MULTILINESTRING"))
-                       result->type = MULTILINETYPE;
-               if (strstr(str,"MULTIPOINT"))
-                       result->type = MULTIPOINTTYPE;
-               PG_RETURN_POINTER( result );
-       }
-
-       if (strstr(str,"BOX3D") != NULL ) // bbox only
-       {
-
-
-               mybox = parse_box3d(str);
-
-               if (mybox == NULL)
-                       PG_RETURN_NULL() ;
-
-               geometry = (GEOMETRY *) palloc(sizeof(GEOMETRY));
-               geometry->size = sizeof(GEOMETRY);
-               geometry->type = BBOXONLYTYPE;
-               geometry->nobjs = -1;
-               geometry->SRID = SRID;
-               geometry->scale = 1.0;
-               geometry->offsetX = 0.0;
-               geometry->offsetY = 0.0;
-               memcpy(&(geometry->bvol),mybox, sizeof(BOX3D) );
-
-               pfree(mybox);
-               PG_RETURN_POINTER(geometry);
-       }
-
-
-       if ((str==NULL) || (strlen(str) == 0) )
-       {
-               elog(ERROR,"couldnt parse objects in GEOMETRY (null string)\n");
-               PG_RETURN_NULL() ;
-       }
-
-       // handle the 2 variants of MULTIPOINT - 'MULTIPOINT(0 0, 1 1)'::geometry and 'MULTIPOINT( (0 0), (1 1))'::geometry;
-
-               // we cheat - if its the 2nd variant, we replace the internal parethesis with spaces!
-                       if (strstr(str,"MULTIPOINT") != NULL )
-                       {
-                               //its a multipoint - replace any internal parenthesis with spaces
-                               char *first_paren;
-                               char *last_paren;
-                               char *current_paren;
-
-                               first_paren= strchr (str,'(');
-                               last_paren = strrchr(str,')');
-
-                               if  ( (first_paren == NULL) || (last_paren == NULL) || (first_paren >last_paren) )
-                               {
-                                               elog(ERROR,"couldnt parse objects in GEOMETRY (parenthesis related)\n");
-                                               PG_RETURN_NULL() ;
-                               }
-                               //now we can just got through the string
-                               for (current_paren = (first_paren+1); current_paren <(last_paren);current_paren++)
-                               {
-                                       if ( (current_paren[0] ==')') || (current_paren[0]=='(') )
-                                       {
-                                               current_paren[0] = ' ';
-                                       }
-                               }
-
-                       }
-
-
-//elog (NOTICE,"in:%s\n", str);
-
-//printf("geometry_in got string ''\n");
-
-       nobjs=  objects_inside(str);  //how many sub-objects
-       if (nobjs <=0)  //dont allow zero-object items
-       {
-               elog(ERROR,"couldnt parse objects in GEOMETRY\n");
-               PG_RETURN_NULL() ;
-       }
-
-//printf("geometry_in determins that there are %i sub-objects\n",nobjs);
-
-       //allocate enough space for info structures
-
-
-       objs = palloc(sizeof( char *) * nobjs);
-       memset(objs, 0, sizeof( char *) * nobjs);
-
-       obj_types = palloc(sizeof(int32) * nobjs);
-       memset(obj_types, 0, sizeof(int32) * nobjs);
-
-       obj_size  = palloc(sizeof(int32) * nobjs);
-       memset(obj_size, 0, sizeof(int32) * nobjs);
-
-       obj_parse_offset = 0; //start populating obj list at beginning
-
-
-//printf("     +about to parse the objects\n");
-
-
-       okay = parse_objects(obj_size,objs,obj_types,nobjs,str,&obj_parse_offset , &is3d);
-
-//printf("     +finished parsing object\n");
-
-       if (!(okay) || (obj_parse_offset != nobjs ) )
-       {
-               //free
-               for (t =0; t<nobjs; t++)
-               {
-                       if (objs[t] != NULL)
-                               pfree (objs[t]);
-               }
-               pfree(objs); pfree(obj_types); pfree(obj_size);
-               elog(ERROR,"couldnt parse object in GEOMETRY\n");
-               PG_RETURN_NULL();
-       }
-
-       entire_size = sizeof(GEOMETRY);
-
-       for (t =0; t<nobjs; t++)
-       {
-               //do they all have an obj_type?
-               if ( (obj_types[t] == 0) || (objs[t] == NULL) )
-               {
-                       okay = FALSE;
-               }
-               entire_size += obj_size[t];  //total space of the objects
-
-               //size seem reasonable?
-               if (obj_size[t] <1)
-               {
-                       okay = FALSE;
-               }
-
-       }
-       if (!(okay) )
-       {
-               for (t =0; t<nobjs; t++)
-               {
-                       if (objs[t] != NULL)
-                               pfree (objs[t]);
-               }
-               pfree(objs); pfree(obj_types); pfree(obj_size);
-               elog(ERROR,"couldnt parse object in GEOMETRY\n");
-               PG_RETURN_NULL();
-       }
-
-               //size = object size + space for object type & offset array and possible double-word boundary stuff
-       entire_size = entire_size + sizeof(int32) *nobjs*2 + nobjs*4;
-       geometry = (GEOMETRY *) palloc (entire_size);
-
-       geometry->size = entire_size;
-
-       //set collection type.  Need to differentiate between
-       //  geometrycollection and (say) multipoint
-
-       if (   strstr(str, "GEOMETRYCOLLECTION") != NULL  )
-               geometry->type = COLLECTIONTYPE;
-       else
-       {
-               if (   strstr(str, "MULTI") != NULL  )
-               {
-                       if (obj_types[0] == POINTTYPE)
-                               geometry->type = MULTIPOINTTYPE;
-                       if (obj_types[0] == LINETYPE)
-                               geometry->type = MULTILINETYPE;
-                       if (obj_types[0] == POLYGONTYPE)
-                               geometry->type = MULTIPOLYGONTYPE;
-               }
-               else
-               {
-                       geometry->type = obj_types[0]; //single object
-               }
-       }
-
-       geometry->is3d = is3d;    //any 3d points found anywhere?
-       geometry->nobjs = nobjs; // sub-objects
-
-
-       //copy in type and length info
-
-                       //where to put objects.  next_loc will point to (bytes forward) &objData[0]
-               next_loc = ( (char *) &(geometry->objType[0] ) - (char *) geometry);
-               next_loc += sizeof(int32) * 2* nobjs;
-
-               next_loc = MAXALIGN(next_loc);
-
-
-
-               //where is the offsets array
-               offsets = (int32 *) ( ((char *) &(geometry->objType[0] ))+ sizeof(int32) * nobjs ) ;
-
-
-//printf("structure is at %p, offsets is at %p, next_loc = %i\n",geometry, offsets, next_loc);
-
-       for (t=0; t<nobjs; t++) //for each object
-       {
-               geometry->objType[t] = obj_types[t];  //set its type
-
-               offsets[t] = next_loc;  //where is it
-//printf("copy %i bytes from %p to %p\n",      obj_size[t] ,  objs[t],(char *) geometry + next_loc);
-               memcpy( (char *) geometry + next_loc, objs[t], obj_size[t] );   //put sub-object into object
-               pfree(objs[t]); // free the original object (its redundant)
-
-               next_loc += obj_size[t];        //where does the next object go?
-
-               next_loc =  MAXALIGN(next_loc);
-
-
-       }
-
-       //free temporary structures
-       pfree(objs); pfree(obj_types); pfree(obj_size);
-
-
-       //calculate its bounding volume
-       the_bbox = bbox_of_geometry(geometry);
-
-       if (the_bbox != NULL)
-       {
-               memcpy( &geometry->bvol, the_bbox, sizeof(BOX3D) );
-               pfree(the_bbox);
-       }
-
-
-//printf("returning from geometry_in, nobjs = %i\n", nobjs);
-
-
-               geometry->SRID = SRID;
-               geometry->scale = scale;
-               geometry->offsetX = offx;
-               geometry->offsetY = offy;
-       PG_RETURN_POINTER(geometry);
-}
-
-PG_FUNCTION_INFO_V1(srid_geom);
-Datum srid_geom(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_INT32(geom1->SRID);
-}
-
-
-//Take internal rep of geometry, output string in the form of
-//  'SRID=%i;<wkt>'  ie.  'SRID=5;POINT(1 1)'
-PG_FUNCTION_INFO_V1(geometry_out);
-Datum geometry_out(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               char                            *wkt;
-               char                            *result;
-               int                             len;
-
-               wkt = geometry_to_text(geom1);
-
-               len = strlen(wkt) + 6+ 25 + 1;
-               result = palloc(len);//extra space for SRID
-               memset(result, 0, len); //zero everything out
-
-               sprintf(result,"SRID=%i;%s",geom1->SRID,wkt);
-
-               pfree(wkt);
-
-               PG_RETURN_CSTRING(result);
-
-}
-
-//Take internal rep of geometry, output string
-PG_FUNCTION_INFO_V1(astext_geometry);
-Datum astext_geometry(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                       *wkt;
-       char                       *result;
-       int                     len;
-
-       wkt = geometry_to_text(geom1);
-
-                       //changed so it isnt null terminated (not needed with text)
-       len = strlen(wkt) + 4;
-
-       result= palloc(len);
-       *((int *) result) = len;
-
-       memcpy(result +4, wkt, len-4);
-
-       pfree(wkt);
-
-       PG_RETURN_CSTRING(result);
-}
-
-
-//Take internal rep of geometry, output string
-
-
-//takes a GEOMETRY and returns a WKT representation
-char *geometry_to_text(GEOMETRY  *geometry)
-{
-       char            *result;
-       int             t,u;
-       int32           *offsets;
-       char            *obj;
-       POINT3D *pts;
-       POLYGON3D       *polygon;
-       LINE3D  *line;
-       POINT3D *point;
-
-       int             pt_off,size;
-       bool            briefmode= TRUE; // ie. dont print out "POINT3D(..)", just print out the ".." part
-       bool            is3d;
-       bool            first_sub_obj = TRUE;
-       bool            multi_obj = FALSE;
-       int             mem_size,npts;
-
-
-       if (geometry->nobjs == 0)
-       {
-                       //empty geometry
-               result = (char*) palloc(30);
-
-               sprintf(result,"GEOMETRYCOLLECTION(EMPTY)");
-
-               if (geometry->type == MULTILINETYPE)
-                       sprintf(result,"MULTILINESTRING(EMPTY)");
-               if (geometry->type == MULTIPOINTTYPE)
-                       sprintf(result,"MULTIPOINT(EMPTY)");
-               if (geometry->type == MULTIPOLYGONTYPE)
-                       sprintf(result,"MULTIPOLYGON(EMPTY)");
-               return result;
-       }
-
-
-//printf("in geom_out(%p)\n",geometry);
-
-       size = 30;      //just enough to put in object type
-       result = (char *) palloc(30); mem_size= 30;       //try to limit number of repalloc()s
-
-       if (geometry->type == BBOXONLYTYPE)
-       {
-                       mem_size = MAX_DIGS_DOUBLE*6+5+2+4+5+1;
-                       pfree(result);
-                       result = (char *) palloc(mem_size); //double digits+ "BOX3D"+ "()" + commas +null
-                       sprintf(result, "BOX3D(%.15g %.15g %.15g,%.15g %.15g %.15g)",
-                                       geometry->bvol.LLB.x,geometry->bvol.LLB.y,geometry->bvol.LLB.z,
-                                       geometry->bvol.URT.x,geometry->bvol.URT.y,geometry->bvol.URT.z);
-               return result;
-       }
-
-
-       if (geometry->type == POINTTYPE)
-       {
-               multi_obj = FALSE;
-               sprintf(result, "POINT(" );
-       }
-       else if (geometry->type == LINETYPE)
-       {
-               multi_obj = FALSE;
-               sprintf(result, "LINESTRING" );
-       }
-       else if (geometry->type == POLYGONTYPE)
-       {
-               multi_obj = FALSE;
-               sprintf(result, "POLYGON" );
-       }
-       else if (geometry->type == MULTIPOINTTYPE)
-       {
-               //multiple sub-object need to be put into one object
-               multi_obj = TRUE;
-               sprintf(result, "MULTIPOINT(" );
-       }
-       else if (geometry->type == MULTILINETYPE)
-       {
-               //multiple sub-object need to be put into one object
-               multi_obj = TRUE;
-               sprintf(result, "MULTILINESTRING(" );
-       }
-       else if (geometry->type == MULTIPOLYGONTYPE)
-       {
-               //multiple sub-object need to be put into one object
-               multi_obj = TRUE;
-               sprintf(result, "MULTIPOLYGON(" );
-       }
-       else if (geometry->type == COLLECTIONTYPE)
-       {
-               sprintf(result, "GEOMETRYCOLLECTION(" );
-               briefmode = FALSE;
-               multi_obj = FALSE;
-       }
-
-               //where are the objects?
-       offsets = (int32 *) ( ((char *) &(geometry->objType[0] ))+ sizeof(int32) * geometry->nobjs ) ;
-
-       is3d = geometry->is3d;
-
-
-       for(t=0;t<geometry->nobjs; t++)  //for each object
-       {
-               obj = (char *) geometry +offsets[t] ;
-
-               if (geometry->objType[t] == 1)   //POINT
-               {
-                       point = (POINT3D *) obj;
-                       if (briefmode)  //dont need to put in "POINT("
-                       {
-                               size +=MAX_DIGS_DOUBLE*3 + 2 +3  ;
-                               result = repalloc(result, size );  //make memory bigger
-                               if (!(first_sub_obj))
-                               {
-                                       strcat(result,",");
-                               }
-                               else
-                               {
-                                       first_sub_obj = FALSE;
-                               }
-                               print_point(result, point,is3d);  //render point
-                               if (t == (geometry->nobjs-1))
-                                       strcat(result,")");     // need to close object?
-                       }
-                       else
-                       {
-                               size +=MAX_DIGS_DOUBLE*3 + 2 +3 +7  ;
-                               result = repalloc(result, size  );
-                               strcat(result, "POINT(");
-                               print_point(result, point,is3d);
-                               strcat(result, ")");
-                               if (t != (geometry->nobjs -1) )
-                                       strcat(result,",");
-                       }
-
-               }
-               if (geometry->objType[t] == 2)  //LINESTRING
-               {
-                       line = (LINE3D *) obj;
-                       if (briefmode)
-                       {
-                               size +=(MAX_DIGS_DOUBLE*3+5)*line->npoints +3;
-                               result = repalloc(result, size );
-#ifdef DEBUG_TOTEXT
-elog(NOTICE, "Added space for %d points, result size: %d", line->npoints, size);
-elog(NOTICE, "Strlen result(%x): %d", result, strlen(result));
-#endif
-
-                               if (!(first_sub_obj))
-                               {
-                                       strcat(result,",");
-                               }
-                               else
-                               {
-                                       first_sub_obj = FALSE;
-                               }
-
-                               strcat(result,"(");
-                               print_many_points(result, &line->points[0],line->npoints , is3d);
-                               strcat(result,")");
-                               if ((t == (geometry->nobjs-1)) && multi_obj )  //close object?
-                                       strcat(result,")");
-#ifdef DEBUG_TOTEXT
-elog(NOTICE, "RESULT: %s", result);
-#endif
-                       }
-                       else
-                       {
-                               size +=(MAX_DIGS_DOUBLE*3+5)*line->npoints +12+3;
-                               result = repalloc(result, size );
-                               strcat(result, "LINESTRING(");
-
-                               //optimized for speed
-
-                               print_many_points(result, &line->points[0],line->npoints , is3d);
-                               strcat(result,")");
-                               if (t != (geometry->nobjs -1) )
-                                       strcat(result,",");
-
-                       }
-               }
-               if (geometry->objType[t] == 3)          //POLYGON
-               {
-                               polygon = (POLYGON3D *) obj;
-                               if (!(briefmode))
-                               {
-                                       size += 7 + polygon->nrings *3+9;
-                                       result = repalloc(result, size );
-                                       strcat(result,"POLYGON");
-                               }
-                               else
-                               {
-                                       size += 7 + polygon->nrings *3;
-                                       result = repalloc(result, size );
-                               }
-
-                               //need to separate objects?
-                               if (!(first_sub_obj))
-                               {
-                                       strcat(result,",");
-                               }
-                               else
-                               {
-                                       first_sub_obj = FALSE;
-                               }
-
-
-                               strcat(result,"(");     //begin poly
-
-                               pt_off = 0;     //where is the first point in this ring?
-
-                                       //where are the points
-                               pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] )  );
-                               pts = (POINT3D *) MAXALIGN(pts);
-
-
-                               npts = 0;
-                               for (u=0; u< polygon->nrings ; u++)
-                                       npts += polygon->npoints[u];
-
-                               size += (MAX_DIGS_DOUBLE*3+3) * npts + 5* polygon->nrings;
-                               result = repalloc(result, size );
-
-                               for (u=0; u< polygon->nrings ; u++)  //for each ring
-                               {
-//printf("making ring #%i in obj, %i\n",u,t);
-                                       if (u!=0)
-                                               strcat(result,","); //separate rings
-
-                                       strcat(result,"(");     //begin ring
-                                       print_many_points(result, &pts[pt_off] ,polygon->npoints[u], is3d);
-
-                                       pt_off = pt_off + polygon->npoints[u]; //where is first point of next ring?
-                                       strcat(result,")");     //end ring
-                               }
-                               strcat(result,")"); //end poly
-                               if ((t == (geometry->nobjs-1)) && multi_obj )
-                                       strcat(result,")");
-                               if ((!(briefmode)) && (t != (geometry->nobjs -1) ))
-                                       strcat(result,",");
-               }
-               if (!(briefmode))
-               {
-                       first_sub_obj = TRUE;
-               }
-
-       }
-
-       if (!(briefmode))
-               strcat(result,")");
-       return(result);
-}
-
-
-/*****************************************************
- * conversion routines
- *****************************************************/
-
-
-
-
-
-//get bvol inside a geometry
-PG_FUNCTION_INFO_V1(get_bbox_of_geometry);
-Datum get_bbox_of_geometry(PG_FUNCTION_ARGS)
-{
-       GEOMETRY  *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       BOX3D    *result;
-
-       if (geom->nobjs == 0)
-               PG_RETURN_NULL();
-
-       //make a copy of it
-
-       result = palloc ( sizeof(BOX3D) );
-       memcpy(result,&geom->bvol, sizeof(BOX3D) );
-
-
-       PG_RETURN_POINTER(result);
-}
-
-
-//make a fake geomery with just it a bvol
-PG_FUNCTION_INFO_V1(get_geometry_of_bbox);
-Datum get_geometry_of_bbox(PG_FUNCTION_ARGS)
-{
-       BOX3D  *bbox = (BOX3D *) PG_GETARG_POINTER(0);
-       GEOMETRY  *geom   ;
-
-       //make a copy of it
-
-       geom = palloc ( sizeof(GEOMETRY) );
-       geom->size = sizeof(GEOMETRY);
-       geom->type = BBOXONLYTYPE;
-       geom->nobjs = -1;
-       geom->SRID = -1;
-       geom->scale = 1.0;
-       geom->offsetX = 0.0;
-       geom->offsetY = 0.0;
-       memcpy(&(geom->bvol),bbox, sizeof(BOX3D) );
-
-
-       PG_RETURN_POINTER(geom);
-}
-
-
-
-
-//*****************************************************************
-//WKB does not do any padding or alignment!
-
-// in general these function take
-//     1. geometry item or list
-//     2. if the endian-ness should be changed (flipbytes)
-//     3. byte_order - 0=big endian (XDR) 1= little endian (NDR)
-//    4. use the 3d extention wkb (use3d)
-//
-// NOTE:
-//             A. mem - if null, function pallocs memory for result
-//                      - otherwise, use mem to dump the wkb into
-//             b. for lists, the # of sub-objects is also specified
-//
-//  and return
-//     1. size of the wkb structure ("int *size")
-//     2. the actual wkb structure
-//*****************************************************************
-
-//convert a POINT3D into wkb
-char   *wkb_point(POINT3D *pt,int32 *size, bool flipbytes, char byte_order, bool use3d)
-{
-       char            *result ;
-       uint32  type ;
-       char            *c_type = (char *) &type;
-
-       if (use3d)
-       {
-               *size = 29;
-               type = ((unsigned int) WKB3DOFFSET + ((unsigned int)1));
-       }
-       else
-       {
-               *size = 21;
-               type =  1;
-       }
-
-       result = palloc (*size);
-
-       if (flipbytes)
-               flip_endian_int32( (char *) &type);
-
-       result[0] = byte_order;
-       result[1] = c_type[0];
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       if (use3d)
-               memcpy(&result[5], pt, 24 ); //copy in point data
-       else
-               memcpy(&result[5], pt, 16 ); //copy in point data
-
-       if (flipbytes)
-       {
-               flip_endian_double((char *) &result[5]);                // x
-               flip_endian_double((char *) &result[5+8]);      // y
-               if (use3d)
-                       flip_endian_double((char *) &result[5+16]);     // z
-       }
-
-       return result;
-}
-
-//pt is a pointer to list of POINT3Ds
-char   *wkb_multipoint(POINT3D *pt,int32 numb_points,int32 *size, bool flipbytes, char byte_order,bool use3d)
-{
-       char *result;
-       uint32  type ;          // 3D/2D multipoint, following frank's spec
-       uint32  npoints = numb_points;
-       char            *c_type = (char *) &type;
-       char            *c_npoints = (char *) &npoints;
-       int             t;
-       int32           junk;
-       const int               sub_size_3d = 29;
-       const int               sub_size_2d = 21;
-
-
-
-
-       if (use3d)
-       {
-               *size = 9 + sub_size_3d*numb_points;
-               type = WKB3DOFFSET + 4;
-       }
-       else
-       {
-               *size = 9 + sub_size_2d*numb_points;
-               type =  4;
-       }
-
-
-       result = palloc (*size);
-       npoints = numb_points;
-
-       if (flipbytes)
-       {
-               flip_endian_int32((char *) &type);
-               flip_endian_int32((char *) &npoints);
-       }
-
-
-       result[0] = byte_order;
-       result[1] = c_type[0];
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_npoints[0];
-       result[6] = c_npoints[1];
-       result[7] = c_npoints[2];
-       result[8] = c_npoints[3];
-
-       for (t=0; t<numb_points;t++)  //for each point
-       {
-               if (use3d)
-                       memcpy(&result[9+ t*sub_size_3d],
-                                       wkb_point(&pt[t],&junk,  flipbytes,  byte_order,use3d)
-                                               , sub_size_3d);
-               else
-                       memcpy(&result[9+ t*sub_size_2d],
-                                       wkb_point(&pt[t],&junk,  flipbytes,  byte_order,use3d)
-                                                       , sub_size_2d);
-       }
-
-       return result;
-
-}
-
-
-//if mem != null, it must have enough space for the wkb
-char   *wkb_line(LINE3D *line,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem)
-{
-       char *result;
-       uint32  type ;
-
-       char            *c_type = (char *) &type;
-       int             t;
-
-       uint32  npoints = line->npoints;
-       int             numb_points = line->npoints;
-       char            *c_npoints = (char *) &npoints;
-
-
-       if (use3d)
-       {
-               *size = 9 + 24*numb_points;
-               type = WKB3DOFFSET + 2;
-       }
-       else
-       {
-               *size = 9 + 16*numb_points;
-               type =  2;
-       }
-
-
-
-       if (flipbytes)
-       {
-               flip_endian_int32((char *) &type);
-               flip_endian_int32((char *) &npoints);
-       }
-
-       if (mem == NULL)
-               result = palloc (*size);
-       else
-               result = mem;
-
-       result[0] = byte_order;
-       result[1] = c_type[0];          //type
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_npoints[0];       //npoints
-       result[6] = c_npoints[1];
-       result[7] = c_npoints[2];
-       result[8] = c_npoints[3];
-
-       if (use3d)
-       {
-               memcpy(&result[9],&line->points, line->npoints*24); // copy all the pt data in one chuck
-               if (flipbytes)
-               {
-                       for (t=0;t<line->npoints; t++)
-                       {
-                               flip_endian_double((char *) &result[9   + t*24]);       // x
-                               flip_endian_double((char *) &result[9+8 + t*24]);       // y
-                               flip_endian_double((char *) &result[9+16+ t*24]);       // z
-                       }
-               }
-       }
-       else
-       {
-               for (t=0; t<numb_points;t++)
-               {
-                       memcpy(&result[9+16*t],&((&line->points)[t]), 16);  //need to copy each pt individually
-                       if (flipbytes)
-                       {
-                               flip_endian_double((char *) &result[9   + t*16]);       // x
-                               flip_endian_double((char *) &result[9+8 + t*16]);       // y
-                       }
-               }
-       }
-       return result;
-}
-
-// expects an array of pointers to lines
-// calls wkb_line() to do most of the work
-char   *wkb_multiline(LINE3D **lines,int32 *size, int numb_lines, bool flipbytes, char byte_order,bool use3d)
-{
-       int     total_points = 0;
-       int     total_size=0;
-       int     size_part = 0;
-
-       int     t;
-       char    *result,*new_spot;
-
-
-       uint32  type ;
-       char            *c_type = (char *) &type;
-
-       uint32  nlines = numb_lines;
-       char            *c_nlines = (char *) &nlines;
-
-       if (use3d)
-       {
-               type = WKB3DOFFSET + 5;
-       }
-       else
-       {
-               type =  5;
-       }
-
-       if (flipbytes)
-       {
-               flip_endian_int32((char *) &type);
-               flip_endian_int32((char *) &nlines);
-       }
-
-       //how many points in the entire multiline()
-       for (t=0;t<numb_lines; t++)
-       {
-               total_points += lines[t]->npoints;
-       }
-
-
-       if (use3d)
-       {
-               total_size = 9+ 9*numb_lines + 24*total_points;
-       }
-       else
-       {
-               total_size = 9 + 9*numb_lines + 16*total_points;
-       }
-
-       *size = total_size;
-
-       result = palloc (total_size);
-
-
-
-       result[0] = byte_order;
-       result[1] = c_type[0];          //type
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_nlines[0];        //num linestrings
-       result[6] = c_nlines[1];
-       result[7] = c_nlines[2];
-       result[8] = c_nlines[3];
-
-
-
-       new_spot = result + 9;//where to put the next linestring
-
-               for (t=0;t<numb_lines;t++)  //for each linestring
-               {
-                       wkb_line( lines[t], &size_part, flipbytes, byte_order, use3d, new_spot);
-                       new_spot += size_part; //move to next slot
-               }
-       return result;
-}
-
-
-//mem should be zero or hold enough space
-char   *wkb_polygon(POLYGON3D  *poly,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem)
-{
-       int     t, u,total_points =0;
-       uint32  type ;
-       char            *c_type = (char *) &type;
-       uint32  numRings,npoints;
-       char            *c_numRings = (char *) &numRings;
-       char            *c_npoints = (char *) &npoints;
-       int             offset;
-       POINT3D *pts;
-       int             point_offset;
-       char    *result;
-
-
-       //where the polygon's points are (double aligned)
-
-       pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-       pts = (POINT3D *) MAXALIGN(pts);
-
-
-
-       numRings = poly->nrings;
-
-       //total points in all the rings
-       for (t=0; t< poly->nrings; t++)
-       {
-               total_points += poly->npoints[t];
-       }
-
-       if (use3d)
-       {
-               *size = 9 + 4*poly->nrings + 24*total_points;
-               type = WKB3DOFFSET + 3;
-       }
-       else
-       {
-               *size = 9 + 4*poly->nrings + 16*total_points;
-               type = 3;
-       }
-
-       if (mem == NULL)
-               result = palloc (*size);
-       else
-               result = mem;
-
-
-       if (flipbytes)
-       {
-               flip_endian_int32((char *) &type);
-               flip_endian_int32((char *) &numRings);
-       }
-
-
-
-       result[0] = byte_order;
-       result[1] = c_type[0];          //type
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_numRings[0];      //npoints
-       result[6] = c_numRings[1];
-       result[7] = c_numRings[2];
-       result[8] = c_numRings[3];
-
-
-       if (use3d)
-       {
-               offset = 9; //where the actual linearring structure is going
-               point_offset = 0;
-               for (t=0;t<poly->nrings; t++) //for each ring
-               {
-                       npoints = poly->npoints[t];
-                       if (flipbytes)
-                               flip_endian_int32((char *) &npoints);
-                       result[offset]   = c_npoints[0];  //num points in this ring
-                       result[offset+1] = c_npoints[1];
-                       result[offset+2] = c_npoints[2];
-                       result[offset+3] = c_npoints[3];
-
-                       memcpy(&result[offset+4], &pts[point_offset], 24*poly->npoints[t]);
-                       if (flipbytes)
-                       {
-                               for (u=0;u<poly->npoints[t];u++)  //for each point
-                               {
-                                       flip_endian_double((char *) &result[offset+4+u*24]   );
-                                       flip_endian_double((char *) &result[offset+4+u*24+8] );
-                                       flip_endian_double((char *) &result[offset+4+u*24]+16);
-                               }
-                       }
-                       point_offset += poly->npoints[t];     // reset offsets
-                       offset +=  4 +  poly->npoints[t]* 24;
-               }
-       }
-       else
-       {
-               offset = 9; // where the 1st linearring goes
-               point_offset = 0;
-               for (t=0;t<poly->nrings; t++)
-               {
-                       npoints = poly->npoints[t];
-                       if (flipbytes)
-                               flip_endian_int32((char *) &npoints);
-                       result[offset]   = c_npoints[0];
-                       result[offset+1] = c_npoints[1];
-                       result[offset+2] = c_npoints[2];
-                       result[offset+3] = c_npoints[3];
-
-                               for (u=0;u<poly->npoints[t];u++)
-                               {
-                                       memcpy(&result[offset+4 + u*16], &pts[point_offset+u], 16);
-                                       if (flipbytes)
-                                       {
-                                               flip_endian_double((char *) &result[offset+4+u*16]   );
-                                               flip_endian_double((char *) &result[offset+4+u*16+8] );
-                                       }
-                               }
-
-                       point_offset += poly->npoints[t];
-                       offset +=  4 +  poly->npoints[t]* 16;
-               }
-
-       }
-       return result;
-}
-
-
-//expects a list of pointer to polygon3d
-char   *wkb_multipolygon(POLYGON3D     **polys,int numb_polys,int32 *size, bool flipbytes, char byte_order,bool use3d)
-{
-
-       int     t,u;
-       int     total_points = 0;
-       int     total_size=0;
-       int     size_part = 0;
-       int     total_rings = 0;
-       char    *result,*new_spot;
-       uint32  type;
-
-       char            *c_type = (char *) &type;
-
-       uint32  npolys = numb_polys;
-       char            *c_npolys = (char *) &npolys;
-
-       if (use3d)
-       {
-               type = WKB3DOFFSET + 6;
-       }
-       else
-       {
-               type =  6;
-       }
-
-
-       if (flipbytes)
-       {
-               flip_endian_int32( (char *) &type);
-               flip_endian_int32((char *) &npolys);
-       }
-
-
-
-
-       //find total # rings and total points
-       for (t=0;t<numb_polys; t++)
-       {
-               total_rings += polys[t]->nrings;
-               for (u=0;u<polys[t]->nrings; u++)
-               {
-                       total_points += polys[t]->npoints[u];
-               }
-       }
-
-
-       if (use3d)
-       {
-               total_size =9 +  9*numb_polys + 24*total_points + 4*total_rings;
-       }
-       else
-       {
-               total_size = 9 + 9*numb_polys + 16*total_points + 4*total_rings;
-       }
-
-       *size = total_size;
-
-       result = palloc (total_size);
-
-       result[0] = byte_order;
-       result[1] = c_type[0];          //type
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_npolys[0];        //number of polygons
-       result[6] = c_npolys[1];
-       result[7] = c_npolys[2];
-       result[8] = c_npolys[3];
-
-
-
-       new_spot = result+9;  //where 1st polygon goes
-
-               for (t=0;t<numb_polys;t++)  //for each polygon
-               {
-                       wkb_polygon( polys[t], &size_part, flipbytes, byte_order, use3d, new_spot);
-                       new_spot +=  size_part; //more to next slot
-               }
-       return result;
-
-}
-
-
-//passes work off to the correct function
-// then makes a simple postgres type - the first 4 bytes is an int32 with the size of the structure
-// and the rest is the wkb info.
-//
-// 3d-ness is determined by looking at the is3d flag in the GEOMETRY structure
-
-char   *to_wkb(GEOMETRY *geom, bool flip_endian)
-{
-       char    *result, *sub_result;
-       int     size;
-
-       if (geom->type == COLLECTIONTYPE)
-       {
-               sub_result=     to_wkb_collection(geom,  flip_endian, &size);
-               size += 4; //size info
-               result = palloc (size );
-               memcpy(result+4, sub_result, size-4);
-               memcpy(result, &size, 4);
-               pfree(sub_result);
-               return result;
-       }
-       else
-       {
-               sub_result=     to_wkb_sub(geom,  flip_endian, &size);
-               size += 4; //size info
-               result = palloc (size );
-               memcpy(result+4, sub_result, size-4);
-               memcpy(result, &size, 4);
-               pfree(sub_result);
-               return result;
-       }
-
-}
-
-//make a wkb chunk out of a geometrycollection
-char *to_wkb_collection(GEOMETRY *geom, bool flip_endian, int32 *end_size)
-{
-       char    *result, **sub_result;
-       int     sub_size;
-       int     *sizes;
-       int     t;
-       int32           *offsets1;
-
-       int32           type;
-       int             total_size =0;
-       int             offset;
-       char            byte_order;
-       int             coll_type=7;
-       char            *c_type = (char *)&coll_type;
-       int             nobj = geom->nobjs;
-       char            *c_nobj = (char *) &nobj;
-
-//printf("making a wkb of a collections\n");
-
-
-       //determing byte order and if numbers need endian change
-       if (BYTE_ORDER == BIG_ENDIAN)
-       {
-               if (flip_endian)
-               {
-                       byte_order = 1;
-               }
-               else
-               {
-                       byte_order = 0;
-               }
-       }
-       else
-       {
-               if (flip_endian)
-               {
-                       byte_order = 0;
-               }
-               else
-               {
-                       byte_order = 1;
-               }
-       }
-
-       //for sub part of the geometry structure
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-
-       // we make a list of smaller wkb chunks in sub_result[]
-       // and that wkb chunk's size in sizes[]
-
-       sub_result = NULL;
-       if (geom->nobjs >0)
-               sub_result = palloc( sizeof(char *) * geom->nobjs);
-       sizes = NULL;
-       if (geom->nobjs >0)
-               sizes = palloc( sizeof(int) * geom->nobjs);
-
-
-       for (t=0; t<geom->nobjs; t++)   //for each part of the collections, do the work in another function
-       {
-               type = geom->objType[t];
-
-               if (type == POINTTYPE)
-               {
-                       sub_result[t] = (  wkb_point((POINT3D *) ((char *) geom +offsets1[t] ) ,
-                                       &sub_size, flip_endian, byte_order, geom->is3d));
-                       sizes[t] = sub_size;
-                       total_size += sub_size;
-               }
-
-               if (type == LINETYPE)
-               {
-
-                       sub_result[t] = (  wkb_line((LINE3D *) ((char *) geom +offsets1[t] ) ,
-                                &sub_size, flip_endian, byte_order, geom->is3d, NULL));
-                       sizes[t] = sub_size;
-                       total_size += sub_size;
-               }
-               if (type == POLYGONTYPE)
-               {
-
-                       sub_result[t] = (  wkb_polygon((POLYGON3D *) ((char *) geom +offsets1[t] ) ,
-                                &sub_size, flip_endian, byte_order, geom->is3d, NULL));
-                       sizes[t] = sub_size;
-                       total_size += sub_size;
-               }
-       }
-
-       result = palloc( total_size +9); // need geometrycollection header
-
-       if (geom->is3d)
-               coll_type += WKB3DOFFSET;
-
-       if (flip_endian)
-       {
-               flip_endian_int32((char *) &coll_type);
-               flip_endian_int32((char *) &nobj);
-       }
-
-       //could use a memcpy, but...
-
-
-
-       result[0] = byte_order;
-       result[1] = c_type[0];          //type
-       result[2] = c_type[1];
-       result[3] = c_type[2];
-       result[4] = c_type[3];
-
-       result[5] = c_nobj[0];  //number of part to collection
-       result[6] = c_nobj[1];
-       result[7] = c_nobj[2];
-       result[8] = c_nobj[3];
-
-
-       offset =9;  //start after the geometrycollection header
-
-
-       for (t=0;t<geom->nobjs; t++)
-       {
-               memcpy(result+ offset, sub_result[t], sizes[t]);
-               pfree(sub_result[t]);
-               offset += sizes[t];
-       }
-
-               //free temp structures
-       if (sub_result != NULL)
-               pfree( sub_result);
-       if (sizes != NULL)
-               pfree( sizes);
-
-               //total size of the wkb
-       *end_size = total_size+9;
-
-
-
-       //decode_wkb(result, &junk);
-       return result;
-}
-
-
-//convert geometry to WKB, flipping endian if appropriate
-//
-//  This handles POINT, LINESTRING, POLYGON, MULTIPOINT,MULTILINESTRING, MULTIPOLYGON
-//
-// GEOMETRYCOLLECTION is not handled by this function see to_wkb_collection()
-//
-// flip_endian - request an endian swap (relative to current machine)
-// wkb_size    - return size of wkb
-
-char   *to_wkb_sub(GEOMETRY *geom, bool flip_endian, int32 *wkb_size)
-{
-
-       char    byte_order;
-       char    *result = NULL;
-       int             t;
-
-
-       int32           *offsets1;
-       LINE3D  **linelist;
-       POLYGON3D       **polylist;
-
-
-       //determine WKB byte order flag
-       if (BYTE_ORDER == BIG_ENDIAN)   //server is running on a big endian machine
-       {
-               if (flip_endian)
-               {
-                       byte_order = 1;  //as per WKB specification
-               }
-               else
-               {
-                       byte_order = 0;
-               }
-       }
-       else
-       {
-               if (flip_endian)
-               {
-                       byte_order = 0;
-               }
-               else
-               {
-                       byte_order = 1;
-               }
-       }
-
-       // for searching in the geom struct
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-
-               // for each of the possible geometry types, we pass it off to a worker function
-
-       if (geom->type == POINTTYPE)
-       {
-
-               result = (  wkb_point((POINT3D *) ((char *) geom +offsets1[0] ) ,
-                                       wkb_size, flip_endian, byte_order, geom->is3d));
-       }
-
-       if (geom->type == MULTIPOINTTYPE)
-       {
-
-               result = (  wkb_multipoint((POINT3D *) ((char *) geom +offsets1[0] ) ,
-                               geom->nobjs,    wkb_size, flip_endian, byte_order, geom->is3d));
-       }
-
-       if (geom->type == LINETYPE)
-       {
-
-               result = (  wkb_line((LINE3D *) ((char *) geom +offsets1[0] ) ,
-                                wkb_size, flip_endian, byte_order, geom->is3d, NULL));
-       }
-
-
-       if (geom->type == MULTILINETYPE)
-       {
-               //make a list of lines
-               linelist = NULL;
-               if (geom->nobjs >0)
-                       linelist = palloc( sizeof(LINE3D *) * geom->nobjs);
-               for (t=0;t<geom->nobjs; t++)
-               {
-                       linelist[t] = (LINE3D *) ((char *) geom +offsets1[t] ) ;
-               }
-               result = (  wkb_multiline( linelist,
-                                wkb_size, geom->nobjs, flip_endian, byte_order, geom->is3d));
-       }
-
-       if (geom->type == POLYGONTYPE)
-       {
-
-               result = (  wkb_polygon((POLYGON3D *) ((char *) geom +offsets1[0] ) ,
-                                wkb_size, flip_endian, byte_order, geom->is3d, NULL));
-       }
-
-
-       if (geom->type == MULTIPOLYGONTYPE)
-       {
-               //make a list of polygons
-               polylist = NULL;
-               if (geom->nobjs >0)
-                       polylist = palloc( sizeof(POLYGON3D *) * geom->nobjs);
-               for (t=0;t<geom->nobjs; t++)
-               {
-                       polylist[t] = (POLYGON3D *) ((char *) geom +offsets1[t] ) ;
-               }
-               result = (  wkb_multipolygon( polylist,geom->nobjs,
-                                wkb_size,  flip_endian, byte_order, geom->is3d));
-       }
-
-       //decode_wkb(result, &junk);
-
-       return (result);
-}
-
-
-//convert binary geometry into OGIS well know binary format with NDR (little endian) formating
-// see http://www.opengis.org/techno/specs/99-049.rtf page 3-24 for specification
-//
-// 3d geometries are encode as in OGR by adding WKB3DOFFSET to the type.  Points are then 24bytes (X,Y,Z)
-// instead of 16 bytes (X,Y)
-//
-//dont do any flipping of endian   asbinary_simple(GEOMETRY)
-PG_FUNCTION_INFO_V1(asbinary_simple);
-Datum asbinary_simple(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       PG_RETURN_POINTER(to_wkb(geom, FALSE));
-}
-
-
-//convert binary geometry into OGIS well know binary format with NDR (little endian) formating
-// see http://www.opengis.org/techno/specs/99-049.rtf page 3-24 for specification
-//
-// 3d geometries are encode as in OGR by adding WKB3DOFFSET to the type.  Points are then 24bytes (X,Y,Z)
-// instead of 16 bytes (X,Y)
-//
-//flip if required    asbinary_specify(GEOMETRY,'xdr') or asbinary_specify(GEOMETRY,'ndr')
-PG_FUNCTION_INFO_V1(asbinary_specify);
-Datum asbinary_specify(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-                text                           *type = PG_GETARG_TEXT_P(1);
-
-
-       if (VARSIZE(type) < 7)  // 4 (size header) + 3 (text length)
-       {
-               elog(ERROR,"asbinary(geometry, <type>) - type should be 'XDR' or 'NDR'.  type length is %i",VARSIZE(type) -4);
-               PG_RETURN_NULL();
-       }
-
-       if  ( ( strncmp(VARDATA(type) ,"xdr",3) == 0 ) || (strncmp(VARDATA(type) ,"XDR",3) == 0) )
-       {
-//printf("requested XDR\n");
-               if (BYTE_ORDER == BIG_ENDIAN)
-                       PG_RETURN_POINTER(to_wkb(geom, FALSE));
-               else
-                       PG_RETURN_POINTER(to_wkb(geom, TRUE));
-       }
-       else
-       {
-//printf("requested NDR\n");
-               if (BYTE_ORDER == LITTLE_ENDIAN)
-                       PG_RETURN_POINTER(to_wkb(geom, FALSE));
-               else
-                       PG_RETURN_POINTER(to_wkb(geom, TRUE));
-       }
-}
-
-//takes a text argument and parses it to make a geometry
-PG_FUNCTION_INFO_V1(geometry_text);
-Datum geometry_text(PG_FUNCTION_ARGS)
-{
-       char            *input = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char            *cstring;
-       void            *result;
-
-       if (*((int *) input) == 4)
-       {
-               //empty string
-               PG_RETURN_NULL();
-       }
-       cstring = palloc(*((int *) input));  // length+4
-
-       memcpy(cstring, &input[4], ( *((int *) input))-4);
-       cstring[( *((int *) input))-4] = 0; // nullterminate
-
-       result = DatumGetPointer(       DirectFunctionCall1(geometry_in,PointerGetDatum(cstring))) ;
-
-       PG_RETURN_POINTER (result);
-//NOTE: this could cause problem since input isnt null terminated - usually this will not
-//      cause a problem because the parse will not go further than the end of the string.
-//       FIXED.
-}
-
-
-
-//make a geometry with one obj in it (of size new_obj_size)
-// type should be POINTTYPE, LINETYPE or POLYGONTYPE
-// if you want to change the object's type to something else (ie GEOMETRYCOLLECTION), do
-// that after with geom->type = GEOMETRYCOLLECTION
-// this does  calculate the bvol
-//
-// sets the SRID and grid info to the given values
-//
-// do not call this with type = GEOMETRYCOLLECTION
-
-GEOMETRY       *make_oneobj_geometry(int sub_obj_size, char *sub_obj, int type, bool is3d,int SRID, double scale, double offx, double offy)
-{
-       int size = sizeof(GEOMETRY) + 4 + sub_obj_size ;
-       GEOMETRY        *result = palloc(size);
-       char            *sub_obj_loc;
-       BOX3D           *bbox;
-
-       result->size = size;
-       result->nobjs = 1;
-       result->type = type;
-       result->is3d = is3d;
-
-
-       result->SRID = SRID;
-       result->scale = scale;
-       result->offsetX = offx;
-       result->offsetY = offy;
-
-       result->objType[0] = type;
-       if (type == MULTIPOINTTYPE)
-               result->objType[0] = POINTTYPE;
-       if (type == MULTILINETYPE)
-               result->objType[0] = LINETYPE;
-       if (type == MULTIPOLYGONTYPE)
-               result->objType[0] = POLYGONTYPE;
-
-       if (type == COLLECTIONTYPE)
-       {
-               pfree(result);
-               return(NULL); //error
-       }
-
-       sub_obj_loc = (char *)  &result->objType[2];
-       sub_obj_loc  = (char *) MAXALIGN(sub_obj_loc);
-
-       result->objType[1] = sub_obj_loc  - (char *) result; //result->objType[1] is where objOffset is
-
-       //copy in the subobject
-       memcpy(sub_obj_loc , sub_obj, sub_obj_size);
-
-       bbox = bbox_of_geometry(result);
-       memcpy(&result->bvol,bbox, sizeof(BOX3D) ); //make bounding box
-
-       return result;
-}
-
-
-//find the size of the subobject and return it
-int    size_subobject (char *sub_obj, int type)
-{
-       if (type == POINTTYPE)
-       {
-               return (sizeof(POINT3D));
-       }
-       if (type == LINETYPE)
-       {
-               /* size of first point is included in struct LINE3D */
-               return(sizeof(LINE3D) +  sizeof(POINT3D) * ( ((LINE3D *)sub_obj)->npoints - 1 ));
-       }
-       if (type==POLYGONTYPE)
-       {
-               POLYGON3D       *poly = (POLYGON3D *) sub_obj;
-               int             t,points=0;
-
-               for (t=0;t<poly->nrings;t++)
-               {
-                       points += poly->npoints[t];
-               }
-               if  (   ( (long) ( &poly->npoints[poly->nrings] )) == (MAXALIGN(&poly->npoints[poly->nrings] ) ) )
-                       return (sizeof(POLYGON3D) + 4*(poly->nrings-1) +  sizeof(POINT3D)*(points-1) );  //no extra align
-               else
-                       return (sizeof(POLYGON3D) + 4*(poly->nrings-1) +  sizeof(POINT3D)*(points-1) +4 );
-       }
-
-       return (-1);//unknown sub-object type
-}
-
-
-//produce a new geometry, which is the old geometry with another object stuck in it
-// This will try to make the geometry's type is correct (move POINTTYPE to MULTIPOINTTYPE or
-//   change to GEOMETRYCOLLECTION)
-//
-// this does NOT calculate the bvol - you should set it with "bbox_of_geometry"
-//
-// type is the type of the subobject
-// do not call this as with type = GEOMETRYCOLLECTION
-//
-// doesnt change the is3d flag
-// doesnt change the SRID or other attributes
-
-GEOMETRY       *add_to_geometry(GEOMETRY *geom,int sub_obj_size, char *sub_obj, int type)
-{
-       int             size,t;
-       int             size_obj,next_offset;
-       GEOMETRY        *result;
-       int32           *old_offsets, *new_offsets;
-
-       //all the offsets could cause re-alignment problems, so need to deal with each one
-       size = geom->size +4*(geom->nobjs +1) /*byte align*/
-                       +sub_obj_size + 4 /*ObjType[]*/ +4 /*new offset*/;
-
-       result = (GEOMETRY *) palloc(size);
-       result->size = size;
-       result->is3d = geom->is3d;
-       result->SRID = geom->SRID;
-       result->offsetX = geom->offsetX;
-       result->offsetY = geom->offsetY;
-       result->scale = geom->scale;
-
-       //accidently sent in a single-entity type but gave it a multi-entity type
-       //  re-type it as single-entity
-       if (type == MULTIPOINTTYPE)
-               type = POINTTYPE;
-       if (type == MULTILINETYPE)
-               type = LINETYPE;
-       if (type == MULTIPOLYGONTYPE)
-               type = POLYGONTYPE;
-
-
-       // change to the simplest possible type that supports the type being added
-       if  (geom->type == POINTTYPE || geom->type == MULTIPOINTTYPE)
-       {
-               if (type == POINTTYPE)
-                       result->type  = MULTIPOINTTYPE;
-               else
-                       result->type  = COLLECTIONTYPE;
-       }
-       if  (geom->type == LINETYPE || geom->type == MULTILINETYPE)
-       {
-               if (type == LINETYPE)
-                       result->type  = MULTILINETYPE;
-               else
-                       result->type  = COLLECTIONTYPE;
-       }
-       if  (geom->type == POLYGONTYPE || geom->type == MULTIPOLYGONTYPE)
-       {
-               if (type == POLYGONTYPE)
-                       result->type  = MULTIPOLYGONTYPE;
-               else
-                       result->type  = COLLECTIONTYPE;
-       }
-       if (geom->type == COLLECTIONTYPE)
-               result->type = COLLECTIONTYPE;
-
-       // now result geometry's type and sub-object's type is okay
-       // we have to setup the geometry
-
-       result->nobjs = geom->nobjs+1;
-
-       for (t=0; t< geom->nobjs; t++)
-       {
-               result->objType[t] = geom->objType[t];
-       }
-
-//printf("about to copy geomes\n");
-//printf("result is at %p and is %i bytes long\n",result,result->size);
-//printf("geom is at %p and is %i bytes long\n",geom,geom->size);
-
-       old_offsets =&  geom->objType[geom->nobjs] ;
-       new_offsets =&  result->objType[result->nobjs] ;
-       next_offset = ( (char *) &new_offsets[result->nobjs] ) - ( (char *) result) ;
-       next_offset = MAXALIGN(next_offset);
-
-       //have to re-set the offsets and copy in the sub-object data
-       for (t=0; t< geom->nobjs; t++)
-       {
-               //where is this going to go?
-               new_offsets[t] = next_offset;
-
-               size_obj =      size_subobject ((char *) (((char *) geom) + old_offsets[t] ), geom->objType[t]);
-
-               next_offset += size_obj;
-               next_offset = MAXALIGN(next_offset); // make sure its aligned properly
-
-
-//printf("coping %i bytes from %p to %p\n", size_obj,( (char *) geom) + old_offsets[t],((char *) result)  + new_offsets[t]   );
-               memcpy( ((char *) result)  + new_offsets[t] , ( (char *) geom) + old_offsets[t], size_obj);
-//printf("copying done\n");
-
-       }
-
-//printf("copying in new object\n");
-
-       //now, put in the new data
-       result->objType[ result->nobjs -1 ] = type;
-       new_offsets[ result->nobjs -1 ] = next_offset;
-       memcpy(  ((char *) result)  + new_offsets[result->nobjs-1] ,sub_obj , sub_obj_size);
-
-//printf("returning\n");
-
-       return result;
-}
-
-
-
-//make a polygon obj
-// size is return in arg "size"
-POLYGON3D      *make_polygon(int nrings, int *pts_per_ring, POINT3D *pts, int npoints, int *size)
-{
-               POLYGON3D       *result;
-               int             t;
-               POINT3D *inside_poly_pts;
-
-
-       *size = sizeof(POLYGON3D) + 4 /*align*/
-                               + 4*(nrings-1)/*npoints struct*/
-                               + sizeof(POINT3D) *(npoints-1) /*points struct*/ ;
-
-       result= (POLYGON3D *) palloc (*size);
-       result->nrings = nrings;
-
-
-       for (t=0;t<nrings;t++)
-       {
-               result->npoints[t] = pts_per_ring[t];
-       }
-
-       inside_poly_pts = (POINT3D *) ( (char *)&(result->npoints[result->nrings] )  );
-       inside_poly_pts = (POINT3D *) MAXALIGN(inside_poly_pts);
-
-       memcpy(inside_poly_pts, pts, npoints *sizeof(POINT3D) );
-
-       return result;
-}
-
-void set_point( POINT3D *pt,double x, double y, double z)
-{
-       pt->x = x;
-       pt->y = y;
-       pt->z = z;
-}
-
-//make a line3d object
-// return size of structure in 'size'
-LINE3D *make_line(int  npoints, POINT3D        *pts, int       *size)
-{
-       LINE3D  *result;
-
-       *size = sizeof(LINE3D) + (npoints-1)*sizeof(POINT3D);
-
-       result= (LINE3D *) palloc (*size);
-
-       result->npoints = npoints;
-       memcpy( result->points, pts, npoints*sizeof(POINT3D) );
-
-       return result;
-}
-
-//given one byte, populate result with two byte representing
-// the hex number
-// ie deparse_hex( 255, mystr)
-//             -> mystr[0] = 'F' and mystr[1] = 'F'
-// no error checking done
-void deparse_hex(unsigned char str, unsigned char *result)
-{
-       int     input_high;
-       int  input_low;
-
-       input_high = (str>>4);
-       input_low = (str & 0x0F);
-
-       switch (input_high)
-       {
-               case 0:
-                       result[0] = '0';
-                       break;
-               case 1:
-                       result[0] = '1';
-                       break;
-               case 2:
-                       result[0] = '2';
-                       break;
-               case 3:
-                       result[0] = '3';
-                       break;
-               case 4:
-                       result[0] = '4';
-                       break;
-               case 5:
-                       result[0] = '5';
-                       break;
-               case 6:
-                       result[0] = '6';
-                       break;
-               case 7:
-                       result[0] = '7';
-                       break;
-               case 8:
-                       result[0] = '8';
-                       break;
-               case 9:
-                       result[0] = '9';
-                       break;
-               case 10:
-                       result[0] = 'A';
-                       break;
-               case 11:
-                       result[0] = 'B';
-                       break;
-               case 12:
-                       result[0] = 'C';
-                       break;
-               case 13:
-                       result[0] = 'D';
-                       break;
-               case 14:
-                       result[0] = 'E';
-                       break;
-               case 15:
-                       result[0] = 'F';
-                       break;
-       }
-
-       switch (input_low)
-       {
-               case 0:
-                       result[1] = '0';
-                       break;
-               case 1:
-                       result[1] = '1';
-                       break;
-               case 2:
-                       result[1] = '2';
-                       break;
-               case 3:
-                       result[1] = '3';
-                       break;
-               case 4:
-                       result[1] = '4';
-                       break;
-               case 5:
-                       result[1] = '5';
-                       break;
-               case 6:
-                       result[1] = '6';
-                       break;
-               case 7:
-                       result[1] = '7';
-                       break;
-               case 8:
-                       result[1] = '8';
-                       break;
-               case 9:
-                       result[1] = '9';
-                       break;
-               case 10:
-                       result[1] = 'A';
-                       break;
-               case 11:
-                       result[1] = 'B';
-                       break;
-               case 12:
-                       result[1] = 'C';
-                       break;
-               case 13:
-                       result[1] = 'D';
-                       break;
-               case 14:
-                       result[1] = 'E';
-                       break;
-               case 15:
-                       result[1] = 'F';
-                       break;
-       }
-}
-
-
-//given a string with at least 2 chars in it, convert them to
-// a byte value.  No error checking done!
-unsigned char  parse_hex(char *str)
-{
-       //do this a little brute force to make it faster
-
-       unsigned char           result_high = 0;
-       unsigned char           result_low = 0;
-
-       switch (str[0])
-       {
-               case '0' :
-                       result_high = 0;
-                       break;
-               case '1' :
-                       result_high = 1;
-                       break;
-               case '2' :
-                       result_high = 2;
-                       break;
-               case '3' :
-                       result_high = 3;
-                       break;
-               case '4' :
-                       result_high = 4;
-                       break;
-               case '5' :
-                       result_high = 5;
-                       break;
-               case '6' :
-                       result_high = 6;
-                       break;
-               case '7' :
-                       result_high = 7;
-                       break;
-               case '8' :
-                       result_high = 8;
-                       break;
-               case '9' :
-                       result_high = 9;
-                       break;
-               case 'A' :
-                       result_high = 10;
-                       break;
-               case 'B' :
-                       result_high = 11;
-                       break;
-               case 'C' :
-                       result_high = 12;
-                       break;
-               case 'D' :
-                       result_high = 13;
-                       break;
-               case 'E' :
-                       result_high = 14;
-                       break;
-               case 'F' :
-                       result_high = 15;
-                       break;
-       }
-       switch (str[1])
-       {
-               case '0' :
-                       result_low = 0;
-                       break;
-               case '1' :
-                       result_low = 1;
-                       break;
-               case '2' :
-                       result_low = 2;
-                       break;
-               case '3' :
-                       result_low = 3;
-                       break;
-               case '4' :
-                       result_low = 4;
-                       break;
-               case '5' :
-                       result_low = 5;
-                       break;
-               case '6' :
-                       result_low = 6;
-                       break;
-               case '7' :
-                       result_low = 7;
-                       break;
-               case '8' :
-                       result_low = 8;
-                       break;
-               case '9' :
-                       result_low = 9;
-                       break;
-               case 'A' :
-                       result_low = 10;
-                       break;
-               case 'B' :
-                       result_low = 11;
-                       break;
-               case 'C' :
-                       result_low = 12;
-                       break;
-               case 'D' :
-                       result_low = 13;
-                       break;
-               case 'E' :
-                       result_low = 14;
-                       break;
-               case 'F' :
-                       result_low = 15;
-                       break;
-       }
-       return (unsigned char) ((result_high<<4) + result_low);
-}
-
-
-// input is a string with hex chars in it.  Convert to binary and put in the result
-PG_FUNCTION_INFO_V1(WKB_in);
-Datum WKB_in(PG_FUNCTION_ARGS)
-{
-       char                    *str = PG_GETARG_CSTRING(0);
-       WellKnownBinary         *result;
-       int                     size;
-       int                     t;
-       int                     input_str_len;
-
-//printf("wkb_in called\n");
-
-       input_str_len = strlen(str);
-
-       if  ( ( ( (int)(input_str_len/2.0) ) *2.0) != input_str_len)
-       {
-               elog(ERROR,"WKB_in parser - should be even number of characters!");
-               PG_RETURN_NULL();
-       }
-
-       if (strspn(str,"0123456789ABCDEF") != strlen(str) )
-       {
-               elog(ERROR,"WKB_in parser - input contains bad characters.  Should only have '0123456789ABCDEF'!");
-               PG_RETURN_NULL();
-       }
-       size = (input_str_len/2) + 4;
-       result = (WellKnownBinary *) palloc(size);
-       result->size = size;
-
-       for (t=0;t<input_str_len/2;t++)
-       {
-               ((unsigned char *)result)[t+4] = parse_hex( &str[t*2]) ;
-       }
-       PG_RETURN_POINTER(result);
-}
-
-
-//given a WKB structure, convert it to Hex and put it in a string
-PG_FUNCTION_INFO_V1(WKB_out);
-Datum WKB_out(PG_FUNCTION_ARGS)
-{
-       WellKnownBinary               *WKB = (WellKnownBinary *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       char                                    *result;
-       int                                     size_result;
-       int                                     t;
-
-//printf("wkb_out called\n");
-
-       size_result = (WKB->size - 4) *2 +1; //+1 for null char
-       result = palloc (size_result);
-       result[size_result-1] = 0; //null terminate
-
-       for (t=0; t< (WKB->size -4); t++)
-       {
-               deparse_hex( ((unsigned char *) WKB)[4 + t], &result[t*2]);
-       }
-       PG_RETURN_CSTRING(result);
-}
-
-
-#if USE_VERSION > 73
-/*
- * This function must advance the StringInfo.cursor pointer
- * and leave it at the end of StringInfo.buf. If it fails
- * to do so the backend will raise an exception with message:
- * ERROR:  incorrect binary data format in bind parameter #
- *
- */
-PG_FUNCTION_INFO_V1(WKB_recv);
-Datum WKB_recv(PG_FUNCTION_ARGS)
-{
-       StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
-        bytea *result;
-
-       //elog(NOTICE, "WKB_recv start");
-
-       /* Add VARLENA size info to make it a valid varlena object */
-       result = (bytea *)palloc(buf->len+VARHDRSZ);
-       VARATT_SIZEP(result) = buf->len+VARHDRSZ;
-       memcpy(VARATT_DATA(result), buf->data, buf->len);
-
-       /* Set cursor to the end of buffer (so the backend is happy) */
-       buf->cursor = buf->len;
-
-       //elog(NOTICE, "WKB_recv end (returning result)");
-        PG_RETURN_POINTER(result);
-}
-#endif
-
-PG_FUNCTION_INFO_V1(WKBtoBYTEA);
-Datum WKBtoBYTEA(PG_FUNCTION_ARGS)
-{
-               WellKnownBinary               *WKB = (WellKnownBinary *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               bytea                                     *result;
-
-               result = (bytea*) palloc(WKB->size);
-               memcpy(result,WKB, WKB->size);
-
-               PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry2box);
-Datum geometry2box(PG_FUNCTION_ARGS)
-{
-        GEOMETRY *g = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-//elog(NOTICE,"geometry2box - ymax is %.15g",g->bvol.URT.y);
-
-       PG_RETURN_POINTER(convert_box3d_to_box(&g->bvol) );
-
-}
-
-//create_histogram2d(BOX3D, boxesPerSide)
-// returns a histgram with 0s in all the boxes.
-PG_FUNCTION_INFO_V1(create_histogram2d);
-Datum create_histogram2d(PG_FUNCTION_ARGS)
-{
-       BOX3D  *bbox = (BOX3D *) PG_GETARG_POINTER(0);
-       int32   boxesPerSide=  PG_GETARG_INT32(1);
-       HISTOGRAM2D             *histo;
-       int size,t;
-
-
-       if ( (boxesPerSide <1) || (boxesPerSide >50) )
-       {
-                       elog(ERROR,"create_histogram2d - boxesPerSide is too small or big.\n");
-                       PG_RETURN_NULL() ;
-       }
-
-
-       size =  sizeof(HISTOGRAM2D) +    (boxesPerSide*boxesPerSide-1)*4  ;
-
-       histo = (HISTOGRAM2D *) palloc (size);
-       histo->size = size;
-
-       histo->xmin = bbox->LLB.x;
-       histo->ymin = bbox->LLB.y;
-
-
-       histo->xmax = bbox->URT.x;
-       histo->ymax = bbox->URT.y;
-
-       histo->avgFeatureArea = 0;
-
-       histo->boxesPerSide = boxesPerSide;
-
-       for (t=0;t<boxesPerSide*boxesPerSide; t++)
-       {
-               histo->value[t] =0;
-       }
-
-       //elog(NOTICE,"create_histogram2d returning");
-
-       PG_RETURN_POINTER(histo);
-
-}
-
-
-//text form of HISTOGRAM2D is:
-// 'HISTOGRAM2D(xmin,ymin,xmax,ymax,boxesPerSide;value[0],value[1],...')
-//    note the ";" in the middle (for easy parsing)
-//  I dont expect anyone to actually create one by hand
-PG_FUNCTION_INFO_V1(histogram2d_in);
-Datum histogram2d_in(PG_FUNCTION_ARGS)
-{
-       char                    *str = PG_GETARG_CSTRING(0);
-       HISTOGRAM2D         *histo ;
-       int nitems;
-       double xmin,ymin,xmax,ymax;
-       int boxesPerSide;
-       double avgFeatureArea;
-       char *str2,*str3;
-       long datum;
-
-       int t;
-
-       while (isspace((unsigned char) *str))
-               str++;
-
-       if (strstr(str,"HISTOGRAM2D(") != str)
-       {
-                       elog(ERROR,"histogram2d parser - doesnt start with 'HISTOGRAM2D(\n");
-                       PG_RETURN_NULL() ;
-       }
-       if (strstr(str,";") == NULL)
-       {
-                       elog(ERROR,"histogram2d parser - doesnt have a ; in sring!\n");
-                       PG_RETURN_NULL() ;
-       }
-
-       nitems = sscanf(str,"HISTOGRAM2D(%lf,%lf,%lf,%lf,%i,%lf;",&xmin,&ymin,&xmax,&ymax,&boxesPerSide,&avgFeatureArea);
-
-       if (nitems != 6)
-       {
-                       elog(ERROR,"histogram2d parser - couldnt parse initial portion of histogram!\n");
-                       PG_RETURN_NULL() ;
-       }
-
-       if  ( (boxesPerSide > 50) || (boxesPerSide <1) )
-       {
-                       elog(ERROR,"histogram2d parser - boxesPerSide is too big or too small\n");
-                       PG_RETURN_NULL() ;
-       }
-
-       str2 = strstr(str,";");
-       str2++;
-
-       if (str2[0] ==0)
-       {
-                       elog(ERROR,"histogram2d parser - no histogram values\n");
-                       PG_RETURN_NULL() ;
-       }
-
-       histo = (HISTOGRAM2D *) palloc (sizeof(HISTOGRAM2D) +    (boxesPerSide*boxesPerSide-1)*4 );
-       histo->size = sizeof(HISTOGRAM2D) +    (boxesPerSide*boxesPerSide-1)*4  ;
-
-       for (t=0;t<boxesPerSide*boxesPerSide;t++)
-       {
-               datum = strtol(str2,&str3,10); // str2=start of int, str3=end of int, base 10
-               // str3 points to "," or ")"
-               if (str3[0] ==0)
-               {
-                       elog(ERROR,"histogram2d parser - histogram values prematurely ended!\n");
-                       PG_RETURN_NULL() ;
-               }
-               histo->value[t] = (unsigned int) datum;
-               str2= str3+1; //move past the "," or ")"
-       }
-       histo->xmin = xmin;
-       histo->xmax = xmax;
-       histo->ymin = ymin;
-       histo->ymax = ymax;
-       histo->avgFeatureArea = avgFeatureArea;
-       histo->boxesPerSide = boxesPerSide;
-
-       PG_RETURN_POINTER(histo);
-}
-
-
-
-//text version
-PG_FUNCTION_INFO_V1(histogram2d_out);
-Datum histogram2d_out(PG_FUNCTION_ARGS)
-{
-       //char *result;
-       //result = palloc(200);
-       //sprintf(result,"HISTOGRAM2D(0,0,100,100,2;11,22,33,44)");
-       //PG_RETURN_CSTRING(result);
-
-               HISTOGRAM2D   *histo = (HISTOGRAM2D *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               char    *result;
-               int t;
-               char    temp[100];
-               int size;
-
-               size = 26+6*MAX_DIGS_DOUBLE + histo->boxesPerSide*histo->boxesPerSide* (MAX_DIGS_DOUBLE+1);
-               result = palloc(size);
-
-               sprintf(result,"HISTOGRAM2D(%.15g,%.15g,%.15g,%.15g,%i,%.15g;",
-                                       histo->xmin,histo->ymin,histo->xmax,histo->ymax,histo->boxesPerSide,histo->avgFeatureArea );
-
-               //elog(NOTICE,"so far: %s",result);
-               //elog(NOTICE,"buffsize=%i, size=%i",size,histo->size);
-
-               for (t=0;t<histo->boxesPerSide*histo->boxesPerSide;t++)
-               {
-                       if (t!=((histo->boxesPerSide*histo->boxesPerSide)-1))
-                               sprintf(temp,"%u,", histo->value[t]);
-                       else
-                               sprintf(temp,"%u", histo->value[t]);
-                       strcat(result,temp);
-               }
-
-               strcat(result,")");
-               //elog(NOTICE,"about to return string (len=%i): -%s-",strlen(result),result);
-
-               PG_RETURN_CSTRING(result);
-
-}
-
-
-
-int getint(char *c)
-{
-       int i;
-       memcpy( &i, c, 4);
-       return i;
-//return *((int*)c);
-}
-
-double getdouble(char *c)
-{
-       double d;
-       memcpy( &d, c, 8);
-       return d;
-//     return *((double*)c);
-}
-
-//void flip_endian_double(char *dd);
-//void         flip_endian_int32(char  *ii);
-
-
-//select geometry(asbinary('POINT(1 2 3)','XDR'));
-//select geometry(asbinary('POINT(1 2)','XDR'));
-//select geometry(asbinary('POINT(1 2 3)','NDR'));
-//select geometry(asbinary('POINT(1 2)','NDR'));
-
-//select geometry(asbinary('LINESTRING(1 2, 3 4)','XDR'));
-//select geometry(asbinary('LINESTRING(1 2, 3 4)','NDR'));
-//select geometry(asbinary('LINESTRING(1 2 5 , 3 4 6)','XDR'));
-//select geometry(asbinary('LINESTRING(1 2 5 , 3 4 6)','NDR'));
-
-
-//select geometry(asbinary('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','XDR'));
-//select geometry(asbinary('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))','NDR'));
-//select geometry(asbinary('POLYGON((0 0 0, 10 0, 10 10, 0 10, 0 0))','XDR'));
-//select geometry(asbinary('POLYGON((0 0 0, 10 0, 10 10, 0 10, 0 0))','NDR'));
-
-//select geometry(asbinary('POLYGON((5 5, 15 5, 15 7, 5 7, 5 5 ),(6 6,6.5 6, 6.5 6.5,6 6.5,6 6))','NDR'));
-//select geometry(asbinary('POLYGON((5 5, 15 5, 15 7, 5 7, 5 5 ),(6 6,6.5 6, 6.5 6.5,6 6.5,6 6))','XDR'));
-//select geometry(asbinary('POLYGON((5 5 0, 15 5, 15 7, 5 7, 5 5 ),(6 6,6.5 6, 6.5 6.5,6 6.5,6 6))','NDR'));
-//select geometry(asbinary('POLYGON((5 5 0, 15 5, 15 7, 5 7, 5 5 ),(6 6,6.5 6, 6.5 6.5,6 6.5,6 6))','XDR'));
-
-
-//select geometry(asbinary('MULTIPOINT(0 0, 10 0, 10 10, 0 10, 0 0)','NDR'));
-//select geometry(asbinary('MULTIPOINT(0 0, 10 0, 10 10, 0 10, 0 0 0)','NDR'));
-//select geometry(asbinary('MULTIPOINT(0 0, 10 0, 10 10, 0 10, 0 0)','XDR'));
-//select geometry(asbinary('MULTIPOINT(0 0, 10 0, 10 10, 0 10, 0 0 0)','NDR'));
-
-
-//select geometry(asbinary('MULTILINESTRING((5 5, 10 10),(1 1, 2 2) )','NDR'));
-//select geometry(asbinary('MULTILINESTRING((5 5, 10 10),(1 1, 2 2 0) )','NDR'));
-//select geometry(asbinary('MULTILINESTRING((5 5, 10 10),(1 1, 2 2) )','XDR'));
-//select geometry(asbinary('MULTILINESTRING((5 5, 10 10),(1 1, 2 2 0) )','XDR'));
-
-
-//select geometry(asbinary('MULTIPOLYGON(((5 5, 15 5, 15 7, 5 7, 5 5)),((1 1,1 2,2 2,1 2, 1 1)))','NDR'));
-//select geometry(asbinary('MULTIPOLYGON(((5 5, 15 5, 15 7, 5 7, 5 5)),((1 1,1 2,2 2,1 2, 1 1 0)))','NDR'));
-//select geometry(asbinary('MULTIPOLYGON(((5 5, 15 5, 15 7, 5 7, 5 5)),((1 1,1 2,2 2,1 2, 1 1)))','XDR'));
-//select geometry(asbinary('MULTIPOLYGON(((5 5, 15 5, 15 7, 5 7, 5 5)),((1 1,1 2,2 2,1 2, 1 1 0)))','XDR'));
-
-
-//select geometry(asbinary('GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))','NDR'));
-//select geometry(asbinary('GEOMETRYCOLLECTION(POINT(1 2 3),LINESTRING(1 2, 3 4),POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)))','NDR'));
-// geometryfromWKB(<WKB>, [<SRID>] )
-PG_FUNCTION_INFO_V1(geometryfromWKB_SRID);
-Datum geometryfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               char   *wkb_input = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               int    SRID = PG_GETARG_INT32(1);
-               char *wkb = &wkb_input[4];
-               int wkb_size = *((int *) wkb_input);
-               int bytes_read;
-               GEOMETRY *result;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-//elog(NOTICE,"geometryfromWKB:: size = %i",wkb_size);
-
-       result = WKBtoGeometry(wkb,wkb_size,&bytes_read);
-
-       if (result == NULL)
-       {
-               PG_RETURN_NULL();
-       }
-       else
-       {
-               result->SRID = SRID;
-               PG_RETURN_POINTER(result);
-       }
-}
-
-PG_FUNCTION_INFO_V1(PointfromWKB_SRID);
-Datum PointfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != POINTTYPE)
-               {
-                       elog(ERROR,"PointfromWKB:: WKB isnt POINT");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(LinefromWKB_SRID);
-Datum LinefromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != LINETYPE)
-               {
-                       elog(ERROR,"LinefromWKB_SRID:: WKB isnt LINESTRING");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(PolyfromWKB_SRID);
-Datum PolyfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != POLYGONTYPE)
-               {
-                       elog(ERROR,"PolyfromWKB_SRID:: WKB isnt POLYGON");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(MPointfromWKB_SRID);
-Datum MPointfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTIPOINTTYPE)
-               {
-                       elog(ERROR,"MPointfromWKB_SRID:: WKB isnt MULTIPOINT");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(MLinefromWKB_SRID);
-Datum MLinefromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTILINETYPE)
-               {
-                       elog(ERROR,"MLinefromWKB_SRID:: WKB isnt MULTILINESTRING");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(MPolyfromWKB_SRID);
-Datum MPolyfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTIPOLYGONTYPE)
-               {
-                       elog(ERROR,"MPolyfromWKB_SRID:: WKB isnt MULTIPOLYGON");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(GCfromWKB_SRID);
-Datum GCfromWKB_SRID(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometryfromWKB_SRID,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != COLLECTIONTYPE)
-               {
-                       elog(ERROR,"MPolyfromWKB_SRID:: WKB isnt GEOMETRYCOLLECTION");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-
-
-
-//convert a WKB (that has length bytes)
-// to a GEOMETRY.  This function read bytes_read bytes during the operation
-//  This function will call itself "recursively" on GeometryCollections
-GEOMETRY *WKBtoGeometry(char *WKB, int length, int *bytes_read)
-{
-                       char myByteOrder;
-                       char wkbByteOrder;
-                       int  wkbType;
-                       char    is3d;
-
-*bytes_read = 0;
-if (length<5)
-       elog(ERROR,"WKB:: insufficient bytes in stream");
-
-
-if ( BYTE_ORDER == BIG_ENDIAN )
-       myByteOrder=0;
-else
-       myByteOrder=1;
-
-wkbByteOrder = *(WKB);
-
-if (!( (wkbByteOrder==0) || (wkbByteOrder==1) ))
-{
-       elog(ERROR,"WKB is not valid - endian code = %i", (int) wkbByteOrder);
-       return NULL;
-}
-
-WKB ++; // skip to next byte
-(*bytes_read)++;
-
-if (myByteOrder == wkbByteOrder)
-{
-       wkbType = getint(WKB);
-}
-else
-{
-       flip_endian_int32( WKB );
-       wkbType = getint(WKB);
-}
-WKB += 4;
-(*bytes_read) += 4;
-
-//elog(NOTICE,"my byte order is %i",myByteOrder);
-//elog(NOTICE,"WKB byte order is %i",wkbByteOrder);
-//elog(NOTICE,"WKB type is %i",wkbType);
-
-is3d = 0;
-
-switch (wkbType)
-{
-       case (0x80000000 +1):  //point 3d
-                       is3d = 1;
-       case 1:  //point 2d
-                       if ( (length-(*bytes_read)) < (16+is3d*8))
-                               elog(ERROR,"WKB:: insufficient bytes in stream");
-                       {
-                               POINT3D pt;
-                               if (myByteOrder == wkbByteOrder)
-                               {
-                                       pt.x = getdouble(WKB);
-                                       WKB+=8;
-                                       (*bytes_read)+=8;
-                                       pt.y = getdouble(WKB);
-                                       WKB+=8;
-                                       (*bytes_read)+=8;
-                                       if (is3d)
-                                       {
-                                               pt.z = getdouble(WKB);
-                                               WKB+=8;
-                                               (*bytes_read)+=8;
-                                       }
-                                       else
-                                       {
-                                               pt.z=0;
-                                       }
-                               }
-                               else
-                               {
-                                       flip_endian_double(WKB);
-                                       pt.x = getdouble(WKB);
-                                       WKB+=8;
-                                       (*bytes_read)+=8;
-                                       flip_endian_double(WKB);
-                                       pt.y = getdouble(WKB);
-                                       WKB+=8;
-                                       (*bytes_read)+=8;
-                                       if (is3d)
-                                       {
-                                               flip_endian_double(WKB);
-                                               pt.z = getdouble(WKB);
-                                               WKB+=8;
-                                               (*bytes_read)+=8;
-                                       }
-                                       else
-                                       {
-                                               pt.z =0;
-                                       }
-                               }
-                               if ( ! finite(pt.x) || ! finite(pt.y) || ! finite(pt.z) )
-                               {
-                                       elog(ERROR, "infinite coordinate in geom");
-                                       return NULL;
-                               }
-                               return make_oneobj_geometry(sizeof(POINT3D),
-                                                                                       (char *) &pt,
-                                                                                       POINTTYPE,  is3d, -1,1.0, 0.0, 0.0
-                                               );
-                       }
-
-
-                       break;
-       case (0x80000000 +2):  //line 3d
-                       is3d = 1;
-       case 2: //line 2d
-                       if ( (length-(*bytes_read)) < (4))
-                               elog(ERROR,"WKB:: insufficient bytes in stream");
-                               {
-                                               int npoints,t;
-                                               POINT3D *pts;
-                                               int size;
-                                               LINE3D  *line;
-                                               if (myByteOrder == wkbByteOrder)
-                                               {
-                                                       npoints= getint(WKB);
-                                                       WKB+=4;
-                                                       (*bytes_read)+=4;
-                                                       if ( (length-(*bytes_read)) < ((16+is3d*8))*npoints)
-                                                               elog(ERROR,"WKB:: insufficient bytes in stream");
-
-                                                       pts = palloc( npoints *sizeof(POINT3D));
-                                                       for (t=0;t<npoints;t++)
-                                                       {
-                                                               pts[t].x = getdouble(WKB);
-                                                               WKB+=8;
-                                                               (*bytes_read)+=8;
-                                                               pts[t].y = getdouble(WKB);
-                                                               WKB+=8;
-                                                               (*bytes_read)+=8;
-                                                               if (is3d)
-                                                               {
-                                                                       pts[t].z = getdouble(WKB);
-                                                                       WKB+=8;
-                                                                       (*bytes_read)+=8;
-                                                               }
-                                                               else
-                                                               {
-                                                                       pts[t].z =0;
-                                                               }
-                                                               if ( ! finite(pts[t].x) || ! finite(pts[t].y) || ! finite(pts[t].z) )
-                                                               {
-                                                                       elog(ERROR, "infinite coordinate in geom");
-                                                                       return NULL;
-                                                               }
-                                                       }
-                                                       //make_line(int  npoints, POINT3D    *pts, int   *size)
-                                                       line = make_line(npoints, pts,&size);
-                                                       return make_oneobj_geometry(size,
-                                                                                                               (char *) line,
-                                                                                                               LINETYPE,  is3d, -1,1.0, 0.0, 0.0
-                                                                                       );
-                                               }
-                                               else
-                                               {
-                                                       flip_endian_int32(WKB);
-                                                       npoints= getint(WKB);
-                                                       WKB+=4;
-                                                       (*bytes_read)+=4;
-                                                       if ( (length-(*bytes_read)) < ((16+is3d*8))*npoints)
-                                                               elog(ERROR,"WKB:: insufficient bytes in stream");
-                                                       pts = palloc( npoints *sizeof(POINT3D));
-                                                       for (t=0;t<npoints;t++)
-                                                       {
-                                                               flip_endian_double(WKB);
-                                                               pts[t].x = getdouble(WKB);
-                                                               WKB+=8;
-                                                               (*bytes_read)+=8;
-                                                               flip_endian_double(WKB);
-                                                               pts[t].y = getdouble(WKB);
-                                                               WKB+=8;
-                                                               (*bytes_read)+=8;
-                                                               if (is3d)
-                                                               {
-                                                                       flip_endian_double(WKB);
-                                                                       pts[t].z = getdouble(WKB);
-                                                                       WKB+=8;
-                                                                       (*bytes_read)+=8;
-                                                               }
-                                                               else
-                                                               {
-                                                                       pts[t].z =0;
-                                                               }
-                                                               if ( ! finite(pts[t].x) || ! finite(pts[t].y) || ! finite(pts[t].z) )
-                                                               {
-                                                                       elog(ERROR, "infinite coordinate in geom");
-                                                                       return NULL;
-                                                               }
-                                                       }
-                                                       //make_line(int  npoints, POINT3D    *pts, int   *size)
-                                                       line = make_line(npoints, pts,&size);
-                                                       return make_oneobj_geometry(size, (char *) line, LINETYPE,  is3d, -1,1.0, 0.0, 0.0);
-                                               }
-                                       }
-                       break;
-       case (0x80000000 +3):  //polygon 3d
-                       is3d =1;
-       case 3: //polygon
-               if ( (length-(*bytes_read)) < (4))
-                               elog(ERROR,"WKB:: insufficient bytes in stream");
-               {
-                               int nrings;
-                               POINT3D** list_list_points;
-                               int32  *points_per_ring;
-                               int t;
-                               int total_points =0;
-                               POLYGON3D *poly;
-                               int size;
-                               POINT3D *pts;
-                               int point_offset;
-
-                       if (myByteOrder == wkbByteOrder)
-                       {
-                               nrings= getint(WKB);
-                               WKB+=4;
-                               (*bytes_read)+=4;
-                               list_list_points = palloc( sizeof(POINT3D*) * nrings);
-                               points_per_ring  = palloc( sizeof(int32*) * nrings);
-                               for (t=0;t<nrings;t++)
-                               {
-                                       int bytes, numbPoints;
-
-                                       list_list_points[t] =
-                                                       wkb_linearring(WKB, is3d, 0, &numbPoints, &bytes,length-(*bytes_read));
-                                       points_per_ring[t] = numbPoints;
-                                       total_points += numbPoints;
-                                       WKB += bytes;
-                                       (*bytes_read)+=bytes;
-                               }
-
-                       }
-                       else
-                       {
-                               flip_endian_int32(WKB);
-                               nrings= getint(WKB);
-                               WKB+=4;
-                               (*bytes_read)+=4;
-                               list_list_points = palloc( sizeof(POINT3D*) * nrings);
-                               points_per_ring  = palloc( sizeof(int32*) * nrings);
-                               for (t=0;t<nrings;t++)
-                               {
-                                       int bytes, numbPoints;
-
-                                       list_list_points[t] =
-                                                       wkb_linearring(WKB, is3d, 1, &numbPoints, &bytes,length-(*bytes_read));
-                                       points_per_ring[t] = numbPoints;
-                                       total_points += numbPoints;
-                                       WKB += bytes;
-                                       (*bytes_read)+=bytes;
-                               }
-                       }
-                       //compact point arrays
-                       pts = palloc ( sizeof(POINT3D) * total_points);
-                       point_offset  = 0;
-                       for (t=0;t<nrings;t++)
-                       {
-                               memcpy( &pts[point_offset],list_list_points[t], sizeof(POINT3D)*points_per_ring[t]);
-                               point_offset += points_per_ring[t];
-                       }
-                       poly = make_polygon( nrings, points_per_ring, pts, total_points, &size);
-                       return make_oneobj_geometry(size,
-                                                                               (char *) poly,
-                                                                               POLYGONTYPE,  is3d, -1,1.0, 0.0, 0.0
-                                       );
-               }
-
-                       break;
-       case (0x80000000 +4):  //multipoint 3d
-       case 4: //multipoint
-                               {
-                                       int ngeoms,t;
-                                       GEOMETRY *so_far,*so_far2;
-                                       GEOMETRY *one_obj;
-
-                                       int mybytes_read;
-                                       int other_bytes_read;
-
-                                       if (myByteOrder != wkbByteOrder)
-                                       {
-                                               flip_endian_int32(WKB);
-                                       }
-                                       ngeoms= getint(WKB);
-                                       WKB+=4;
-                                       (*bytes_read)+=4;
-                                       if (ngeoms ==0)
-                                       {
-                                               GEOMETRY *result= makeNullGeometry(-1);
-                                               result->type = MULTIPOINTTYPE;
-                                               return result;
-                                       }
-
-                                               mybytes_read = *bytes_read;
-                                               so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                               (*bytes_read) =  mybytes_read + other_bytes_read;
-                                               WKB += other_bytes_read;
-                                               so_far->type = MULTIPOINTTYPE;
-
-                                               if (ngeoms ==1)
-                                                       return so_far;
-
-                                       for (t=1;t<ngeoms;t++) // already done the first
-                                       {
-                                               mybytes_read = *bytes_read;
-                                               one_obj = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                               (*bytes_read) =  mybytes_read + other_bytes_read;
-                                               WKB += other_bytes_read;
-                                               so_far2 =
-                                                       (GEOMETRY *) DatumGetPointer(
-                                                                               DirectFunctionCall2(collector,
-                                                                                               PointerGetDatum(so_far),PointerGetDatum(one_obj)
-                                                                                       )
-                                                                       );
-                                               pfree(one_obj);
-                                               pfree(so_far);
-                                               so_far = so_far2;
-                                       }
-                                       return so_far;
-                               }
-       case (0x80000000 +5):  //multiline 3d
-       case 5: //multiline
-                       {
-                                       int ngeoms,t;
-                                       GEOMETRY *so_far,*so_far2;
-                                       GEOMETRY *one_obj;
-
-                                       int mybytes_read;
-                                       int other_bytes_read;
-
-                                       if (myByteOrder != wkbByteOrder)
-                                       {
-                                               flip_endian_int32(WKB);
-                                       }
-                                       ngeoms= getint(WKB);
-                                       WKB+=4;
-                                       (*bytes_read)+=4;
-                                       if (ngeoms ==0)
-                                       {
-                                               GEOMETRY *result= makeNullGeometry(-1);
-                                               result->type = MULTILINETYPE;
-                                               return result;
-                                       }
-
-                                               mybytes_read = *bytes_read;
-                                               so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                               (*bytes_read) =  mybytes_read + other_bytes_read;
-                                               WKB += other_bytes_read;
-                                               so_far->type = MULTILINETYPE;
-
-                                               if (ngeoms ==1)
-                                                       return so_far;
-
-                                       for (t=1;t<ngeoms;t++) // already done the first
-                                       {
-                                               mybytes_read = *bytes_read;
-                                               one_obj = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                               (*bytes_read) =  mybytes_read + other_bytes_read;
-                                               WKB += other_bytes_read;
-                                               so_far2 =
-                                                       (GEOMETRY *) DatumGetPointer(
-                                                                               DirectFunctionCall2(collector,
-                                                                                               PointerGetDatum(so_far),PointerGetDatum(one_obj)
-                                                                                       )
-                                                                       );
-                                               pfree(one_obj);
-                                               pfree(so_far);
-                                               so_far = so_far2;
-                                       }
-                                       return so_far;
-                               }
-       case (0x80000000 +6):  //multipolygon 3d
-       case 6: //multipolygon
-                       {
-                               int ngeoms,t;
-                               GEOMETRY *so_far,*so_far2;
-                               GEOMETRY *one_obj;
-
-                               int mybytes_read;
-                               int other_bytes_read;
-
-                               if (myByteOrder != wkbByteOrder)
-                               {
-                                       flip_endian_int32(WKB);
-                               }
-                               ngeoms= getint(WKB);
-                               WKB+=4;
-                               (*bytes_read)+=4;
-                               if (ngeoms ==0)
-                               {
-                                       GEOMETRY *result= makeNullGeometry(-1);
-                                       result->type = MULTIPOLYGONTYPE;
-                                       return result;
-                               }
-
-                                       mybytes_read = *bytes_read;
-                                       so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                       (*bytes_read) =  mybytes_read + other_bytes_read;
-                                       WKB += other_bytes_read;
-                                       so_far->type = MULTIPOLYGONTYPE;
-
-                                       if (ngeoms ==1)
-                                               return so_far;
-
-                               for (t=1;t<ngeoms;t++) // already done the first
-                               {
-                                       mybytes_read = *bytes_read;
-                                       one_obj = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                       (*bytes_read) =  mybytes_read + other_bytes_read;
-                                       WKB += other_bytes_read;
-                                       so_far2 =
-                                               (GEOMETRY *) DatumGetPointer(
-                                                                       DirectFunctionCall2(collector,
-                                                                                       PointerGetDatum(so_far),PointerGetDatum(one_obj)
-                                                                               )
-                                                               );
-                                       pfree(one_obj);
-                                       pfree(so_far);
-                                       so_far = so_far2;
-                               }
-                               return so_far;
-                       }
-       case (0x80000000 +7):  //geometry collection 3d
-       case 7: //geometry collection
-                       {
-                               int ngeoms,t;
-                               GEOMETRY *so_far,*so_far2;
-                               GEOMETRY *one_obj;
-
-                               int mybytes_read;
-                               int other_bytes_read;
-
-                               if (myByteOrder != wkbByteOrder)
-                               {
-                                       flip_endian_int32(WKB);
-                               }
-                               ngeoms= getint(WKB);
-                               WKB+=4;
-                               (*bytes_read)+=4;
-                               if (ngeoms ==0)
-                               {
-                                       GEOMETRY *result= makeNullGeometry(-1);
-                                       return result;
-                               }
-
-                                       mybytes_read = *bytes_read;
-                                       so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                       (*bytes_read) =  mybytes_read + other_bytes_read;
-                                       WKB += other_bytes_read;
-                                       so_far->type = COLLECTIONTYPE;
-
-                                       if (ngeoms ==1)
-                                               return so_far;
-
-                               for (t=1;t<ngeoms;t++) // already done the first
-                               {
-                                       mybytes_read = *bytes_read;
-                                       one_obj = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
-                                       (*bytes_read) =  mybytes_read + other_bytes_read;
-                                       WKB += other_bytes_read;
-                                       so_far2 =
-                                               (GEOMETRY *) DatumGetPointer(
-                                                                       DirectFunctionCall2(collector,
-                                                                                       PointerGetDatum(so_far),PointerGetDatum(one_obj)
-                                                                               )
-                                                               );
-                                       pfree(one_obj);
-                                       pfree(so_far);
-                                       so_far = so_far2;
-                               }
-                               return so_far;
-                       }
-       default:
-               elog(ERROR,"unknown WKB type: %i",wkbType);
-               return NULL;
-}
-return NULL;
-}
-
-// take some wkt (and if its 3d or needs endianflip) and return as list of points
-//  also return the number of points and its size in bytes
-//
-POINT3D *wkb_linearring(char *WKB,char is3d, char flip_endian, int *numbPoints, int *bytes,int bytes_in_stream)
-{
-       int t;
-
-       if (bytes_in_stream < 4)
-               elog(ERROR,"WKB:: insufficient bytes in stream");
-
-       if (flip_endian)
-       {
-               POINT3D *pts;
-               int npoints;
-
-               flip_endian_int32(WKB);
-               npoints= getint(WKB);
-               WKB+=4;
-               if ( (bytes_in_stream-4) < ((16+is3d*8))*npoints)
-                                       elog(ERROR,"WKB:: insufficient bytes in stream");
-               pts = palloc( npoints *sizeof(POINT3D));
-               for (t=0;t<npoints;t++)
-               {
-                       flip_endian_double(WKB);
-                       pts[t].x = getdouble(WKB);
-                       WKB+=8;
-                       flip_endian_double(WKB);
-                       pts[t].y = getdouble(WKB);
-                       WKB+=8;
-                       if (is3d)
-                       {
-                               flip_endian_double(WKB);
-                               pts[t].z = getdouble(WKB);
-                               WKB+=8;
-                       }
-                       else
-                       {
-                               pts[t].z =0;
-                       }
-                       if ( ! finite(pts[t].x) || ! finite(pts[t].y) || ! finite(pts[t].z) )
-                       {
-                               elog(ERROR, "infinite coordinate in geom");
-                               return NULL;
-                       }
-               }
-               *numbPoints = npoints;
-               if (is3d)
-               {
-                       *bytes = 4+8*3*npoints;
-               }
-               else
-               {
-                       *bytes = 4+8*2*npoints;
-               }
-               return pts;
-       }
-       else
-       {
-               POINT3D *pts;
-               int npoints;
-
-               npoints= getint(WKB);
-               WKB+=4;
-               if ( (bytes_in_stream-4) < ((16+is3d*8))*npoints)
-                                       elog(ERROR,"WKB:: insufficient bytes in stream");
-               pts = palloc( npoints *sizeof(POINT3D));
-               for (t=0;t<npoints;t++)
-               {
-                       pts[t].x = getdouble(WKB);
-                       WKB+=8;
-                       pts[t].y = getdouble(WKB);
-                       WKB+=8;
-                       if (is3d)
-                       {
-                               pts[t].z = getdouble(WKB);
-                               WKB+=8;
-                       }
-                       else
-                       {
-                               pts[t].z =0;
-                       }
-               }
-               *numbPoints = npoints;
-               if (is3d)
-               {
-                       *bytes = 4+8*3*npoints;
-               }
-               else
-               {
-                       *bytes = 4+8*2*npoints;
-               }
-               return pts;
-       }
-}
-
-
-
-PG_FUNCTION_INFO_V1(geometry_from_text_poly);
-Datum geometry_from_text_poly(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != POLYGONTYPE)
-               {
-                       elog(ERROR,"geometry_from_text_poly:: WKT isnt POLYGON");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(geometry_from_text_line);
-Datum geometry_from_text_line(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != LINETYPE)
-               {
-                       elog(ERROR,"geometry_from_text_line:: WKT isnt LINESTRING");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-
-PG_FUNCTION_INFO_V1(geometry_from_text_point);
-Datum geometry_from_text_point(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != POINTTYPE)
-               {
-                       elog(ERROR,"geometry_from_text_point:: WKT isnt POINT");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(geometry_from_text_mpoint);
-Datum geometry_from_text_mpoint(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTIPOINTTYPE)
-               {
-                       elog(ERROR,"geometry_from_text_mpoint:: WKT isnt MULTIPOINT");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(geometry_from_text_mline);
-Datum geometry_from_text_mline(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTILINETYPE)
-               {
-                       elog(ERROR,"geometry_from_text_mline:: WKT isnt MULTILINESTRING");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(geometry_from_text_mpoly);
-Datum geometry_from_text_mpoly(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != MULTIPOLYGONTYPE)
-               {
-                       elog(ERROR,"geometry_from_text_mpoly:: WKT isnt MULTIPOLYGON");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-PG_FUNCTION_INFO_V1(geometry_from_text_gc);
-Datum geometry_from_text_gc(PG_FUNCTION_ARGS)
-{
-               int SRID;
-               GEOMETRY *geom;
-
-               if ( ! PG_ARGISNULL(1) )
-                       SRID = PG_GETARG_INT32(1);
-               else
-                       SRID = -1;
-
-
-               geom = (GEOMETRY *) DatumGetPointer(
-                                       DirectFunctionCall2(geometry_from_text,
-                                                       PG_GETARG_DATUM(0),Int32GetDatum(SRID)
-                                               ));
-               if (geom->type != COLLECTIONTYPE)
-               {
-                       elog(ERROR,"geometry_from_text_gc:: WKT isnt GEOMETRYCOLLECTION");
-               }
-               PG_RETURN_POINTER(geom);
-}
-
-
-//returns a GEOMETRYCOLLECTION(EMPTY)
-// bbox of this object is BOX3D(0 0 0, 0 0 0)
-//   but should be treated as NULL
-GEOMETRY *makeNullGeometry(int SRID)
-{
-               int size = sizeof(GEOMETRY);
-               GEOMETRY        *result = palloc(size);
-
-
-               memset(result,0, size ); // init to 0s
-
-               result->size = size;
-               result->nobjs = 0;
-               result->type = COLLECTIONTYPE;
-               result->is3d = false;
-
-
-               result->SRID = SRID;
-               result->scale = 1.0;
-               result->offsetX = 0;
-               result->offsetY = 0;
-
-               memset(&result->bvol,0, sizeof(BOX3D) );  //make bbox :: BOX3D(0 0 0, 0 0 0)
-
-       return result;
-}
-
-
diff --git a/hwgeom/postgis_ops.c b/hwgeom/postgis_ops.c
deleted file mode 100644 (file)
index 188cad3..0000000
+++ /dev/null
@@ -1,1123 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- * 
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.13  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.12  2003/11/20 15:34:02  strk
- * expected in-transaction memory release for btree operators
- *
- * Revision 1.11  2003/11/19 15:26:57  strk
- * Added geometry_le, geometry_ge, geometry_cmp functions,
- * modified geometry_lt, geometry_gt, geometry_eq to be consistent.
- *
- * Revision 1.10  2003/07/25 17:08:37  pramsey
- * Moved Cygwin endian define out of source files into postgis.h common
- * header file.
- *
- * Revision 1.9  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-#include "fmgr.h"
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-//given a bvol, make a "fake" geometry that contains it (for indexing)
-GEOMETRY *make_bvol_geometry(BOX3D *box)
-{
-       return (GEOMETRY *) DatumGetPointer(DirectFunctionCall1(get_geometry_of_bbox,PointerGetDatum(box) ) );
-}
-
-//   ***********************************
-//          GEOMETRY indexing (operator) fns
-//     NOTE:
-//             These work on the bbox of the geometry, not the 
-//             individual components (except same)
-//   ***********************************
-
-
-PG_FUNCTION_INFO_V1(box3d_same);
-Datum box3d_same(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *)  PG_GETARG_POINTER(0);
-       BOX3D              *box2 = (BOX3D *) PG_GETARG_POINTER(1);
-
-       bool            result;
-
-       result = (         FPeq(box1->LLB.x     , box2->LLB.x) &&
-                                  FPeq(box1->LLB.y     , box2->LLB.y) &&
-                                  FPeq(box1->URT.x     , box2->URT.x) &&
-                                  FPeq(box1->URT.y     , box2->URT.y)
-                               );
-       PG_RETURN_BOOL(result);
-}
-
-
-
-
-PG_FUNCTION_INFO_V1(geometry_overleft);
-Datum geometry_overleft(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-
-//printf("in geometry_overleft\n");
-//print_box(&geom1->bvol);
-//print_box(&geom2->bvol);
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       result = FPle(geom1->bvol.URT.x, geom2->bvol.URT.x);
-
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_left);
-Datum geometry_left(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-
-//printf("in geometry_left\n");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       result = FPlt(geom1->bvol.URT.x, geom2->bvol.LLB.x);
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-PG_FUNCTION_INFO_V1(geometry_right);
-Datum geometry_right(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-//printf("in geometry_right\n");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       result = FPgt(geom1->bvol.LLB.x, geom2->bvol.URT.x);
-       
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_overright);
-Datum geometry_overright(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-//printf("in geometry_overright\n");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       result = FPge(geom1->bvol.LLB.x, geom2->bvol.LLB.x);
-       
-
-
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_contained);
-Datum geometry_contained(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-//printf("in geometry_contained\n");
-
-
-       result = FPle(geom1->bvol.URT.x, geom2->bvol.URT.x) &&
-                                  FPge(geom1->bvol.LLB.x, geom2->bvol.LLB.x) &&
-                                  FPle(geom1->bvol.URT.y, geom2->bvol.URT.y) &&
-                                  FPge(geom1->bvol.LLB.y, geom2->bvol.LLB.y);
-       
-//printf("returning geometry_contained\n");
-       PG_RETURN_BOOL(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_contain);
-Datum geometry_contain(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool    result;
-//printf("in geometry_contain\n");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       result = FPge(geom1->bvol.URT.x, geom2->bvol.URT.x) &&
-                                  FPle(geom1->bvol.LLB.x, geom2->bvol.LLB.x) &&
-                                  FPge(geom1->bvol.URT.y, geom2->bvol.URT.y) &&
-                                  FPle(geom1->bvol.LLB.y, geom2->bvol.LLB.y);
-       
-
-
-       PG_RETURN_BOOL(result);
-}
-
-bool box3d_ov(BOX3D *box1, BOX3D *box2)
-{
-       bool    result;
-
-       result = 
-
-       /*overlap in x*/
-                ((    FPge(box1->URT.x, box2->URT.x) &&
-                        FPle(box1->LLB.x, box2->URT.x)) ||
-                       (FPge(box2->URT.x, box1->URT.x) &&
-                        FPle(box2->LLB.x, box1->URT.x)))
-       &&
-       /*overlap in y*/
-       ((FPge(box1->URT.y, box2->URT.y) &&
-         FPle(box1->LLB.y, box2->URT.y)) ||
-        (FPge(box2->URT.y, box1->URT.y) &&
-         FPle(box2->LLB.y, box1->URT.y)));
-
-//printf("box3d_ov about to return %i\n",(int) result);        
-       return result;
-}
-
-
-PG_FUNCTION_INFO_V1(geometry_overlap);
-Datum geometry_overlap(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-//printf("in geometry_overlap\n");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       PG_RETURN_BOOL(box3d_ov(&(geom1->bvol), &(geom2->bvol)));
-}
-
-
-bool is_same_point(POINT3D     *p1, POINT3D    *p2)
-{
-       return ( FPeq(p1->x, p2->x ) && FPeq(p1->y, p2->y ) &&FPeq(p1->z, p2->z ) );
-}
-
-bool is_same_line(LINE3D       *l1, LINE3D     *l2)
-{
-       int i;
-               //lines are directed, so all the points should be the same
-
-       if (l1->npoints != l2->npoints)
-               return FALSE; //simple case, not the same # of points
-
-       for (i=0;i<l2->npoints; i++)
-       {
-               if (!( is_same_point( &l1->points[i], &l2->points[i] ) ) )
-               {
-                       return FALSE;
-               }
-       }
-       return TRUE;
-}
-
-
-/***********************************************************
- *
- * Comparision function for use in Binary Tree searches
- * (ORDER BY, GROUP BY, DISTINCT)
- *
- ***********************************************************/
-
-
-PG_FUNCTION_INFO_V1(geometry_lt);
-Datum geometry_lt(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_lt called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) {
-               if  (geom1->bvol.LLB.x < geom2->bvol.LLB.x)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) {
-               if  (geom1->bvol.LLB.y < geom2->bvol.LLB.y)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) {
-               if  (geom1->bvol.LLB.z < geom2->bvol.LLB.z)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) {
-               if  (geom1->bvol.URT.x < geom2->bvol.URT.x)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) ) {
-               if  (geom1->bvol.URT.y < geom2->bvol.URT.y)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) {
-               if  (geom1->bvol.URT.z < geom2->bvol.URT.z)
-                       PG_RETURN_BOOL(TRUE);
-       }
-
-       PG_RETURN_BOOL(FALSE);
-}
-
-PG_FUNCTION_INFO_V1(geometry_le);
-Datum geometry_le(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_le called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) {
-               if  (geom1->bvol.LLB.x < geom2->bvol.LLB.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) {
-               if  (geom1->bvol.LLB.y < geom2->bvol.LLB.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) {
-               if  (geom1->bvol.LLB.z < geom2->bvol.LLB.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) {
-               if  (geom1->bvol.URT.x < geom2->bvol.URT.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) ) {
-               if  (geom1->bvol.URT.y < geom2->bvol.URT.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) {
-               if  (geom1->bvol.URT.z < geom2->bvol.URT.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-
-       PG_RETURN_BOOL(TRUE);
-}
-
-PG_FUNCTION_INFO_V1(geometry_eq);
-Datum geometry_eq(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_eq called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) 
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) 
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) 
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) 
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) )
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) 
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-
-       PG_RETURN_BOOL(TRUE);
-}
-
-PG_FUNCTION_INFO_V1(geometry_ge);
-Datum geometry_ge(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_ge called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) {
-               if  (geom1->bvol.LLB.x > geom2->bvol.LLB.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) {
-               if  (geom1->bvol.LLB.y > geom2->bvol.LLB.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) {
-               if  (geom1->bvol.LLB.z > geom2->bvol.LLB.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) {
-               if  (geom1->bvol.URT.x > geom2->bvol.URT.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) ) {
-               if  (geom1->bvol.URT.y > geom2->bvol.URT.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) {
-               if  (geom1->bvol.URT.z > geom2->bvol.URT.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-               PG_RETURN_BOOL(FALSE);
-       }
-
-       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-
-       PG_RETURN_BOOL(TRUE);
-}
-
-PG_FUNCTION_INFO_V1(geometry_gt);
-Datum geometry_gt(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_gt called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 )
-                       pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 )
-                       pfree(geom2);
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) {
-               if  (geom1->bvol.LLB.x > geom2->bvol.LLB.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) {
-               if  (geom1->bvol.LLB.y > geom2->bvol.LLB.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) {
-               if  (geom1->bvol.LLB.z > geom2->bvol.LLB.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) {
-               if  (geom1->bvol.URT.x > geom2->bvol.URT.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) ) {
-               if  (geom1->bvol.URT.y > geom2->bvol.URT.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) {
-               if  (geom1->bvol.URT.z > geom2->bvol.URT.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_BOOL(TRUE);
-               }
-       }
-
-       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-
-       PG_RETURN_BOOL(FALSE);
-}
-
-PG_FUNCTION_INFO_V1(geometry_cmp);
-Datum geometry_cmp(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       //elog(NOTICE, "geometry_cmp called");
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 )
-                       pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 )
-                       pfree(geom2);
-               elog(ERROR,
-                       "Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.x , geom2->bvol.LLB.x) ) {
-               if  (geom1->bvol.LLB.x < geom2->bvol.LLB.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.y , geom2->bvol.LLB.y) ) {
-               if  (geom1->bvol.LLB.y < geom2->bvol.LLB.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if  ( ! FPeq(geom1->bvol.LLB.z , geom2->bvol.LLB.z) ) {
-               if  (geom1->bvol.LLB.z < geom2->bvol.LLB.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.x , geom2->bvol.URT.x) ) {
-               if  (geom1->bvol.URT.x < geom2->bvol.URT.x)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.y , geom2->bvol.URT.y) ) {
-               if  (geom1->bvol.URT.y < geom2->bvol.URT.y)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if  ( ! FPeq(geom1->bvol.URT.z , geom2->bvol.URT.z) ) {
-               if  (geom1->bvol.URT.z < geom2->bvol.URT.z)
-               {
-                       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-                       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-                       PG_RETURN_INT32(-1);
-               }
-               if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-               if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-               PG_RETURN_INT32(1);
-       }
-
-       if ( (Pointer *)PG_GETARG_DATUM(0) != (Pointer *)geom1 ) pfree(geom1);
-       if ( (Pointer *)PG_GETARG_DATUM(1) != (Pointer *)geom2 ) pfree(geom2);
-
-       PG_RETURN_INT32(0);
-}
-
-
-//order of points in a ring IS important
-//order of rings is also important
-bool is_same_polygon(POLYGON3D *poly1, POLYGON3D       *poly2)
-{
-       int     i;
-       int     numb_points;
-       POINT3D *pts1, *pts2;
-
-
-       if (poly1->nrings != poly2->nrings)
-               return FALSE;
-       
-       numb_points = 0;
-       for (i=0; i< poly1->nrings; i++)
-       {
-               if (poly1->npoints[i] != poly2->npoints[i])
-                       return FALSE;
-               numb_points += poly1->npoints[i];
-       }
-
-       pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] )  );
-       pts1 = (POINT3D *) MAXALIGN(pts1);
-       
-
-       pts2 = (POINT3D *) ( (char *)&(poly2->npoints[poly2->nrings] )  );
-       pts2 = (POINT3D *) MAXALIGN(pts2);
-
-       for (i=0; i< numb_points; i++)
-       {
-               if (!( is_same_point( &pts1[i], &pts2[i] ) ) )
-               {
-                       return FALSE;
-               }
-
-       }
-       return TRUE;
-}
-
-
-
-//FIXED: 
-// geom1 same as geom2
-//  iff  
-//     + have same type
-//     + have same # objects
-//     + have same bvol
-//     + each object in geom1 has a corresponding object in geom2 (see above)
-PG_FUNCTION_INFO_V1(geometry_same);
-Datum geometry_same(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       bool                            result;
-       int                             i,j;
-       bool                            *already_hit;
-       int32                           type1,type2;
-       int32                           *offsets1,*offsets2;
-       char                            *o1,*o2;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-//printf("in geometry_same\n");
-
-       //This was removed because this doesnt actually refer to the geometry, but how it is represented
-       // to the user
-       //easy tests
-       //if (geom1->type != geom2-> type)
-       //      PG_RETURN_BOOL(FALSE);
-
-       
-
-       if (geom1->nobjs != geom2->nobjs)
-               PG_RETURN_BOOL(FALSE);  
-
-       result = DatumGetBool(DirectFunctionCall2(box3d_same,
-                                                               PointerGetDatum(&geom1->bvol), 
-                                                               PointerGetDatum(&geom2->bvol)   )     );
-
-       if (result == FALSE)
-               PG_RETURN_BOOL(FALSE);
-
-       if (geom1->nobjs<1)
-               return FALSE; // no objects (probably a BOXONLYTYPE) and bvols dont match
-
-//     printf("        +have to do it the hard way");
-
-       already_hit = (bool *) palloc (geom2->nobjs * sizeof(bool) );
-       memset(already_hit, 0, geom2->nobjs * sizeof(bool) ); //all false
-       
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-       offsets2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+ sizeof(int32) * geom2->nobjs ) ;
-
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom1->nobjs; j++)         //for each object in geom1
-       {
-               o1 = (char *) geom1 +offsets1[j] ;  
-               type1=  geom1->objType[j];
-
-               for(i=0;i<geom1->nobjs; i++)            //for each object in geom2
-               {
-                       o2 = (char *) geom2 +offsets2[i] ;  
-                       type2=  geom2->objType[j];
-                       
-                       if (  (type1 == type2) && (!(already_hit[i])) )
-                       {
-                               //see if they match
-                               if (type1 == POINTTYPE)
-                               {
-                                       if (is_same_point((POINT3D *) o1,(POINT3D *) o2))
-                                       {
-                                               already_hit[i] = TRUE;
-                                               break;
-                                       } 
-                               }
-                               if (type1 == LINETYPE)
-                               {
-                                       if (is_same_line((LINE3D *) o1,(LINE3D *) o2))
-                                       {
-                                               already_hit[i] = TRUE;
-                                               break;
-                                       } 
-
-                               }
-                               if (type2 == POLYGONTYPE)
-                               {
-                                       if (is_same_polygon((POLYGON3D *) o1,(POLYGON3D *) o2))
-                                       {
-                                               already_hit[i] = TRUE;
-                                               break;
-                                       } 
-                               }       
-                       }
-               }
-               if (i == geom1->nobjs)
-                       PG_RETURN_BOOL(FALSE);   // couldnt find match
-       }
-       PG_RETURN_BOOL(TRUE);
-}
-
-/*******************************************************
- *Box3d routines
- *******************************************************/
-
-
-
-/*             box_overlap             -               does box1 overlap box2?
- */
-PG_FUNCTION_INFO_V1(box3d_overlap);
-Datum box3d_overlap(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-       BOX3D              *box2 = (BOX3D *) PG_GETARG_POINTER(1);
-
-       PG_RETURN_BOOL(box3d_ov(box1, box2));
-}
-
-/*             box_overleft    -               is the right edge of box1 to the left of
- *                                                             the right edge of box2?
- *
- *             This is "less than or equal" for the end of a time range,
- *             when time ranges are stored as rectangles.
- */
-PG_FUNCTION_INFO_V1(box3d_overleft);
-Datum box3d_overleft(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-       BOX3D              *box2 = (BOX3D *) PG_GETARG_POINTER(1);
-
-       bool    result;
-
-       result = FPle(box1->URT.x, box2->URT.x);
-
-//printf("box3d_overleft about to return %i\n",(int) result);  
-
-       PG_RETURN_BOOL(result);
-}
-
-/*             box_right               -               is box1 strictly right of box2?
- */
-PG_FUNCTION_INFO_V1(box3d_right);
-Datum box3d_right(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-       BOX3D              *box2 = (BOX3D *) PG_GETARG_POINTER(1);
-
-       bool    result;
-
-       result = FPgt(box1->LLB.x, box2->URT.x);
-//printf("box3d_rightabout to return %i\n",(int) result);      
-
-       PG_RETURN_BOOL(result);
-}
-
-/*             box_contain             -               does box1 contain box2?
- */
-PG_FUNCTION_INFO_V1(box3d_contain);
-Datum box3d_contain(PG_FUNCTION_ARGS)
-{
-       BOX3D              *box1 = (BOX3D *) PG_GETARG_POINTER(0);
-       BOX3D              *box2 = (BOX3D *) PG_GETARG_POINTER(1);
-
-       bool result;
-
-       result = FPge(box1->URT.x, box2->URT.x) &&
-                                  FPle(box1->LLB.x, box2->LLB.x) &&
-                                  FPge(box1->URT.y, box2->URT.y) &&
-                                  FPle(box1->LLB.y, box2->LLB.y);
-       //printf("box3d_contain about to return %i\n",(int) result);    
-
-
-       PG_RETURN_BOOL(result);
-}
-
-
-/******************************************************
- * RTREE index requires these 3 functions
- ******************************************************/
-
-PG_FUNCTION_INFO_V1(geometry_union);
-Datum geometry_union(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 =  (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 =  (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       GEOMETRY                   *result = (GEOMETRY *) palloc(sizeof(GEOMETRY) );
-       BOX3D                           *n;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-
-       result->size = sizeof(GEOMETRY);
-       result->type = BBOXONLYTYPE;
-       result->nobjs = -1;
-       result->SRID = geom1->SRID;
-       result->scale = geom1->scale;
-       result->offsetX = geom1->offsetX;
-       result->offsetY = geom1->offsetY;
-
-
-       n = &result->bvol;
-
-       //cheat - just change the bbox
-
-        n->URT.x = max(geom1->bvol.URT.x, geom2->bvol.URT.x);
-        n->URT.y = max(geom1->bvol.URT.y, geom2->bvol.URT.y);
-        n->LLB.x = min(geom1->bvol.LLB.x, geom2->bvol.LLB.x);
-        n->LLB.y = min(geom1->bvol.LLB.y, geom2->bvol.LLB.y);
-
-       
-        n->URT.z = max(geom1->bvol.URT.z, geom2->bvol.URT.z);
-        n->LLB.z = min(geom1->bvol.LLB.z, geom2->bvol.LLB.z);
-
-         PG_FREE_IF_COPY(geom1, 0);
-        PG_FREE_IF_COPY(geom2, 1);
-
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_inter);
-Datum geometry_inter(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom1 =  (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       GEOMETRY                   *geom2 =  (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       GEOMETRY                   *result = (GEOMETRY *) palloc(sizeof(GEOMETRY) );
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       result->size = sizeof(GEOMETRY);
-       result->type = BBOXONLYTYPE;
-       result->nobjs = -1;
-       result->SRID = geom1->SRID;
-       result->scale = geom1->scale;
-       result->offsetX = geom1->offsetX;
-       result->offsetY = geom1->offsetY;
-
-       result->bvol.URT.x = min(geom1->bvol.URT.x, geom2->bvol.URT.x);
-       result->bvol.URT.y = min(geom1->bvol.URT.y, geom2->bvol.URT.y);
-       result->bvol.URT.z = min(geom1->bvol.URT.z, geom2->bvol.URT.z);
-
-       result->bvol.LLB.x = max(geom1->bvol.LLB.x, geom2->bvol.LLB.x);
-       result->bvol.LLB.y = max(geom1->bvol.LLB.y, geom2->bvol.LLB.y);
-       result->bvol.LLB.z = max(geom1->bvol.LLB.z, geom2->bvol.LLB.z);
-
-    if (result->bvol.URT.x < result->bvol.LLB.x || result->bvol.URT.y < result->bvol.LLB.y)
-    {
-               pfree(result);
-        /* Indicate "no intersection" by returning NULL pointer */
-        result = NULL;
-    }
-       PG_FREE_IF_COPY(geom1, 0);
-    PG_FREE_IF_COPY(geom2, 1);
-
-       PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(geometry_size);
-Datum geometry_size(PG_FUNCTION_ARGS)
-{
-       Pointer          aptr = PG_GETARG_POINTER(0);
-
-    float              *size = (float *) PG_GETARG_POINTER(1);
-    GEOMETRY           *a;
-       float                   xdim,ydim;
-
-    if (aptr == NULL)
-    {
-        *size = 0.0;
-               //printf("      + aprt==null return in 0.0\n");
-        PG_RETURN_VOID();
-    }
-
-       a = (GEOMETRY *)   PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-    if (a->bvol.URT.x <= a->bvol.LLB.x ||
-        a->bvol.URT.y <= a->bvol.LLB.y)
-        *size = 0.0;
-    else
-    {
-               xdim = (a->bvol.URT.x - a->bvol.LLB.x);
-        ydim = (a->bvol.URT.y - a->bvol.LLB.y);
-
-        *size = (float) (xdim * ydim);
-    }
-
-       //printf("      + about to return (and free) with %e\n",*size);
-
-    /* Avoid leaking memory when handed toasted input. */
-       PG_FREE_IF_COPY(a, 0);
-       
-       PG_RETURN_VOID();
-}
diff --git a/hwgeom/postgis_proj.c b/hwgeom/postgis_proj.c
deleted file mode 100644 (file)
index 9d09440..0000000
+++ /dev/null
@@ -1,646 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.14  2004/09/16 15:50:59  mleslie
- * Added the distance_sphere function to calculate the distance between two points
- * on an earth-sized sphere using an algorithm implemented by Bruno Wolff III.
- * Added the postgresql loader function.
- *
- * Revision 1.13  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.12  2004/02/06 00:42:25  dblasby
- * moved forward declarations from postgis.h to postgis_proj.c
- *
- * Revision 1.11  2004/02/05 20:31:48  dblasby
- * Optimized the curvature method (doesnt have to calculate e2)
- *
- * Revision 1.10  2004/02/05 20:21:14  dblasby
- * Added 'curvature method' for cases where the original algorithm breaks down.
- *
- * Revision 1.9  2004/02/04 02:53:20  dblasby
- * applied patricia tozer's patch (distance function was taking acos of something
- * just slightly outside [-1,1]).
- *
- * Revision 1.8  2003/12/04 18:58:35  dblasby
- * changed david skae to skea
- *
- * Revision 1.7  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-
-#include "fmgr.h"
-
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-//     distance from -126 49  to -126 49.011096139863 in 'SPHEROID["GRS_1980",6378137,298.257222101]' is 1234.000
-
-
-double distance_sphere_method(double lat1, double long1,double lat2,double long2, SPHEROID *sphere);
-double distance_ellipse_calculation(double lat1, double long1,
-                                       double lat2, double long2,
-                                       SPHEROID *sphere);
-
-//use the WKT definition of an ellipsoid
-// ie. SPHEROID["name",A,rf] or SPHEROID("name",A,rf)
-//       SPHEROID["GRS_1980",6378137,298.257222101]
-// wkt says you can use "(" or "["
-
-PG_FUNCTION_INFO_V1(ellipsoid_in);
-Datum ellipsoid_in(PG_FUNCTION_ARGS)
-{
-       char               *str = PG_GETARG_CSTRING(0);
-       SPHEROID           *sphere = (SPHEROID *) palloc(sizeof(SPHEROID));
-       int                nitems;
-       double     rf;
-
-
-       memset(sphere,0, sizeof(SPHEROID));
-
-       if (strstr(str,"SPHEROID") !=  str )
-       {
-                elog(ERROR,"SPHEROID parser - doesnt start with SPHEROID");
-                pfree(sphere);
-                PG_RETURN_NULL();
-       }
-
-       nitems = sscanf(str,"SPHEROID[\"%19[^\"]\",%lf,%lf]",sphere->name,&sphere->a,&rf);
-
-       if ( nitems==0)
-               nitems = sscanf(str,"SPHEROID(\"%19[^\"]\",%lf,%lf)",sphere->name,&sphere->a,&rf);
-
-       if (nitems != 3)
-       {
-                elog(ERROR,"SPHEROID parser - couldnt parse the spheroid");
-                pfree(sphere);
-                PG_RETURN_NULL();
-       }
-
-       sphere->f = 1.0/rf;
-       sphere->b = sphere->a - (1.0/rf)*sphere->a;
-       sphere->e_sq = ((sphere->a*sphere->a) - (sphere->b*sphere->b) )/ (sphere->a*sphere->a);
-       sphere->e = sqrt(sphere->e_sq);
-
-       PG_RETURN_POINTER(sphere);
-
-}
-
-
-
-PG_FUNCTION_INFO_V1(ellipsoid_out);
-Datum ellipsoid_out(PG_FUNCTION_ARGS)
-{
-       SPHEROID  *sphere = (SPHEROID *) PG_GETARG_POINTER(0);
-       char    *result;
-
-       result = palloc(MAX_DIGS_DOUBLE + MAX_DIGS_DOUBLE + 20 + 9 + 2);
-
-       sprintf(result,"SPHEROID(\"%s\",%.15g,%.15g)", sphere->name,sphere->a, 1.0/sphere->f);
-
-       PG_RETURN_CSTRING(result);
-}
-
-//support function for distance calc
-       //code is taken from David Skea
-       //Geographic Data BC, Province of British Columbia, Canada.
-       // Thanks to GDBC and David Skea for allowing this to be
-       // put in PostGIS.
-double deltaLongitude(double azimuth, double sigma, double tsm,SPHEROID *sphere)
-{
-       // compute the expansion C
-       double das,C;
-       double ctsm,DL;
-
-       das = cos(azimuth)*cos(azimuth);
-       C = sphere->f/16.0 * das * (4.0 + sphere->f * (4.0 - 3.0 * das));
-       // compute the difference in longitude
-
-       ctsm = cos(tsm);
-       DL = ctsm + C * cos(sigma) * (-1.0 + 2.0 * ctsm*ctsm);
-       DL = sigma + C * sin(sigma) * DL;
-       return (1.0 - C) * sphere->f * sin(azimuth) * DL;
-}
-
-
-//support function for distance calc
-       //code is taken from David Skea
-       //Geographic Data BC, Province of British Columbia, Canada.
-       // Thanks to GDBC and David Skea for allowing this to be
-       // put in PostGIS.
-double mu2(double azimuth,SPHEROID *sphere)
-{
-       double    e2;
-
-       e2 = sqrt(sphere->a*sphere->a-sphere->b*sphere->b)/sphere->b;
-       return cos(azimuth)*cos(azimuth) * e2*e2;
-}
-
-
-//support function for distance calc
-       //code is taken from David Skea
-       //Geographic Data BC, Province of British Columbia, Canada.
-       // Thanks to GDBC and David Skea for allowing this to be
-       // put in PostGIS.
-double bigA(double u2)
-{
-       return 1.0 + u2/256.0 * (64.0 + u2 * (-12.0 + 5.0 * u2));
-}
-
-
-//support function for distance calc
-       //code is taken from David Skea
-       //Geographic Data BC, Province of British Columbia, Canada.
-       // Thanks to GDBC and David Skea for allowing this to be
-       // put in PostGIS.
-double bigB(double u2)
-{
-       return u2/512.0 * (128.0 + u2 * (-64.0 + 37.0 * u2));
-}
-
-
-
-double distance_ellipse(double lat1, double long1,
-                                       double lat2, double long2,
-                                       SPHEROID *sphere)
-{
-               double result;
-
-           if ( (lat1==lat2) && (long1 == long2) )
-               {
-                       return 0.0; // same point, therefore zero distance
-               }
-
-               result = distance_ellipse_calculation(lat1,long1,lat2,long2,sphere);
-//             result2 =  distance_sphere_method(lat1, long1,lat2,long2, sphere);
-
-//elog(NOTICE,"delta = %lf, skae says: %.15lf,2 circle says: %.15lf",(result2-result),result,result2);
-//elog(NOTICE,"2 circle says: %.15lf",result2);
-
-               if (result != result)  // NaN check (x==x for all x except NaN by IEEE definition)
-               {
-                       result =  distance_sphere_method(lat1, long1,lat2,long2, sphere);
-               }
-
-               return result;
-}
-
-//given 2 lat/longs and ellipse, find the distance
-// note original r = 1st, s=2nd location
-double distance_ellipse_calculation(double lat1, double long1,
-                                       double lat2, double long2,
-                                       SPHEROID *sphere)
-{
-       //code is taken from David Skea
-       //Geographic Data BC, Province of British Columbia, Canada.
-       // Thanks to GDBC and David Skea for allowing this to be
-       // put in PostGIS.
-
-       double L1,L2,sinU1,sinU2,cosU1,cosU2;
-       double dl,dl1,dl2,dl3,cosdl1,sindl1;
-       double cosSigma,sigma,azimuthEQ,tsm;
-       double u2,A,B;
-       double dsigma;
-
-       double TEMP;
-
-       int iterations;
-
-
-       L1 = atan((1.0 - sphere->f ) * tan( lat1) );
-       L2 = atan((1.0 - sphere->f ) * tan( lat2) );
-       sinU1 = sin(L1);
-       sinU2 = sin(L2);
-       cosU1 = cos(L1);
-       cosU2 = cos(L2);
-
-       dl = long2- long1;
-       dl1 = dl;
-       cosdl1 = cos(dl);
-       sindl1 = sin(dl);
-       iterations = 0;
-       do {
-               cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosdl1;
-               sigma = acos(cosSigma);
-               azimuthEQ = asin((cosU1 * cosU2 * sindl1)/sin(sigma));
-
-                       // patch from patrica tozer to handle minor mathematical stability problem
-               TEMP = cosSigma - (2.0 * sinU1 * sinU2)/(cos(azimuthEQ)*cos(azimuthEQ));
-               if(TEMP > 1)
-               {
-                          TEMP = 1;
-               }
-               else if(TEMP < -1)
-               {
-                          TEMP = -1;
-               }
-        tsm = acos(TEMP);
-
-
-               //tsm = acos(cosSigma - (2.0 * sinU1 * sinU2)/(cos(azimuthEQ)*cos(azimuthEQ)));
-               dl2 = deltaLongitude(azimuthEQ, sigma, tsm,sphere);
-               dl3 = dl1 - (dl + dl2);
-               dl1 = dl + dl2;
-               cosdl1 = cos(dl1);
-               sindl1 = sin(dl1);
-               iterations++;
-       } while ( (iterations<999) && (fabs(dl3) > 1.0e-032));
-
-          // compute expansions A and B
-       u2 = mu2(azimuthEQ,sphere);
-       A = bigA(u2);
-       B = bigB(u2);
-
-       // compute length of geodesic
-       dsigma = B * sin(sigma) * (cos(tsm) + (B*cosSigma*(-1.0 + 2.0 * (cos(tsm)*cos(tsm))))/4.0);
-       return sphere->b * (A * (sigma - dsigma));
-}
-
-
-double length2d_ellipse_linestring(LINE3D      *line, SPHEROID         *sphere)
-{
-
-       int     i;
-       POINT3D *frm,*to;
-       double  dist = 0.0;
-
-       if (line->npoints <2)
-               return 0.0;     //must have >1 point to make sense
-
-       frm = &line->points[0];
-
-       for (i=1; i<line->npoints;i++)
-       {
-               to = &line->points[i];
-
-               dist +=  distance_ellipse(frm->y*M_PI/180.0 , frm->x*M_PI/180.0,
-                                               to->y*M_PI/180.0 , to->x*M_PI/180.0,
-                                               sphere);
-
-               frm = to;
-       }
-       return dist;
-}
-
-double length3d_ellipse_linestring(LINE3D      *line, SPHEROID         *sphere)
-{
-       int     i;
-       POINT3D *frm,*to;
-       double  dist = 0.0;
-       double  dist_ellipse;
-
-       if (line->npoints <2)
-               return 0.0;     //must have >1 point to make sense
-
-       frm = &line->points[0];
-
-       for (i=1; i<line->npoints;i++)
-       {
-               to = &line->points[i];
-
-               dist_ellipse =  distance_ellipse(frm->y*M_PI/180.0 , frm->x*M_PI/180.0,
-                                               to->y*M_PI/180.0 , to->x*M_PI/180.0,
-                                               sphere);
-
-               dist += sqrt(dist_ellipse*dist_ellipse + (frm->z*frm->z) );
-
-               frm = to;
-       }
-       return dist;
-
-
-}
-
-
-// length_ellipsoid(GEOMETRY, SPHEROID)
-// find the "length of a geometry"
-// length2d(point) = 0
-// length2d(line) = length of line
-// length2d(polygon) = 0
-// uses ellipsoidal math to find the distance
-//// x's are longitude, and y's are latitude - both in decimal degrees
-
-PG_FUNCTION_INFO_V1(length_ellipsoid);
-Datum length_ellipsoid(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               SPHEROID                *sphere = (SPHEROID *) PG_GETARG_POINTER(1);
-
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       LINE3D                  *line;
-       double                  dist = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o1 = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-               if (type1 == LINETYPE)  //LINESTRING
-               {
-                       line = (LINE3D *) o1;
-                       dist += length2d_ellipse_linestring(line,sphere);
-               }
-       }
-       PG_RETURN_FLOAT8(dist);
-
-
-
-}
-
-// length3d_ellipsoid(GEOMETRY, SPHEROID)
-// find the "length of a geometry"
-// length3d(point) = 0
-// length3d(line) = length of line
-// length3d(polygon) = 0
-// uses ellipsoidal math to find the distance on the XY plane, then
-//  uses simple Pythagoras theorm to find the 3d distance on each segment
-// x's are longitude, and y's are latitude - both in decimal degrees
-
-PG_FUNCTION_INFO_V1(length3d_ellipsoid);
-Datum length3d_ellipsoid(PG_FUNCTION_ARGS)
-{
-               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               SPHEROID                *sphere = (SPHEROID *) PG_GETARG_POINTER(1);
-
-       int32                           *offsets1;
-       char                            *o1;
-       int32                           type1,j;
-       LINE3D                  *line;
-       double                  dist = 0.0;
-
-       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
-
-
-       //now have to do a scan of each object
-
-       for (j=0; j< geom->nobjs; j++)          //for each object in geom1
-       {
-               o1 = (char *) geom +offsets1[j] ;
-               type1=  geom->objType[j];
-               if (type1 == LINETYPE)  //LINESTRING
-               {
-                       line = (LINE3D *) o1;
-                       dist += length3d_ellipse_linestring(line,sphere);
-               }
-       }
-       PG_RETURN_FLOAT8(dist);
-}
-
-/*
- * This algorithm was taken from the geo_distance function of the 
- * earthdistance package contributed by Bruno Wolff III.
- * It was altered to accept GEOMETRY objects and return results in
- * meters.
- */
-PG_FUNCTION_INFO_V1(distance_sphere);
-Datum distance_sphere(PG_FUNCTION_ARGS)
-{
-               const double EARTH_RADIUS = 6370986.884258304;
-               const double TWO_PI = 2.0 * M_PI;
-               GEOMETRY                *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-               POINT3D                 *pt1, *pt2;
-               int32                   *offsets1;
-               int32                   *offsets2;
-               char                    *o;
-
-               double                  long1, lat1, long2, lat2;
-               double                  longdiff;
-               double                  sino;
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR, "optimistic_overlap:Operation on two GEOMETRIES with differenc SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if (geom1->type != POINTTYPE)
-       {
-               elog(ERROR, "optimistic_overlap: first arg isnt a point\n");
-               PG_RETURN_NULL();
-       }
-
-       if (geom2->type != POINTTYPE)
-       {
-               elog(ERROR, "optimistic_overlap: second arg isnt a point\n");
-               PG_RETURN_NULL();
-       }
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs );
-       offsets2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+ sizeof(int32) * geom2->nobjs );
-       o = (char *) geom1 + offsets1[0];
-       pt1 = (POINT3D *) o;
-
-       o = (char *) geom2 + offsets2[0];
-       pt2 = (POINT3D *) o;
-
-       /*
-        * Start geo_distance code.  Longitude is degrees west of
-        * Greenwich, and thus is negative from what normal things
-        * will supply the function.
-        */
-        long1 = -1 * (pt1->x / 360.0) * TWO_PI;
-        lat1 = (pt1->y / 360.0) * TWO_PI;
-
-       long2 = -1 * (pt2->x / 360.0) * TWO_PI;
-       lat2 = (pt2->y / 360.0) * TWO_PI;
-
-        /* compute difference in longitudes - want < 180 degrees */
-        longdiff = fabs(long1 - long2);
-        if (longdiff > M_PI)
-                longdiff = TWO_PI - longdiff;
-
-        sino = sqrt(sin(fabs(lat1 - lat2) / 2.) * sin(fabs(lat1 - lat2) / 2.) +
-                cos(lat1) * cos(lat2) * sin(longdiff / 2.) * sin(longdiff / 2.));
-        if (sino > 1.)
-                sino = 1.;
-        PG_RETURN_FLOAT8(2. * EARTH_RADIUS * asin(sino));
-
-/*     PG_RETURN_FLOAT8(distance_sphere_method(pt1->y*M_PI/180.0 ,
-                                               pt1->x*M_PI/180.0 ,
-                                               pt2->y*M_PI/180.0 ,
-                                               pt2->x*M_PI/180.0 ,
-                                               sphere));
-*/
-
-}
-
-
-//distance (geometry,geometry, sphere)
-// -geometrys MUST be points
-PG_FUNCTION_INFO_V1(distance_ellipsoid);
-Datum distance_ellipsoid(PG_FUNCTION_ARGS)
-{
-               SPHEROID                *sphere = (SPHEROID *) PG_GETARG_POINTER(2);
-               GEOMETRY                      *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               GEOMETRY                      *geom2 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               POINT3D *pt1,*pt2;
-               int32                           *offsets1;
-               int32                           *offsets2;
-               char                            *o;
-
-
-       if (geom1->SRID != geom2->SRID)
-       {
-               elog(ERROR,"optimistic_overlap:Operation on two GEOMETRIES with different SRIDs\n");
-               PG_RETURN_NULL();
-       }
-
-       if (geom1->type != POINTTYPE)
-       {
-               elog(ERROR,"optimistic_overlap: first arg isnt a point\n");
-               PG_RETURN_NULL();
-       }
-       if (geom2->type != POINTTYPE)
-       {
-               elog(ERROR,"optimistic_overlap: second arg isnt a point\n");
-               PG_RETURN_NULL();
-       }
-
-       offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
-       offsets2 = (int32 *) ( ((char *) &(geom2->objType[0] ))+ sizeof(int32) * geom2->nobjs ) ;
-       o = (char *) geom1 +offsets1[0] ;
-       pt1 = (POINT3D *) o;
-
-       o = (char *) geom2 +offsets2[0] ;
-       pt2 = (POINT3D *) o;
-
-       PG_RETURN_FLOAT8(distance_ellipse(pt1->y*M_PI/180.0 ,pt1->x*M_PI/180.0 ,
-                                                         pt2->y*M_PI/180.0 ,pt2->x*M_PI/180.0 , sphere) );
-
-//double       distance_ellipse(double lat1, double long1,
-//                                     double lat2, double long2,
-//                                     SPHEROID *sphere)
-
-
-}
-
-
-/*
- *  For some lat/long points, the above method doesnt calculate the distance very well.
- *  Typically this is for two lat/long points that are very very close together (<10cm).
- *  This gets worse closer to the equator.
- *
- *   This method works very well for very close together points, not so well if they're
- *   far away (>1km).
- *
- *  METHOD:
- *    We create two circles (with Radius R and Radius S) and use these to calculate the distance.
- *
- *    The first (R) is basically a (north-south) line of longitude.
- *    Its radius is approximated by looking at the ellipse. Near the equator R = 'a' (earth's major axis)
- *    near the pole R = 'b' (earth's minor axis).
- *
- *    The second (S) is basically a (east-west) line of lattitude.
- *    Its radius runs from 'a' (major axis) at the equator, and near 0 at the poles.
- *
- *
- *                North pole
- *                *
- *               *
- *              *\--S--
- *             *  R   +
- *            *    \  +
- *           *     A\ +
- *          * ------ \         Equator/centre of earth
- *           *
- *            *
- *             *
- *              *
- *               *
- *                *
- *                South pole
- *  (side view of earth)
- *
- *   Angle A is lat1
- *   R is the distance from the centre of the earth to the lat1/long1 point on the surface
- *   of the Earth.
- *   S is the circle-of-lattitude.  Its calculated from the right triangle defined by
- *      the angle (90-A), and the hypothenus R.
- *
- *
- *
- *   Once R and S have been calculated, the actual distance between the two points can be
- *   calculated.
- *
- *   We dissolve the vector from lat1,long1 to lat2,long2 into its X and Y components (called DeltaX,DeltaY).
- *   The actual distance that these angle-based measurements represent is taken from the two
- *   circles we just calculated; R (for deltaY) and S (for deltaX).
- *
- *    (if deltaX is 1 degrees, then that distance represents 1/360 of a circle of radius S.)
- *
- *
- *  Parts taken from PROJ4 - geodetic_to_geocentric() (for calculating Rn)
- *
- *  remember that lat1/long1/lat2/long2 are comming in a *RADIANS* not degrees.
- *
- * By Patricia Tozer and Dave Blasby
- *
- *  This is also called the "curvature method".
- */
-
-double distance_sphere_method(double lat1, double long1,double lat2,double long2, SPHEROID *sphere)
-{
-                       double R,S,X,Y,deltaX,deltaY;
-
-                       double  distance        = 0.0;
-                       double  sin_lat         = sin(lat1);
-                       double  sin2_lat        = sin_lat * sin_lat;
-
-                       double  Geocent_a       = sphere->a;
-                       double  Geocent_e2      = sphere->e_sq;
-
-                       R       = Geocent_a / (sqrt(1.0e0 - Geocent_e2 * sin2_lat));
-                       S       = R * sin(M_PI/2.0-lat1) ; // 90 - lat1, but in radians
-
-                       deltaX = long2 - long1;  //in rads
-                       deltaY = lat2 - lat1;    // in rads
-
-                       X = deltaX/(2.0*M_PI) * 2 * M_PI * S;  // think: a % of 2*pi*S
-                       Y = deltaY /(2.0*M_PI) * 2 * M_PI * R;
-
-                       distance = sqrt((X * X + Y * Y));
-
-                       return distance;
-}
diff --git a/hwgeom/postgis_svg.c b/hwgeom/postgis_svg.c
deleted file mode 100644 (file)
index cb14bfc..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of hte GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- *
- * SVG output routines.
- * Originally written by: Klaus Förster <klaus@svg.cc>
- * Patches from: Olivier Courtin <pnine@free.fr>
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.4  2004/09/13 14:26:27  strk
- * indentation fix
- *
- * Revision 1.3  2004/09/10 16:16:31  pramsey
- * Added Log tag to header.
- *
- *
- **********************************************************************/
-
-
-#include "postgres.h"
-#include "postgis.h"
-
-Datum assvg_geometry(PG_FUNCTION_ARGS);
-char *geometry_to_svg(GEOMETRY  *geometry, int svgrel, int precision);
-void print_svg_coords(char *result, POINT3D *pt, int precision);
-void print_svg_circle(char *result, POINT3D *pt, int precision);
-void print_svg_path_abs(char *result, POINT3D *pt, int npoints, int precision);
-void print_svg_path_rel(char *result, POINT3D *pt, int npoints, int precision);
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-/**
- * SVG features
- */
-PG_FUNCTION_INFO_V1(assvg_geometry);
-Datum assvg_geometry(PG_FUNCTION_ARGS)
-{
-       GEOMETRY *geom1;
-       char *wkt;
-       char *result;
-       int len;
-       int32 svgrel=0;
-       int32 precision=15;
-
-       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-
-       geom1 = (GEOMETRY *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       // check for relative path notation
-       if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
-                       svgrel = PG_GETARG_INT32(1);
-
-       if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
-               precision = PG_GETARG_INT32(2);
-               
-       wkt = geometry_to_svg(geom1, svgrel, precision);
-
-       len = strlen(wkt) + 5;
-
-       result= palloc(len);
-       *((int *) result) = len;
-
-       memcpy(result +4, wkt, len-4);
-
-       pfree(wkt);
-
-       PG_RETURN_CSTRING(result);
-}
-
-
-//takes a GEOMETRY and returns a SVG representation
-char *geometry_to_svg(GEOMETRY  *geometry, int svgrel, int precision)
-{
-       char            *result;
-       int             t,u;
-       int32           *offsets;
-       char            *obj;
-       POINT3D *pts;
-       POLYGON3D       *polygon;
-       LINE3D  *line;
-       POINT3D *point;
-
-       int             pt_off,size;
-       bool            first_sub_obj = TRUE;
-       int             npts;
-
-       //elog(NOTICE, "precision is %d", precision);
-       size = 30;      //just enough to put in object type
-
-       // TODO BBox, from where is it called?...
-       if (geometry->type == BBOXONLYTYPE)
-       {
-               if (svgrel == 1)
-               {
-                       // 5 double digits+ "Mhvhz"+ spaces +null
-                       size = MAX_DIGS_DOUBLE*5+5+6+1;
-                       result = (char *) palloc(size); 
-
-                       sprintf(result, "M %.*g %.*g h%.*g v%.*g h%.*g z",
-                               precision, 
-                               geometry->bvol.LLB.x,
-                               precision, 
-                               geometry->bvol.URT.y*-1,
-                               precision, 
-                               (geometry->bvol.URT.x 
-                                - geometry->bvol.LLB.x),
-                               precision, 
-                               (geometry->bvol.URT.y 
-                                - geometry->bvol.LLB.y),
-                               precision, 
-                               (geometry->bvol.URT.x 
-                                - geometry->bvol.LLB.x)*-1);
-               }
-               else
-               {
-                       size = MAX_DIGS_DOUBLE*4+3+1;
-                       result = (char *) palloc(size); 
-                       // 4 double digits + 3 spaces +null
-
-                       sprintf(result, "%.*g %.*g %.*g %.*g",
-                               precision,
-                               geometry->bvol.LLB.x,
-                               precision,
-                               geometry->bvol.URT.y*-1,
-                               precision,
-                               (geometry->bvol.URT.x - 
-geometry->bvol.LLB.x),
-                               precision, 
-                               (geometry->bvol.URT.y - 
-geometry->bvol.LLB.y)
-                               );
-               }
-               return result;
-       }
-
-       if (geometry->type == COLLECTIONTYPE)
-       {
-               result = (char *)palloc(64); 
-               sprintf(result, "GEOMETRYCOLLECTION not yet supported");
-               return result;
-       }
-
-       //where are the objects?
-       offsets = (int32 *) ( ((char *) &(geometry->objType[0] ))
-                       + sizeof(int32) * geometry->nobjs ) ;
-
-       result = palloc(size);
-       result[0] = '\0';
-       for(t=0;t<geometry->nobjs; t++)  //for each object
-       {
-               obj = (char *) geometry +offsets[t] ;
-
-               if (geometry->objType[t] == 1)   //POINT
-               {
-                       point = (POINT3D *) obj;
-                       size +=MAX_DIGS_DOUBLE*3 + 2 +10  ;
-                       //make memory bigger
-                       result = repalloc(result, size );
-
-                       if (!(first_sub_obj))
-                       {       
-                               // next circle ...
-                               strcat(result,",");
-                       }
-                       else
-                       {
-                               first_sub_obj = FALSE;
-                       }
-                       if (svgrel == 1)
-                       {  
-                               //render circle
-                               print_svg_coords(result, point, precision);
-                       }
-                       else
-                       {  
-                               //render circle
-                               print_svg_circle(result, point, precision);
-                       }
-
-               }
-               if (geometry->objType[t] == 2)  //LINESTRING
-               {
-                       line = (LINE3D *) obj;
-
-                       size +=(MAX_DIGS_DOUBLE*3+5)*line->npoints +12+3;
-                       result = repalloc(result, size );
-
-                       // start path with moveto
-                       strcat(result, "M ");
-
-                       if (svgrel == 1)
-                               print_svg_path_rel(
-                                               result,
-                                               &line->points[0],
-                                               line->npoints, 
-                                               precision
-                                               );
-                       else
-                               print_svg_path_abs(
-                                               result,
-                                               &line->points[0],
-                                               line->npoints,
-                                               precision
-                                               );
-
-                       strcat(result," ");
-               }
-               if (geometry->objType[t] == 3)  //POLYGON
-               {
-                       polygon = (POLYGON3D *) obj;
-                       pt_off = 0;     //where is the first point in this ring?
-
-                       //where are the points
-                       pts = (POINT3D *)
-                               ((char *)&(polygon->npoints[polygon->nrings]));
-                       pts = (POINT3D *) MAXALIGN(pts);
-
-                       npts = 0;
-                       for (u=0; u< polygon->nrings ; u++)
-                               npts += polygon->npoints[u];
-
-                       size += (MAX_DIGS_DOUBLE*3+3) 
-                               * npts + 5* polygon->nrings;
-                       result = repalloc(result, size );
-
-                       for (u=0; u< polygon->nrings ; u++)  //for each ring
-                       {
-                               strcat(result,"M ");    //begin ring
-                               if (svgrel == 1)
-                                       print_svg_path_rel(result, 
-                                                       &pts[pt_off] ,
-                                                       polygon->npoints[u],
-                                                       precision);
-                               else
-                                       print_svg_path_abs(result,
-                                                       &pts[pt_off],
-                                                       polygon->npoints[u],
-                                                       precision);
-                               
-                               //where is first point of next ring?
-                               pt_off = pt_off + polygon->npoints[u]; 
-                               strcat(result," ");     //end ring
-                       }
-               }
-       }
-       return(result);
-}
-
-
-void print_svg_coords(char *result, POINT3D *pt, int precision)
-{
-       char    temp[MAX_DIGS_DOUBLE*3 +12];
-
-       if ( (pt == NULL) || (result == NULL) )
-               return;
-
-       sprintf(temp, "x=\"%.*g\" y=\"%.*g\"", 
-                       precision, pt->x, 
-                       precision, pt->y*-1);
-       strcat(result,temp);
-}
-
-
-void print_svg_circle(char *result, POINT3D *pt, int precision)
-{
-       char    temp[MAX_DIGS_DOUBLE*3 +12];
-
-       if ( (pt == NULL) || (result == NULL) )
-               return;
-
-       sprintf(temp, "cx=\"%.*g\" cy=\"%.*g\"", 
-                       precision, pt->x, 
-                       precision, pt->y*-1);
-       strcat(result,temp);
-}
-
-
-void print_svg_path_abs(char *result, POINT3D *pt ,int npoints, int
-precision){
-       int     u;
-
-       result += strlen(result);
-       for (u=0;u<npoints;u++)
-       {
-               if (u != 0)
-               {
-                       result[0] = ' ';
-                       result++;
-               }
-               result+= sprintf(result,"%.*g %.*g", 
-                               precision, pt[u].x, 
-                               precision, pt[u].y*-1);
-       }
-}
-
-
-void print_svg_path_rel(char *result, POINT3D *pt ,int npoints, int
-precision){
-       int     u;
-
-       result += strlen(result);
-       for (u=0;u<npoints;u++)
-       {
-               if (u == 0)
-               {
-                       result+= sprintf(result,"%.*g %.*g l", 
-                                       precision, pt[u].x, 
-                                       precision, pt[u].y*-1);
-               }
-               else
-               {
-                       result+= sprintf(result," %.*g %.*g", 
-                                       precision, (pt[u].x-pt[u-1].x), 
-                                       precision, (pt[u].y-pt[u-1].y)*-1);
-               }
-       }
-}
-
-
-/**********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.4  2004/09/13 14:26:27  strk
- * indentation fix
- *
- * Revision 1.3  2004/09/10 16:16:31  pramsey
- * Added Log tag to header.
- *
- * Revision 1.2  2004/09/10 13:25:36  strk
- * fixed a memory fault
- *
- * Revision 1.1  2004/09/10 12:49:29  strk
- * Included SVG output function, modified to have precision expressed
- * in terms of significant digits.
- *
- **********************************************************************/
-
diff --git a/hwgeom/postgis_transform.c b/hwgeom/postgis_transform.c
deleted file mode 100644 (file)
index 98d96aa..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- * $Log$
- * Revision 1.1  2004/09/20 07:50:06  strk
- * prepared to contain old internal representation code
- *
- * Revision 1.20  2004/08/10 21:09:59  strk
- * changed proj version extractor to support pre 4.4.8 releases
- *
- * Revision 1.19  2004/07/28 16:10:59  strk
- * Changed all version functions to return text.
- * Renamed postgis_scripts_version() to postgis_scripts_installed()
- * Added postgis_scripts_released().
- * Added postgis_full_version().
- *
- * Revision 1.18  2004/07/23 21:24:33  strk
- * Added postgis_proj_version()
- *
- * Revision 1.17  2004/07/22 16:20:10  strk
- * Added postgis_lib_version() and postgis_geos_version()
- *
- * Revision 1.16  2004/04/28 22:26:02  pramsey
- * Fixed spelling mistake in header text.
- *
- * Revision 1.15  2004/01/14 01:52:53  pramsey
- * Fix solaris alignment problem in transformations.
- *
- * Revision 1.14  2003/09/16 20:27:12  dblasby
- * added ability to delete geometries.
- *
- * Revision 1.13  2003/07/01 18:30:55  pramsey
- * Added CVS revision headers.
- *
- *
- **********************************************************************/
-
-#include "postgres.h"
-
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "access/gist.h"
-#include "access/itup.h"
-#include "access/rtree.h"
-
-
-#include "fmgr.h"
-
-
-#include "postgis.h"
-#include "utils/elog.h"
-
-
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-
-// if USE_PROJECTION undefined, we get a do-nothing transform() function
-#ifdef USE_PROJ
-
-#include "projects.h"
-
-
-PJ *make_project(char *str1);
-void to_rad(POINT3D *pts, int num_points);
-void to_dec(POINT3D *pts, int num_points);
-
-int pj_transform_nodatum( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
-                  double *x, double *y, double *z );
-
-//this is *exactly* the same as PROJ.4's pj_transform(), but it doesnt do the
-// datum shift.
-int pj_transform_nodatum( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
-                  double *x, double *y, double *z )
-
-{
-    long      i;
-    //int       need_datum_shift;
-
-    pj_errno = 0;
-
-    if( point_offset == 0 )
-        point_offset = 1;
-
-    if( !srcdefn->is_latlong )
-    {
-        for( i = 0; i < point_count; i++ )
-        {
-            XY         projected_loc;
-            LP        geodetic_loc;
-
-            projected_loc.u = x[point_offset*i];
-            projected_loc.v = y[point_offset*i];
-
-            geodetic_loc = pj_inv( projected_loc, srcdefn );
-            if( pj_errno != 0 )
-                return pj_errno;
-
-            x[point_offset*i] = geodetic_loc.u;
-            y[point_offset*i] = geodetic_loc.v;
-        }
-    }
-
-    if( !dstdefn->is_latlong )
-    {
-        for( i = 0; i < point_count; i++ )
-        {
-            XY         projected_loc;
-            LP        geodetic_loc;
-
-            geodetic_loc.u = x[point_offset*i];
-            geodetic_loc.v = y[point_offset*i];
-
-            projected_loc = pj_fwd( geodetic_loc, dstdefn );
-            if( pj_errno != 0 )
-                return pj_errno;
-
-            x[point_offset*i] = projected_loc.u;
-            y[point_offset*i] = projected_loc.v;
-        }
-    }
-
-    return 0;
-}
-
-
-
-// convert decimal degress to radians
-void to_rad(POINT3D *pts, int num_points)
-{
-       int t;
-       for(t=0;t<num_points;t++)
-       {
-               pts[t].x *= PI/180.0;
-               pts[t].y *= PI/180.0;
-       }
-}
-
-// convert radians to decimal degress
-void to_dec(POINT3D *pts, int num_points)
-{
-       int t;
-       for(t=0;t<num_points;t++)
-       {
-               pts[t].x *= 180.0/PI;
-               pts[t].y *= 180.0/PI;
-       }
-
-}
-
-       //given a string, make a PJ object
-PJ *make_project(char *str1)
-{
-       int t;
-       char    *params[1024];  //one for each parameter
-       char  *loc;
-       char    *str;
-       PJ *result;
-
-
-       if (str1 == NULL)
-               return NULL;
-
-       if (strlen(str1) ==0)
-               return NULL;
-
-       str = palloc(1+strlen(str1) );
-       strcpy(str,str1);
-
-       //first we split the string into a bunch of smaller strings, based on the " " separator
-
-       params[0] = str; //1st param, we'll null terminate at the " " soon
-
-       loc = str;
-       t =1;
-       while  ((loc != NULL) && (*loc != 0) )
-       {
-               loc = strchr( loc,' ');
-               if (loc != NULL)
-               {
-                       *loc = 0; // null terminate
-                       params[t] = loc +1;
-                       loc++; // next char
-                       t++; //next param
-               }
-       }
-
-       if (!(result= pj_init ( t , params)))
-       {
-               pfree(str);
-               return NULL;
-       }
-       pfree(str);
-       return result;
-}
-
-
-//tranform_geom( GEOMETRY, TEXT (input proj4), TEXT (output proj4), INT (output srid)
-// tmpPts - if there is a nadgrid error (-38), we re-try the transform on a copy of points.  The transformed points
-//          are in an indeterminate state after the -38 error is thrown.
-PG_FUNCTION_INFO_V1(transform_geom);
-Datum transform_geom(PG_FUNCTION_ARGS)
-{
-       GEOMETRY                   *geom ;
-       GEOMETRY                   *result;
-       PJ                         *input_pj,*output_pj;
-
-       char                            *o1;
-       int32                           *offsets1;
-       int                             j,type1,gtype,i,poly_points;
-
-       POLYGON3D                       *poly;
-       LINE3D                  *line;
-       POINT3D                 *pt,*poly_pts;
-
-       char                            *input_proj4, *output_proj4;
-
-       BOX3D                           *bbox;
-       POINT3D                 *tmpPts;
-
-
-
-       text       *input_proj4_text;
-       text       *output_proj4_text;
-       int32      result_srid ;
-
-
-       geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       input_proj4_text  = (PG_GETARG_TEXT_P(1));
-       output_proj4_text = (PG_GETARG_TEXT_P(2));
-       result_srid   = PG_GETARG_INT32(3);
-
-
-       input_proj4 = (char *) palloc(input_proj4_text->vl_len +1-4);
-      memcpy(input_proj4,input_proj4_text->vl_dat, input_proj4_text->vl_len-4);
-       input_proj4[input_proj4_text->vl_len-4] = 0; //null terminate
-
-
-       output_proj4 = (char *) palloc(output_proj4_text->vl_len +1-4);
-      memcpy(output_proj4,output_proj4_text->vl_dat, output_proj4_text->vl_len-4);
-       output_proj4[output_proj4_text->vl_len-4] = 0; //null terminate
-
-       if (geom->SRID == -1)
-       {
-               pfree(input_proj4); pfree(output_proj4);
-               elog(ERROR,"tranform: source SRID = -1");
-               PG_RETURN_NULL();                       // no srid, cannot convert
-       }
-
-       if (result_srid   == -1)
-       {
-               pfree(input_proj4); pfree(output_proj4);
-               elog(ERROR,"tranform: destination SRID = -1");
-               PG_RETURN_NULL();                       // no srid, cannot convert
-       }
-
-       //make input and output projection objects
-       input_pj = make_project(input_proj4);
-       if ( (input_pj == NULL) || pj_errno)
-       {
-               pfree(input_proj4); pfree(output_proj4);
-               elog(ERROR,"tranform: couldnt parse proj4 input string");
-               PG_RETURN_NULL();
-       }
-
-       output_pj = make_project(output_proj4);
-       if ((output_pj == NULL)|| pj_errno)
-       {
-               pfree(input_proj4); pfree(output_proj4);
-               pj_free(input_pj);
-               elog(ERROR,"tranform: couldnt parse proj4 output string");
-
-               PG_RETURN_NULL();
-       }
-       //great, now we have a geometry, and input/output PJ* structs.  Excellent.
-
-       //copy the geometry structure - we're only going to change the points, not the structures
-       result = (GEOMETRY *) palloc (geom->size);
-       memcpy(result,geom, geom->size);
-
-       gtype = result->type;
-
-       // allow transformations of the BOX3D type - the loop below won't be entered since for a BOX3D
-       // type result->nobjs will be -1 so we check for it here
-       if (gtype == BBOXONLYTYPE)
-       {
-               bbox = &(result->bvol);
-               pt = (POINT3D *)bbox;
-
-               if (input_pj->is_latlong)
-                       to_rad(pt,2);
-
-               tmpPts = palloc(sizeof(POINT3D)*2);
-               memcpy(tmpPts, pt, sizeof(POINT3D)*2);
-
-               pj_transform(input_pj,output_pj, 2,3, &pt->x,&pt->y, &pt->z);
-
-               if (pj_errno)
-               {
-                       if (pj_errno == -38)  //2nd chance
-                       {
-                               //couldnt do nadshift - do it without the datum
-                               memcpy(pt,tmpPts, sizeof(POINT3D)*2);
-                               pj_transform_nodatum(input_pj,output_pj, 2 ,3, &pt->x,&pt->y, &pt->z);
-                       }
-
-                       if (pj_errno)
-                       {
-                               pfree(input_proj4); pfree(output_proj4);
-                               pj_free(input_pj); pj_free(output_pj);
-                               elog(ERROR,"transform: couldnt project bbox point: %i (%s)",pj_errno,pj_strerrno(pj_errno));
-                               PG_RETURN_NULL();
-                       }
-
-               }
-               pfree(tmpPts);
-               if (output_pj->is_latlong)
-                       to_dec(pt,2);
-
-       }else{
-
-               //handle each sub-geometry
-               offsets1 = (int32 *) ( ((char *) &(result->objType[0] ))+ sizeof(int32) * result->nobjs ) ;
-               for (j=0; j< result->nobjs; j++)                //for each object in geom1
-               {
-                       o1 = (char *) result +offsets1[j] ;
-                       type1=  result->objType[j];
-
-                       if (type1 == POINTTYPE) //point
-                       {
-                               pt = (POINT3D *) o1;
-                               if (input_pj->is_latlong)
-                                       to_rad(pt,1);
-
-                               tmpPts = palloc(sizeof(POINT3D) );
-                               memcpy(tmpPts,pt, sizeof(POINT3D));
-
-                               pj_transform(input_pj,output_pj, 1,3, &pt->x,&pt->y, &pt->z);
-                               if (pj_errno)
-                               {
-                                       if (pj_errno == -38)  //2nd chance
-                                       {
-                                               //couldnt do nadshift - do it without the datum
-                                               memcpy(pt,tmpPts, sizeof(POINT3D));
-                                               pj_transform_nodatum(input_pj,output_pj, 1,3, &pt->x,&pt->y, &pt->z);
-                                       }
-
-                                       if (pj_errno)
-                                       {
-                                               pfree(input_proj4); pfree(output_proj4);
-                                               pj_free(input_pj); pj_free(output_pj);
-                                               elog(ERROR,"transform: couldnt project point: %i (%s)",pj_errno,pj_strerrno(pj_errno));
-                                               PG_RETURN_NULL();
-                                       }
-
-                               }
-                               pfree(tmpPts);
-                               if (output_pj->is_latlong)
-                                       to_dec(pt,1);
-                       }
-                       if (type1 == LINETYPE)  //line
-                       {
-                               line = (LINE3D *) o1;
-                               if (input_pj->is_latlong)
-                                       to_rad(&line->points[0],line->npoints);
-
-                               tmpPts = palloc(sizeof(POINT3D)*line->npoints );
-                               memcpy(tmpPts,&line->points[0], sizeof(POINT3D)*line->npoints);
-
-                               pj_transform(input_pj,output_pj, line->npoints ,3,
-                                                       &line->points[0].x,&line->points[0].y, &line->points[0].z);
-                               if (pj_errno)
-                               {
-                                       if (pj_errno == -38)  //2nd chance
-                                       {
-                                               //couldnt do nadshift - do it without the datum
-                                               memcpy(&line->points[0],tmpPts, sizeof(POINT3D)*line->npoints);
-                                               pj_transform_nodatum(input_pj,output_pj, line->npoints ,3,
-                                                       &line->points[0].x,&line->points[0].y, &line->points[0].z);
-                                       }
-
-                                       if (pj_errno)
-                                       {
-
-                                               pfree(input_proj4); pfree(output_proj4);
-                                               pj_free(input_pj); pj_free(output_pj);
-                                               elog(ERROR,"transform: couldnt project line");
-                                               PG_RETURN_NULL();
-                                       }
-                               }
-                               pfree(tmpPts);
-                               if (output_pj->is_latlong)
-                                       to_dec(&line->points[0],line->npoints);
-                       }
-                       if (type1 == POLYGONTYPE)       //POLYGON
-                       {
-                               poly = (POLYGON3D *) o1;
-                               poly_points = 0;
-
-                               for (i=0; i<poly->nrings;i++)
-                               {
-                                       poly_points  += poly->npoints[i];
-                               }
-                               poly_pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] )  );
-                               poly_pts = (POINT3D *) MAXALIGN(poly_pts);
-
-                               if (input_pj->is_latlong)
-                                       to_rad(poly_pts , poly_points);
-
-                               tmpPts = palloc(sizeof(POINT3D)* poly_points );
-                               memcpy(tmpPts,&poly_pts[0].x, sizeof(POINT3D)* poly_points);
-
-
-
-                               pj_transform(input_pj,output_pj, poly_points,3,
-                                                       &poly_pts[0].x,&poly_pts[0].y, &poly_pts[0].z);
-                               if (pj_errno)
-                               {
-                                       if (pj_errno == -38)  //2nd chance
-                                       {
-                                               //couldnt do nadshift - do it without the datum
-                                               memcpy(&poly_pts[0].x,tmpPts, sizeof(POINT3D)*poly_points);
-                                               pj_transform_nodatum(input_pj,output_pj, poly_points,3,
-                                                       &poly_pts[0].x,&poly_pts[0].y, &poly_pts[0].z);
-                                       }
-
-                                       if (pj_errno)
-                                       {
-
-                                               pfree(input_proj4); pfree(output_proj4);
-                                               pj_free(input_pj); pj_free(output_pj);
-                                               elog(ERROR,"transform: couldnt project polygon");
-                                               PG_RETURN_NULL();
-                                       }
-                               }
-                               pfree(tmpPts);
-                               if (output_pj->is_latlong)
-                                       to_dec(poly_pts , poly_points);
-                       }
-               }
-
-       }
-
-       // clean up
-       pj_free(input_pj);
-       pj_free(output_pj);
-       pfree(input_proj4); pfree(output_proj4);
-
-       // Generate the bounding box if necessary
-       if (gtype != BBOXONLYTYPE)
-       {
-               bbox = bbox_of_geometry(result);
-               memcpy(&result->bvol,bbox, sizeof(BOX3D) ); //make bounding box
-       }
-
-       result->SRID = result_srid;
-
-       PG_RETURN_POINTER(result); // new geometry
-}
-
-PG_FUNCTION_INFO_V1(postgis_proj_version);
-Datum postgis_proj_version(PG_FUNCTION_ARGS)
-{
-       //const char *ver = pj_get_release();
-       const char *ver = pj_release;
-       text *result;
-       result = (text *) palloc(VARHDRSZ  + strlen(ver));
-       VARATT_SIZEP(result) = VARHDRSZ + strlen(ver) ;
-       memcpy(VARDATA(result), ver, strlen(ver));
-       PG_RETURN_POINTER(result);
-}
-
-
-#else // ! defined USE_PROJ
-
-       // return the original geometry
-PG_FUNCTION_INFO_V1(transform_geom);
-Datum transform_geom(PG_FUNCTION_ARGS)
-{
-
-       elog(ERROR,"PostGIS transform() called, but support not compiled in.  Modify your makefile to add proj support, remake and re-install");
-
-       //GEOMETRY                 *geom1 = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       //GEOMETRY                 *result;
-
-       //result = (GEOMETRY *) palloc (geom1->size);
-       //memcpy(result,geom1, geom1->size);
-       ///elog(NOTICE,"PostGIS transform
-       //PG_RETURN_POINTER(result);
-       PG_RETURN_NULL();
-}
-
-PG_FUNCTION_INFO_V1(postgis_proj_version);
-Datum postgis_proj_version(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_NULL();
-}
-#endif