]> granicus.if.org Git - postgis/commitdiff
Added OGIS support functions and basic constructors.
authorDavid Blasby <dblasby@gmail.com>
Tue, 26 Jun 2001 18:33:40 +0000 (18:33 +0000)
committerDavid Blasby <dblasby@gmail.com>
Tue, 26 Jun 2001 18:33:40 +0000 (18:33 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@7 b70326c6-7e19-0410-871a-916f4a2858ee

Makefile
postgis.h
postgis.sql.in
postgis_debug.c
postgis_fn.c
postgis_inout.c

index fe0a9e0fb323b52f95b80fcb7c8b1f9484927cbe..ec8a8c99ee2932fde206d45ace725957dc1c0cab 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,8 @@
 subdir = contrib/postgis
 
 # Root of the pgsql source tree 
-top_builddir = ../..
-#top_builddir = /data3/postgresql-7.1.2/src
+#top_builddir = ../..
+top_builddir = /data3/postgresql-7.1.2/src
 
 include $(top_builddir)/src/Makefile.global
 
@@ -36,11 +36,11 @@ all: all-lib $(NAME).sql
 # Shared library stuff
 include $(top_srcdir)/src/Makefile.shlib
 
-$(NAME).sql: $(NAME).sql.in
-       sed -e 's:@MODULE_FILENAME@:$(libdir)/$(shlib):g' < $< > $@
-
 #$(NAME).sql: $(NAME).sql.in
-#      sed -e 's:@MODULE_FILENAME@:/data1/Refractions/Projects/PostGIS/work_dave/postgis/$(shlib):g' < $< > $@
+#      sed -e 's:@MODULE_FILENAME@:$(libdir)/$(shlib):g' < $< > $@
+
+$(NAME).sql: $(NAME).sql.in
+       sed -e 's:@MODULE_FILENAME@:/data1/Refractions/Projects/PostGIS/work_dave/postgis/$(shlib):g' < $< > $@
 
 install: all installdirs install-lib
        $(INSTALL_DATA) $(srcdir)/README.$(NAME)  $(docdir)/contrib
index c54aee45a4568fb50c2ce092f7aa01c08e3fb204..46af4a641d3cb7a427d5a04258bb5cbfe95fd32e 100644 (file)
--- a/postgis.h
+++ b/postgis.h
@@ -189,6 +189,10 @@ typedef struct geomkey {
      int isspace(int c);
 
 
+/* 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);
 
 void print_box(BOX3D *box);
 void print_box_oneline(BOX3D *box);
@@ -241,7 +245,10 @@ 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);
+char  *print_geometry(GEOMETRY *geom);
 
 void  swap_char(char *a, char*b);
 void   flip_endian_double(char *dd);
@@ -304,14 +311,32 @@ Datum numb_sub_objs(PG_FUNCTION_ARGS);
 Datum summary(PG_FUNCTION_ARGS);
 Datum translate(PG_FUNCTION_ARGS);
 
-Datum wkb_XDR(PG_FUNCTION_ARGS);
-Datum wkb_NDR(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 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);
+
 
 
 //for GIST index
index c2b0553a689b395857849514cad293a9acbbf349..2031ee91b659d91622c0f951bfe226e072044926 100644 (file)
@@ -5,12 +5,12 @@ BEGIN TRANSACTION;
 CREATE FUNCTION BOX3D_in(opaque)
    RETURNS BOX3D 
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION BOX3D_out(opaque)
    RETURNS opaque
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE TYPE BOX3D (
        alignment = double,
@@ -31,12 +31,12 @@ CREATE TYPE WKB (
 create function geometry_in(opaque)
        RETURNS GEOMETRY
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 create function geometry_out(opaque)
        RETURNS opaque
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE TYPE GEOMETRY (
        alignment = double,
@@ -50,24 +50,24 @@ CREATE TYPE GEOMETRY (
 CREATE FUNCTION box3d(GEOMETRY)
    RETURNS BOX3D
    AS '@MODULE_FILENAME@','get_bbox_of_geometry'
-            LANGUAGE 'c' WITH (iscachable);
+            LANGUAGE 'c' WITH (iscachable,isstrict);
 
 CREATE FUNCTION geometry(BOX3D)
    RETURNS GEOMETRY
    AS '@MODULE_FILENAME@','get_geometry_of_bbox'
-            LANGUAGE 'c' WITH (iscachable);
+            LANGUAGE 'c' WITH (iscachable,isstrict);
 
 --------- functions for converting to wkb
 
-CREATE FUNCTION wkb_NDR(GEOMETRY)
+CREATE FUNCTION asbinary(GEOMETRY)
    RETURNS WKB
-   AS '@MODULE_FILENAME@','wkb_NDR'
-            LANGUAGE 'c' WITH (iscachable);
+   AS '@MODULE_FILENAME@','asbinary_simple'
+            LANGUAGE 'c' WITH (iscachable,isstrict);
 
-CREATE FUNCTION wkb_XDR(GEOMETRY)
+CREATE FUNCTION asbinary(GEOMETRY,TEXT)
    RETURNS WKB
-   AS '@MODULE_FILENAME@','wkb_XDR'
-            LANGUAGE 'c' WITH (iscachable);
+   AS '@MODULE_FILENAME@','asbinary_specify'
+            LANGUAGE 'c' WITH (iscachable,isstrict);
 
 
 ---- Debug (info) functions
@@ -75,32 +75,98 @@ CREATE FUNCTION wkb_XDR(GEOMETRY)
 CREATE FUNCTION npoints(GEOMETRY)
    RETURNS INT4
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c'  with (isstrict);
 
 CREATE FUNCTION nrings(GEOMETRY)
    RETURNS INT4
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c'  with (isstrict) ;
 
 CREATE FUNCTION mem_size(GEOMETRY)
    RETURNS INT4
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c'  with (isstrict);
 
 CREATE FUNCTION numb_sub_objs(GEOMETRY)
    RETURNS INT4
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c'  with (isstrict);
 
 CREATE FUNCTION summary(GEOMETRY)
    RETURNS text
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c'  with (isstrict);
 
 CREATE FUNCTION translate(GEOMETRY,float8,float8,float8)
    RETURNS GEOMETRY
    AS '@MODULE_FILENAME@'
-            LANGUAGE 'c' ;
+            LANGUAGE 'c' with (isstrict) ;
+
+CREATE FUNCTION dimension(GEOMETRY)
+   RETURNS INT4
+   AS '@MODULE_FILENAME@'
+            LANGUAGE 'c' with (isstrict) ;
+
+CREATE FUNCTION geometrytype(GEOMETRY)
+   RETURNS text
+   AS '@MODULE_FILENAME@'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION envelope(GEOMETRY)
+   RETURNS geometry
+   AS '@MODULE_FILENAME@'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION x(GEOMETRY)
+   RETURNS float4
+   AS '@MODULE_FILENAME@','x_point'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION y(GEOMETRY)
+   RETURNS float4
+   AS '@MODULE_FILENAME@','y_point'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION z(GEOMETRY)
+   RETURNS float4
+   AS '@MODULE_FILENAME@','z_point'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION numpoints(GEOMETRY)
+   RETURNS integer
+   AS '@MODULE_FILENAME@','numpoints_linestring'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION pointn(GEOMETRY,INTEGER)
+   RETURNS GEOMETRY
+   AS '@MODULE_FILENAME@','pointn_linestring'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION exteriorring(GEOMETRY)
+   RETURNS GEOMETRY
+   AS '@MODULE_FILENAME@','exteriorring_polygon'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION numinteriorrings(GEOMETRY)
+   RETURNS INTEGER
+   AS '@MODULE_FILENAME@','numinteriorrings_polygon'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION interiorringn(GEOMETRY,INTEGER)
+   RETURNS GEOMETRY
+   AS '@MODULE_FILENAME@','interiorringn_polygon'
+            LANGUAGE 'c'  with (isstrict);
+
+
+CREATE FUNCTION numgeometries(GEOMETRY)
+   RETURNS INTEGER
+   AS '@MODULE_FILENAME@','numgeometries_collection'
+            LANGUAGE 'c'  with (isstrict);
+
+CREATE FUNCTION geometryn(GEOMETRY,INTEGER)
+   RETURNS GEOMETRY
+   AS '@MODULE_FILENAME@','geometryn_collection'
+            LANGUAGE 'c'  with (isstrict);
 
 
 -------  generic operations
@@ -108,32 +174,32 @@ CREATE FUNCTION translate(GEOMETRY,float8,float8,float8)
 CREATE FUNCTION length3d(GEOMETRY)
    RETURNS FLOAT4
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION length2d(GEOMETRY)
    RETURNS FLOAT4
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION area2d(GEOMETRY)
    RETURNS FLOAT4
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION perimeter3d(GEOMETRY)
    RETURNS FLOAT4
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION perimeter2d(GEOMETRY)
    RETURNS FLOAT4
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION truly_inside(GEOMETRY,GEOMETRY)
    RETURNS bool
    AS '@MODULE_FILENAME@'
-   LANGUAGE 'c';
+   LANGUAGE 'c' with (isstrict);
 
 ------- Aggregate
 
@@ -153,47 +219,47 @@ CREATE AGGREGATE extent(
 -------  OPERATOR functions
 
 CREATE FUNCTION geometry_overleft(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@' LANGUAGE 'c';
+        AS '@MODULE_FILENAME@' LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_overright(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@' LANGUAGE 'c';
+        AS '@MODULE_FILENAME@' LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_left(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_right(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@' LANGUAGE 'c';
+        AS '@MODULE_FILENAME@' LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_contain(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_contained(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_overlap(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_same(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 --------- functions for doing sorting-like things (not very usefull)
 
 CREATE FUNCTION geometry_lt(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_gt(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION geometry_eq(GEOMETRY, GEOMETRY) RETURNS bool
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 --------- functions for forcing geometry to be 2d or 3d
 
 CREATE FUNCTION force_2d(GEOMETRY) RETURNS GEOMETRY
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 CREATE FUNCTION force_3d(GEOMETRY) RETURNS GEOMETRY
-        AS '@MODULE_FILENAME@'  LANGUAGE 'c';
+        AS '@MODULE_FILENAME@'  LANGUAGE 'c' with (isstrict);
 
 
 
index 420b3f10bcd9c0f1ff2a7ece1d2303613cc80cf8..d5afd22760699a98be9bb103b484922382ce8bf9 100644 (file)
@@ -714,3 +714,12 @@ void decode_wkb(char *wkb, int *size)
 }
 
 
+char *print_geometry(GEOMETRY *geom)
+{
+       char    *text;
+
+       text = (char *) DatumGetPointer(DirectFunctionCall1(geometry_out,PointerGetDatum(geom) ) ) ;
+
+       printf( "%s", text);
+       return text;
+}
index 5052bc1c02fe6be7ab9a5d4c270aaccb4fd51cd4..312bd9fc60768f9604bb3c911cffd5fea606d837 100644 (file)
@@ -970,5 +970,460 @@ Datum combine_bbox(PG_FUNCTION_ARGS)
 }
 
 
+//return 2 for 2d geometries or 3 for 3d geometries
+PG_FUNCTION_INFO_V1(dimension);
+Datum dimension(PG_FUNCTION_ARGS)
+{
+               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       if (geom->is3d)
+               PG_RETURN_INT32(3);
+       else
+               PG_RETURN_INT32(2);
+}
+
+//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)
+
+       set_point( &pts[0], geom->bvol.LLB.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
+       set_point( &pts[1], 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[3], geom->bvol.LLB.x , geom->bvol.URT.y , geom->bvol.LLB.z );
+       set_point( &pts[4], 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);
+
+       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_FLOAT4( ((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_FLOAT4( ((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_FLOAT4( ((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;
+
+       
+       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) 
+                                               );
+               }
+
+       }
+       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) 
+                                               );
+               }
+
+       }
+       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;
+
+       
+       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) 
+                                               );                      
+               }
+       }
+       PG_RETURN_NULL();
+}
+
+
+//        numgeometries(GEOMETRY) -- if GEOMETRY is a GEOMETRYCOLLECTION, return
+//the number of geometries in it, otherwise return NULL.
+
+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)
+                       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.
+
+
+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;
+
+
+
+       offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
+
+               if (geom->type != COLLECTIONTYPE)
+                               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) 
+                                               );
+               }
+               if (type == LINETYPE)
+               {
+                               PG_RETURN_POINTER(
+                               make_oneobj_geometry(   size_subobject (o, LINETYPE),
+                                                        o,
+                                                          LINETYPE,  geom->is3d) 
+                                               );
+               }
+               if (type == POLYGONTYPE)
+               {
+                               PG_RETURN_POINTER(
+                               make_oneobj_geometry(   size_subobject (o, POLYGONTYPE),
+                                                        o,
+                                                          POLYGONTYPE,  geom->is3d) 
+                                               );
+               }
+
+               PG_RETURN_NULL();       
+}
+
+
+
+
+
+
 
 
index ac814ff715cde661f2e38ffb665b8d0e3e570a58..f9df0bc3d8bd5ab412227079ea0309024f29a5b4 100644 (file)
@@ -1358,6 +1358,7 @@ BOX3D     *bbox_of_geometry(GEOMETRY *geom)
 
                if (geom->objType[i] == POINTTYPE)
                {
+//printf("box of a point\n");
                        a_box = bbox_of_point(  (POINT3D *) obj);
                        result= union_box3d(a_box  ,result);
 
@@ -1366,6 +1367,7 @@ BOX3D     *bbox_of_geometry(GEOMETRY *geom)
                }
                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)
@@ -1373,6 +1375,7 @@ BOX3D     *bbox_of_geometry(GEOMETRY *geom)
                }
                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)
@@ -2608,39 +2611,304 @@ char   *to_wkb_sub(GEOMETRY *geom, bool flip_endian, int32 *wkb_size)
 }
 
 
-//convert binary geometry into OGIS well know binary format with XDR (big endian) formating
+//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 32768 to the type.  Points are then 24bytes (X,Y,Z)
 // instead of 16 bytes (X,Y)
-
-PG_FUNCTION_INFO_V1(wkb_XDR);
-Datum wkb_XDR(PG_FUNCTION_ARGS)
+//
+//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));
 
-       if (BYTE_ORDER == BIG_ENDIAN)
-               PG_RETURN_POINTER(to_wkb(geom, FALSE));
-       else
-               PG_RETURN_POINTER(to_wkb(geom, TRUE));
+       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 32768 to the type.  Points are then 24bytes (X,Y,Z)
 // instead of 16 bytes (X,Y)
-
-PG_FUNCTION_INFO_V1(wkb_NDR);
-Datum wkb_NDR(PG_FUNCTION_ARGS)
+//
+//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));
+               GEOMETRY                      *geom = (GEOMETRY *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+                text                           *type = PG_GETARG_TEXT_P(1);
 
-       if (BYTE_ORDER == LITTLE_ENDIAN)
-               PG_RETURN_POINTER(to_wkb(geom, FALSE));
+       if  ( ( strcmp(VARDATA(type) ,"xdr") == 0 ) || (strcmp(VARDATA(type) ,"XDR") == 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
-               PG_RETURN_POINTER(to_wkb(geom, TRUE));
+       {
+printf("requested NDR\n");
+               if (BYTE_ORDER == LITTLE_ENDIAN)
+                       PG_RETURN_POINTER(to_wkb(geom, FALSE));
+               else
+                       PG_RETURN_POINTER(to_wkb(geom, TRUE));
+       }
+}
+
+
+
+
+
+//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 
+//
+// do not call this with type = GEOMETRYCOLLECTION
+
+GEOMETRY       *make_oneobj_geometry(int sub_obj_size, char *sub_obj, int type, bool is3d)
+{
+       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->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)
+       {
+               return(sizeof(LINE3D) +  sizeof(POINT3D) * ( ((LINE3D *)sub_obj)->npoints ));
+       }
+       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
+
+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;
+       BOX3D           *bbox;
+
+       //all the offsets could cause re-alignment problems, so need to deal with each on
+       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;
+
 
+       //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;
+
+
+       //simple conversion
+       if  (geom->type == POINTTYPE)
+       {
+               if (type == POINTTYPE)
+                       result->type  = MULTIPOINTTYPE;
+               else
+                       result->type  = COLLECTIONTYPE;
+       }
+       if  (geom->type == LINETYPE)
+       {
+               if (type == LINETYPE)
+                       result->type  = MULTILINETYPE;
+               else
+                       result->type  = COLLECTIONTYPE;
+       }
+       if  (geom->type == POLYGONTYPE)
+       {
+               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("calculating bbox\n");
+
+       bbox = bbox_of_geometry(result);
+       memcpy(&result->bvol,bbox, sizeof(BOX3D) ); //make bounding box
+
+//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;
+}
\ No newline at end of file