postGIS - geometric types for postgres
This software is copyrighted (2001).
-
+
This is free software; you can redistribute it and/or modify
it under the GNU General Public Licence. See the file "COPYING".
- More Info? See the documentation, join the mailing list
+ More Info? See the documentation, join the mailing list
(postgis@yahoogroups.com), or see the web page
(http://postgis.refractions.net).
//Norman Vine found this problem for compiling under cygwin
-// it defines BYTE_ORDER and LITTLE_ENDIAN
+// it defines BYTE_ORDER and LITTLE_ENDIAN
#ifdef __CYGWIN__
#include <sys/param.h> // FOR ENDIAN DEFINES
// 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
+//
+// NOTE: doesnt actually parse the points, so if the
// str contains an invalid geometry, this could give
// back the wrong answer.
//
//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)
+ while (keep_going)
{
str=strpbrk(str,",)"); // look for a "," or ")"
keep_going = (str != NULL);
else //str[0] = ","
{
points_found++;
- str++; //move 1 char forward
+ str++; //move 1 char forward
}
}
}
}
//Actually parse the points in a list
-// "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" =>
+// "(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)
//
//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)
+ 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 !=3)
{
if (num_entities !=2 )
{
}
else
{
- points[numb_found].z = 0.0; //2d (only found x,y - set z =0.0)
+ points[numb_found].z = 0.0; //2d (only found x,y - set z =0.0)
}
- }
+ }
else
{
*is3d = TRUE; //found 3 entites (x,y,z)
str++;
keep_going = ( (str != NULL) && (str[0] != ')' ) && (numb_found < max_points) );
}
- return TRUE;
+ return TRUE;
}
//Actually parse the points in a list
-// "(1 2 3, 4 5 6),(7 8, 9 10, 11 12 13)" =>
+// "(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)
//
//
// returns true if everything parses okay, otherwise false
//
-// THIS IS EXACTLY the same as parse_points_in_list(), but returns FALSE if
+// 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) )
//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)
+ 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)
{
str++;
keep_going = ( (str != NULL) && (str[0] != ')' ) && (numb_found < max_points) );
}
- return (numb_found == max_points);
+ return (numb_found == max_points);
}
// for every ")", depth (nesting) decreases by 1
// if find a "(" at depth 1, then there is a sub list
//
-// example:
+// example:
// "(((..),(..)),((..)))"
//depth 12333223332112333210
// + + increase here
{
if (current_depth==2)
{
- npoints[current_list] ++;
+ npoints[current_list] ++;
}
}
str++;
//printf( "box3d_in gets '%s'\n",str);
- if (strstr(str,"BOX3D") != str )
+ if (strstr(str,"BOX3D") != str )
{
elog(ERROR,"BOX3D parser - doesnt start with BOX3D");
pfree(bbox);
- return NULL;
+ return NULL;
}
if ((npoints = numb_points_in_list(str)) != 2)
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)
}
if ( bbox->LLB.y > bbox->URT.y)
{
- swap ( &bbox->LLB.y , &bbox->URT.y );
+ swap ( &bbox->LLB.y , &bbox->URT.y );
}
if ( bbox->LLB.z > bbox->URT.z)
{
}
/***************************************************************
- * these functions return the number of sub-objects inside a
+ * 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
// 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),
+// 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) ) )'
//
int sub_size = 0;
//skip past the "geometrycollection" at begining of string
- str += 18;
+ str += 18;
if (strstr(str, "GEOMETRYCOLLECTION") != NULL)
return -1; // collection inside collection; bad boy!
//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)
if (((loc = strstr(str,"MULTIPOLYGON")) != NULL) && (loc < parenth) )
return objects_inside_multipolygon(str);
- //base types
+ //base types
if (((loc = strstr(str,"POINT")) != NULL) && (loc < parenth) )
return objects_inside_point(str);
if (((loc = strstr(str,"LINESTRING")) != NULL) && (loc < parenth) )
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);
}
-
+
// -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
}
if (add_point)
- {
+ {
memcpy( &(( (LINE3D*) objs[*offset]) ->points[1]) , &(( (LINE3D*) objs[*offset]) ->points[0]) , sizeof(POINT3D) );
}
if (num_lines ==0)
return TRUE; //can be nothing
-
+
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
return FALSE;
}
}
-
+
//now we can allocate the structure
polygon->nrings = num_rings;
- pts = (POINT3D *) &(polygon->npoints[num_rings]); //pts[] is just past the end of npoints[]
+ pts = (POINT3D *) &(polygon->npoints[num_rings]); //pts[] is just past the end of npoints[]
// make sure its double-word aligned
{
//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],
+ result = parse_points_in_list_exact(str,
+ &pts[points_offset],
npoints[t], is3d);
//printf(" +done parsing points\n");
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].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");
return FALSE;
if (num_polys ==0)
- return TRUE; //ask for nothing, get nothing
+ return TRUE; //ask for nothing, get nothing
if (*offset >= nobjs)
return FALSE; //too many objs found
return FALSE; //invalid
-
+
}
//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);
the_box->URT.x = pt->x;
the_box->URT.y = pt->y;
the_box->URT.z = pt->z;
-
+
return the_box;
}
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++)
//for each sub-object
for(i=0; i<geom->nobjs;i++)
{
- obj = (char *) geom +offsets[i] ;
+ obj = (char *) geom +offsets[i] ;
if (geom->objType[i] == POINTTYPE)
result =union_box3d(a_box ,result);
if (a_box != NULL)
pfree (a_box);
- }
+ }
}
return result;
}
-//given wkt and SRID, return a geometry
+//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)
// 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)
str++;
//test to see if it starts with a SRID=
-
+
SRID = -1;
scale = offx = offy = 0;
str++;
}
- if (strstr(str,"BOX3D") != NULL ) // bbox only
+ 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;
elog(ERROR,"couldnt parse objects in GEOMETRY (null string)\n");
PG_RETURN_NULL() ;
}
-
+
//printf("geometry_in got string ''\n");
//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);
}
//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;
+ 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
+ // geometrycollection and (say) multipoint
if ( strstr(str, "GEOMETRYCOLLECTION") != NULL )
geometry->type = COLLECTIONTYPE;
next_loc += sizeof(int32) * 2* nobjs;
next_loc = MAXALIGN(next_loc);
-
+
//where is the offsets array
memcpy( &geometry->bvol, the_bbox, sizeof(BOX3D) );
pfree(the_bbox);
}
-
+
//printf("returning from geometry_in, nobjs = %i\n", nobjs);
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);
pfree(wkt);
PG_RETURN_CSTRING(result);
-
+
}
//Take internal rep of geometry, output string
len = strlen(wkt) + 5;
-
+
result= palloc(len);
*((int *) result) = len;
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;
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] ;
+ obj = (char *) geometry +offsets[t] ;
if (geometry->objType[t] == 1) //POINT
{
result = repalloc(result, size ); //make memory bigger
if (!(first_sub_obj))
{
- strcat(result,",");
+ strcat(result,",");
}
else
{
first_sub_obj = FALSE;
}
print_point(result, point,is3d); //render point
- if (t == (geometry->nobjs-1))
+ if (t == (geometry->nobjs-1))
strcat(result,")"); // need to close object?
}
else
result = repalloc(result, size );
if (!(first_sub_obj))
{
- strcat(result,",");
+ strcat(result,",");
}
else
{
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,",");
+ strcat(result,",");
}
else
{
first_sub_obj = FALSE;
}
-
+
strcat(result,"("); //begin poly
pt_off = 0; //where is the first point in this ring?
pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
-
+
npts = 0;
- for (u=0; u< polygon->nrings ; u++)
+ 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);
{
first_sub_obj = TRUE;
}
-
+
}
if (!(briefmode))
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
BOX3D *result;
-
+
//make a copy of it
result = palloc ( sizeof(BOX3D) );
{
BOX3D *bbox = (BOX3D *) PG_GETARG_POINTER(0);
GEOMETRY *geom ;
-
+
//make a copy of it
geom = palloc ( sizeof(GEOMETRY) );
//*****************************************************************
//WKB does not do any padding or alignment!
-// in general these function take
+// 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)
char *wkb_point(POINT3D *pt,int32 *size, bool flipbytes, char byte_order, bool use3d)
{
char *result ;
- uint32 type ;
+ uint32 type ;
char *c_type = (char *) &type;
if (use3d)
{
- *size = 29;
- type = 32768 + 1;
+ *size = 29;
+ type = 32768 + 1;
}
else
{
- *size = 21;
- type = 1;
+ *size = 21;
+ type = 1;
}
result = palloc (*size);
int32 junk;
const int sub_size_3d = 29;
const int sub_size_2d = 21;
-
+
if (use3d)
{
- *size = 9 + sub_size_3d*numb_points;
- type = 32768 + 4;
+ *size = 9 + sub_size_3d*numb_points;
+ type = 32768 + 4;
}
else
{
- *size = 9 + sub_size_2d*numb_points;
- type = 4;
+ *size = 9 + sub_size_2d*numb_points;
+ type = 4;
}
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)
+ 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);
+ memcpy(&result[9+ t*sub_size_2d],
+ wkb_point(&pt[t],&junk, flipbytes, byte_order,use3d)
+ , sub_size_2d);
}
return result;
char *wkb_line(LINE3D *line,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem)
{
char *result;
- uint32 type ;
-
+ uint32 type ;
+
char *c_type = (char *) &type;
int t;
if (use3d)
{
- *size = 9 + 24*numb_points;
- type = 32768 + 2;
+ *size = 9 + 24*numb_points;
+ type = 32768 + 2;
}
else
{
- *size = 9 + 16*numb_points;
- type = 2;
+ *size = 9 + 16*numb_points;
+ type = 2;
}
else
result = mem;
- result[0] = byte_order;
+ result[0] = byte_order;
result[1] = c_type[0]; //type
result[2] = c_type[1];
result[3] = c_type[2];
char *result,*new_spot;
- uint32 type ;
+ uint32 type ;
char *c_type = (char *) &type;
uint32 nlines = numb_lines;
if (use3d)
{
- type = 32768 + 5;
+ type = 32768 + 5;
}
else
{
- type = 5;
+ type = 5;
}
if (flipbytes)
{
total_points += lines[t]->npoints;
}
-
+
if (use3d)
{
- total_size = 9+ 9*numb_lines + 24*total_points;
+ total_size = 9+ 9*numb_lines + 24*total_points;
}
else
{
- total_size = 9 + 9*numb_lines + 16*total_points;
+ total_size = 9 + 9*numb_lines + 16*total_points;
}
*size = total_size;
- result[0] = byte_order;
+ result[0] = byte_order;
result[1] = c_type[0]; //type
result[2] = c_type[1];
result[3] = c_type[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
char *wkb_polygon(POLYGON3D *poly,int32 *size, bool flipbytes, char byte_order,bool use3d, char *mem)
{
int t, u,total_points =0;
- uint32 type ;
+ uint32 type ;
char *c_type = (char *) &type;
uint32 numRings,npoints;
char *c_numRings = (char *) &numRings;
pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
-
+
numRings = poly->nrings;
else
result = mem;
-
+
if (flipbytes)
{
flip_endian_int32((char *) &type);
flip_endian_int32((char *) &numRings);
}
-
- result[0] = byte_order;
+
+ result[0] = byte_order;
result[1] = c_type[0]; //type
result[2] = c_type[1];
result[3] = c_type[2];
result[7] = c_numRings[2];
result[8] = c_numRings[3];
-
+
if (use3d)
{
offset = 9; //where the actual linearring structure is going
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);
flip_endian_double((char *) &result[offset+4+u*16+8] );
}
}
-
+
point_offset += poly->npoints[t];
offset += 4 + poly->npoints[t]* 16;
}
if (use3d)
{
- type = 32768 + 6;
+ type = 32768 + 6;
}
else
{
- type = 6;
+ type = 6;
}
total_points += polys[t]->npoints[u];
}
}
-
+
if (use3d)
{
- total_size =9 + 9*numb_polys + 24*total_points + 4*total_rings;
+ 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;
+ total_size = 9 + 9*numb_polys + 16*total_points + 4*total_rings;
}
*size = total_size;
result = palloc (total_size);
- result[0] = byte_order;
+ result[0] = byte_order;
result[1] = c_type[0]; //type
result[2] = c_type[1];
result[3] = c_type[2];
}
-//passes work off to the correct function
+//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);
memcpy(result+4, sub_result, size-4);
memcpy(result, &size, 4);
pfree(sub_result);
- return result;
+ return result;
}
}
int *sizes;
int t;
int32 *offsets1;
-
+
int32 type;
int total_size =0;
int offset;
for (t=0; t<=geom->nobjs; t++) //for each part of the collections, do the work in another function
{
- type = geom->objType[t];
+ type = geom->objType[t];
if (type == POINTTYPE)
{
- sub_result[t] = ( wkb_point((POINT3D *) ((char *) geom +offsets1[t] ) ,
+ 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_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_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 (flip_endian)
+ if (flip_endian)
{
flip_endian_int32((char *) &coll_type);
flip_endian_int32((char *) &nobj);
//could use a memcpy, but...
- result[0] = byte_order;
+ result[0] = byte_order;
result[1] = c_type[0]; //type
result[2] = c_type[1];
result[3] = c_type[2];
result[6] = c_nobj[1];
result[7] = c_nobj[2];
result[8] = c_nobj[3];
-
+
offset =9; //start after the geometrycollection header
pfree( sub_result);
pfree( sizes);
- //total size of the wkb
+ //total size of the wkb
*end_size = total_size+9;
//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)
char byte_order;
char *result = NULL;
int t;
-
+
int32 *offsets1;
LINE3D **linelist;
}
}
- // for searching in the geom struct
+ // for searching in the geom struct
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
if (geom->type == POINTTYPE)
{
- result = ( wkb_point((POINT3D *) ((char *) geom +offsets1[0] ) ,
+ 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] ) ,
+ 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] ) ,
+ result = ( wkb_line((LINE3D *) ((char *) geom +offsets1[0] ) ,
wkb_size, flip_endian, byte_order, geom->is3d, NULL));
}
if (geom->type == POLYGONTYPE)
{
- result = ( wkb_polygon((POLYGON3D *) ((char *) geom +offsets1[0] ) ,
+ result = ( wkb_polygon((POLYGON3D *) ((char *) geom +offsets1[0] ) ,
wkb_size, flip_endian, byte_order, geom->is3d, NULL));
}
PG_RETURN_NULL();
}
input = &input[4];
- PG_RETURN_POINTER (
+ PG_RETURN_POINTER (
DatumGetPointer( DirectFunctionCall1(geometry_in,PointerGetDatum(input)))
);
// 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
-//
+// this does calculate the bvol
+//
// sets the SRID and grid info to the given values
//
// do not call this with type = GEOMETRYCOLLECTION
return(NULL); //error
}
- sub_obj_loc = (char *) &result->objType[2];
+ 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
{
POLYGON3D *poly = (POLYGON3D *) sub_obj;
int t,points=0;
-
+
for (t=0;t<poly->nrings;t++)
{
points += poly->npoints[t];
//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
+// 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"
// 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++)
//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] ;
+ 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);
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
POINT3D *inside_poly_pts;
- *size = sizeof(POLYGON3D) + 4 /*align*/
- + 4*(nrings-1)/*npoints struct*/
+ *size = sizeof(POLYGON3D) + 4 /*align*/
+ + 4*(nrings-1)/*npoints struct*/
+ sizeof(POINT3D) *(npoints-1) /*points struct*/ ;
result= (POLYGON3D *) palloc (*size);
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);
return result;
}
-//given one byte, populate result with two byte representing
+//given one byte, populate result with two byte representing
// the hex number
// ie deparse_hex( 255, mystr)
// -> mystr[0] = 'F' and mystr[1] = 'F'
{
int input_high;
int input_low;
-
+
input_high = (str>>4);
input_low = (str & 0x0F);
if (strspn(str,"0123456789ABCDEF") != strlen(str) )
{
elog(ERROR,"WKB_in parser - input contains bad characters. Should only have '0123456789ABCDEF'!");
- PG_RETURN_NULL();
+ 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]) ;
for (t=0; t< (WKB->size -4); t++)
{
- deparse_hex( ((unsigned char *) WKB)[4 + t], &result[t*2]);
+ deparse_hex( ((unsigned char *) WKB)[4 + t], &result[t*2]);
}
- PG_RETURN_CSTRING(result);
+ PG_RETURN_CSTRING(result);
}
+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);
+}