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
# 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
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);
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);
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
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,
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,
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
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
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
------- 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);
}
+char *print_geometry(GEOMETRY *geom)
+{
+ char *text;
+
+ text = (char *) DatumGetPointer(DirectFunctionCall1(geometry_out,PointerGetDatum(geom) ) ) ;
+
+ printf( "%s", text);
+ return text;
+}
}
+//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();
+}
+
+
+
+
+
+
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 (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)
}
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)
}
-//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