2004-03-10 01:15:06 +00:00
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "access/gist.h"
|
|
|
|
#include "access/itup.h"
|
|
|
|
#include "access/rtree.h"
|
|
|
|
|
|
|
|
#include "fmgr.h"
|
|
|
|
#include "utils/elog.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "lwgeom.h"
|
2004-04-07 23:12:31 +00:00
|
|
|
#include "stringBuffer.h"
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//#define DEBUG
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
#include "wktparse.h"
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void elog_ERROR(const char* string);
|
|
|
|
void *palloc_fn(size_t size);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
extern unsigned char parse_hex(char *str);
|
|
|
|
extern void deparse_hex(unsigned char str, unsigned char *result);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
extern char *parse_lwgeom_wkt(char *wkt_input);
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void *palloc_fn2(size_t size);
|
|
|
|
void free_fn(void *ptr);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
// 3d or 4d. There is NOT a (x,y,m) point type!!!
|
|
|
|
#define WKB3DOFFSET 0x80000000
|
|
|
|
#define WKB4DOFFSET 0x40000000
|
|
|
|
|
|
|
|
Datum LWGEOMFromWKB(PG_FUNCTION_ARGS);
|
|
|
|
Datum WKBFromLWGEOM(PG_FUNCTION_ARGS);
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
Datum LWGEOM_in(PG_FUNCTION_ARGS);
|
|
|
|
Datum LWGEOM_out(PG_FUNCTION_ARGS);
|
|
|
|
|
2004-04-07 23:12:31 +00:00
|
|
|
Datum LWGEOM_asText(PG_FUNCTION_ARGS);
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS);
|
|
|
|
Datum LWGEOM_getBBOX(PG_FUNCTION_ARGS);
|
|
|
|
|
|
|
|
|
|
|
|
Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
// included here so we can be independent from postgis
|
2004-03-11 00:54:37 +00:00
|
|
|
// WKB structure -- exactly the same as TEXT
|
|
|
|
typedef struct Well_known_bin {
|
2004-04-26 23:05:20 +00:00
|
|
|
int32 size; // total size of this structure
|
2004-03-11 00:54:37 +00:00
|
|
|
unsigned char data[1]; //THIS HOLD VARIABLE LENGTH DATA
|
|
|
|
} WellKnownBinary;
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
// LWGEOM_in(cstring)
|
|
|
|
// format is '[SRID=#;]wkt|wkb'
|
|
|
|
// LWGEOM_in( 'SRID=99;POINT(0 0)')
|
|
|
|
// LWGEOM_in( 'POINT(0 0)') --> assumes SRID=-1
|
|
|
|
// LWGEOM_in( 'SRID=99;0101000000000000000000F03F000000000000004')
|
|
|
|
// returns a LWGEOM object
|
2004-03-11 00:54:37 +00:00
|
|
|
PG_FUNCTION_INFO_V1(LWGEOM_in);
|
|
|
|
Datum LWGEOM_in(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *str = PG_GETARG_CSTRING(0);
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
char *semicolonLoc,start;
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//determine if its WKB or WKT
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
semicolonLoc = strchr(str,';');
|
|
|
|
if (semicolonLoc == NULL)
|
|
|
|
{
|
|
|
|
start = str[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start =semicolonLoc[1]; // one in
|
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// this is included just for redundancy (new parser can handle wkt and wkb)
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
if (
|
|
|
|
( (start >= '0') && (start <= '9') ) ||
|
|
|
|
( (start >= 'A') && (start <= 'F') )
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//its WKB
|
|
|
|
//PG_RETURN_POINTER(parse_lwgeom_serialized_form(str));
|
|
|
|
PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); // this function handles wkt and wkb (in hex-form)
|
|
|
|
}
|
2004-06-07 10:07:06 +00:00
|
|
|
else if ( (start == 'P') || (start == 'L') || (start == 'M') || (start == 'G') || (start == 'p') || (start == 'l') || (start == 'm') || (start == 'g'))
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
|
|
|
// its WKT
|
|
|
|
PG_RETURN_POINTER( parse_lwgeom_wkt(str) ); // this function handles wkt and wkb (in hex-form)
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(ERROR,"couldnt determine if input lwgeom is WKB or WKT");
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
// LWGEOM_out(lwgeom) --> cstring
|
|
|
|
// output is 'SRID=#;<wkb in hex form>'
|
|
|
|
// ie. 'SRID=-99;0101000000000000000000F03F0000000000000040'
|
|
|
|
// WKB is machine endian
|
|
|
|
// if SRID=-1, the 'SRID=-1;' will probably not be present.
|
2004-03-11 00:54:37 +00:00
|
|
|
PG_FUNCTION_INFO_V1(LWGEOM_out);
|
|
|
|
Datum LWGEOM_out(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
2004-04-26 23:05:20 +00:00
|
|
|
char *result =unparse_WKB(lwgeom,palloc_fn2,free_fn);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
// LWGEOMFromWKB(wkb, [SRID] )
|
2004-04-26 23:05:20 +00:00
|
|
|
// NOTE: wkb is in *binary* not hex form.
|
2004-03-10 01:15:06 +00:00
|
|
|
PG_FUNCTION_INFO_V1(LWGEOMFromWKB);
|
|
|
|
Datum LWGEOMFromWKB(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
WellKnownBinary *wkb_input = (WellKnownBinary *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
|
|
|
char *wkb_srid_hexized;
|
|
|
|
int size_result,size_header;
|
2004-03-11 00:54:37 +00:00
|
|
|
int SRID = -1;
|
2004-04-26 23:05:20 +00:00
|
|
|
char sridText[100];
|
|
|
|
char *loc;
|
|
|
|
char *lwgeom;
|
|
|
|
int t;
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
if ( ( PG_NARGS()>1) && ( ! PG_ARGISNULL(1) ))
|
2004-03-10 01:15:06 +00:00
|
|
|
SRID = PG_GETARG_INT32(1);
|
|
|
|
else
|
|
|
|
SRID = -1;
|
|
|
|
|
2004-04-06 22:58:11 +00:00
|
|
|
// elog(NOTICE,"LWGEOMFromWKB: entry with SRID=%i",SRID);
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// convert WKB to hexized WKB string
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
size_header = sprintf(sridText,"SRID=%i;",SRID);
|
|
|
|
size_result = size_header + 2*(wkb_input->size -4) + 1; //SRID text size + wkb size (+1 = NULL term)
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
wkb_srid_hexized = palloc(size_result);
|
|
|
|
wkb_srid_hexized[0] = 0; // empty
|
|
|
|
strcpy(wkb_srid_hexized, sridText);
|
|
|
|
loc = wkb_srid_hexized + size_header; // points to null in "SRID=#;"
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
for (t=0; t< (wkb_input->size -4); t++)
|
2004-03-10 01:15:06 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
deparse_hex( ((unsigned char *) wkb_input)[4 + t], &loc[t*2]);
|
2004-03-10 01:15:06 +00:00
|
|
|
}
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
wkb_srid_hexized[size_result-1] = 0; // null term
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"size_header = %i",size_header);
|
|
|
|
//elog(NOTICE,"size_result = %i", size_result);
|
|
|
|
//elog(NOTICE,"LWGEOMFromWKB :: '%s'", wkb_srid_hexized);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
lwgeom = parse_lwgeom_wkt(wkb_srid_hexized);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
pfree(wkb_srid_hexized);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_RETURN_POINTER(lwgeom);
|
2004-03-10 01:15:06 +00:00
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// WKBFromLWGEOM(lwgeom) --> wkb
|
|
|
|
// this will have no 'SRID=#;'
|
|
|
|
PG_FUNCTION_INFO_V1(WKBFromLWGEOM);
|
|
|
|
Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
|
2004-03-10 01:15:06 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
char *lwgeom_input = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
char *hexized_wkb_srid =unparse_WKB(lwgeom_input,palloc_fn2,free_fn); // SRID=#;<hexized wkb>
|
|
|
|
char *hexized_wkb; // hexized_wkb_srid w/o srid
|
|
|
|
char *result; //wkb
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
int len_hexized_wkb;
|
|
|
|
int size_result;
|
|
|
|
char *semicolonLoc;
|
2004-03-10 01:15:06 +00:00
|
|
|
int t;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE, "in WKBFromLWGEOM with WKB = '%s'", hexized_wkb_srid);
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
hexized_wkb = hexized_wkb_srid;
|
|
|
|
semicolonLoc = strchr(hexized_wkb_srid,';');
|
2004-03-10 01:15:06 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
if (semicolonLoc != NULL)
|
|
|
|
{
|
|
|
|
hexized_wkb = (semicolonLoc+1);
|
|
|
|
}
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE, "in WKBFromLWGEOM with WKB (with no 'SRID=#;' = '%s'", hexized_wkb);
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
len_hexized_wkb = strlen(hexized_wkb);
|
|
|
|
size_result = len_hexized_wkb/2 + 4;
|
|
|
|
result = palloc(size_result);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
memcpy(result, &size_result,4); // size header
|
2004-04-06 22:58:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// have a hexized string, want to make it binary
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
for (t=0; t< (len_hexized_wkb/2); t++)
|
2004-04-06 22:58:11 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
((unsigned char *) result +4)[t] = parse_hex( hexized_wkb + (t*2) );
|
2004-04-06 22:58:11 +00:00
|
|
|
}
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
pfree(hexized_wkb_srid);
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_RETURN_POINTER(result);
|
2004-03-10 01:15:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
//given one byte, populate result with two byte representing
|
|
|
|
// the hex number
|
|
|
|
// ie deparse_hex( 255, mystr)
|
|
|
|
// -> mystr[0] = 'F' and mystr[1] = 'F'
|
|
|
|
// no error checking done
|
|
|
|
void deparse_hex(unsigned char str, unsigned char *result)
|
|
|
|
{
|
|
|
|
int input_high;
|
|
|
|
int input_low;
|
|
|
|
|
|
|
|
input_high = (str>>4);
|
|
|
|
input_low = (str & 0x0F);
|
|
|
|
|
|
|
|
switch (input_high)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
result[0] = '0';
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result[0] = '1';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
result[0] = '2';
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
result[0] = '3';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
result[0] = '4';
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
result[0] = '5';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
result[0] = '6';
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
result[0] = '7';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
result[0] = '8';
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
result[0] = '9';
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
result[0] = 'A';
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
result[0] = 'B';
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
result[0] = 'C';
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
result[0] = 'D';
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
result[0] = 'E';
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
result[0] = 'F';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (input_low)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
result[1] = '0';
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result[1] = '1';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
result[1] = '2';
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
result[1] = '3';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
result[1] = '4';
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
result[1] = '5';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
result[1] = '6';
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
result[1] = '7';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
result[1] = '8';
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
result[1] = '9';
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
result[1] = 'A';
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
result[1] = 'B';
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
result[1] = 'C';
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
result[1] = 'D';
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
result[1] = 'E';
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
result[1] = 'F';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//given a string with at least 2 chars in it, convert them to
|
|
|
|
// a byte value. No error checking done!
|
|
|
|
unsigned char parse_hex(char *str)
|
|
|
|
{
|
|
|
|
//do this a little brute force to make it faster
|
|
|
|
|
|
|
|
unsigned char result_high = 0;
|
|
|
|
unsigned char result_low = 0;
|
|
|
|
|
|
|
|
switch (str[0])
|
|
|
|
{
|
|
|
|
case '0' :
|
|
|
|
result_high = 0;
|
|
|
|
break;
|
|
|
|
case '1' :
|
|
|
|
result_high = 1;
|
|
|
|
break;
|
|
|
|
case '2' :
|
|
|
|
result_high = 2;
|
|
|
|
break;
|
|
|
|
case '3' :
|
|
|
|
result_high = 3;
|
|
|
|
break;
|
|
|
|
case '4' :
|
|
|
|
result_high = 4;
|
|
|
|
break;
|
|
|
|
case '5' :
|
|
|
|
result_high = 5;
|
|
|
|
break;
|
|
|
|
case '6' :
|
|
|
|
result_high = 6;
|
|
|
|
break;
|
|
|
|
case '7' :
|
|
|
|
result_high = 7;
|
|
|
|
break;
|
|
|
|
case '8' :
|
|
|
|
result_high = 8;
|
|
|
|
break;
|
|
|
|
case '9' :
|
|
|
|
result_high = 9;
|
|
|
|
break;
|
|
|
|
case 'A' :
|
|
|
|
result_high = 10;
|
|
|
|
break;
|
|
|
|
case 'B' :
|
|
|
|
result_high = 11;
|
|
|
|
break;
|
|
|
|
case 'C' :
|
|
|
|
result_high = 12;
|
|
|
|
break;
|
|
|
|
case 'D' :
|
|
|
|
result_high = 13;
|
|
|
|
break;
|
|
|
|
case 'E' :
|
|
|
|
result_high = 14;
|
|
|
|
break;
|
|
|
|
case 'F' :
|
|
|
|
result_high = 15;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (str[1])
|
|
|
|
{
|
|
|
|
case '0' :
|
|
|
|
result_low = 0;
|
|
|
|
break;
|
|
|
|
case '1' :
|
|
|
|
result_low = 1;
|
|
|
|
break;
|
|
|
|
case '2' :
|
|
|
|
result_low = 2;
|
|
|
|
break;
|
|
|
|
case '3' :
|
|
|
|
result_low = 3;
|
|
|
|
break;
|
|
|
|
case '4' :
|
|
|
|
result_low = 4;
|
|
|
|
break;
|
|
|
|
case '5' :
|
|
|
|
result_low = 5;
|
|
|
|
break;
|
|
|
|
case '6' :
|
|
|
|
result_low = 6;
|
|
|
|
break;
|
|
|
|
case '7' :
|
|
|
|
result_low = 7;
|
|
|
|
break;
|
|
|
|
case '8' :
|
|
|
|
result_low = 8;
|
|
|
|
break;
|
|
|
|
case '9' :
|
|
|
|
result_low = 9;
|
|
|
|
break;
|
|
|
|
case 'A' :
|
|
|
|
result_low = 10;
|
|
|
|
break;
|
|
|
|
case 'B' :
|
|
|
|
result_low = 11;
|
|
|
|
break;
|
|
|
|
case 'C' :
|
|
|
|
result_low = 12;
|
|
|
|
break;
|
|
|
|
case 'D' :
|
|
|
|
result_low = 13;
|
|
|
|
break;
|
|
|
|
case 'E' :
|
|
|
|
result_low = 14;
|
|
|
|
break;
|
|
|
|
case 'F' :
|
|
|
|
result_low = 15;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (unsigned char) ((result_high<<4) + result_low);
|
|
|
|
}
|
|
|
|
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// for the parser/unparser -- it needs memory management functions
|
2004-04-26 23:05:20 +00:00
|
|
|
void *palloc_fn2(size_t size)
|
|
|
|
{
|
|
|
|
void * result;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result = palloc(size);
|
|
|
|
// elog(NOTICE," palloc(%i) at %p",size,result);
|
2004-04-07 23:12:31 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void free_fn(void *ptr)
|
2004-04-07 23:12:31 +00:00
|
|
|
{
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// elog(NOTICE," pfree(%p)", ptr);
|
|
|
|
pfree(ptr);
|
2004-04-07 23:12:31 +00:00
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//convert LWGEOM to wkt (in TEXT format)
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_FUNCTION_INFO_V1(LWGEOM_asText);
|
|
|
|
Datum LWGEOM_asText(PG_FUNCTION_ARGS)
|
2004-04-07 23:12:31 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
|
|
|
char *result_cstring = unparse_WKT(lwgeom,palloc_fn2,free_fn);
|
|
|
|
int len;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
char *result,*loc_wkt;
|
|
|
|
char *semicolonLoc;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
semicolonLoc = strchr(result_cstring,';');
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//loc points to start of wkt
|
|
|
|
if (semicolonLoc == NULL)
|
|
|
|
loc_wkt = result_cstring;
|
|
|
|
else
|
|
|
|
loc_wkt = semicolonLoc +1;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
len = strlen(loc_wkt)+4;
|
|
|
|
result = palloc(len);
|
|
|
|
memcpy(result, &len, 4);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
memcpy(result+4,loc_wkt, len-4);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
pfree(result_cstring);
|
|
|
|
PG_RETURN_POINTER(result);
|
2004-04-07 23:12:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// puts a bbox inside the geometry
|
|
|
|
PG_FUNCTION_INFO_V1(LWGEOM_addBBOX);
|
|
|
|
Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
|
|
|
char *result;
|
|
|
|
BOX2DFLOAT4 box;
|
|
|
|
unsigned char old_type;
|
|
|
|
int size;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"in LWGEOM_addBBOX");
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
if (lwgeom_hasBBOX( (unsigned char) lwgeom[0] ) )
|
2004-04-07 23:12:31 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"LWGEOM_addBBOX -- already has bbox");
|
|
|
|
// easy - already has one. Just copy!
|
|
|
|
result = palloc ( *((int *) lwgeom));
|
|
|
|
memcpy(result,lwgeom, *((int *) lwgeom));
|
|
|
|
PG_RETURN_POINTER(result);
|
2004-04-07 23:12:31 +00:00
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"LWGEOM_addBBOX -- giving it a bbox");
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//construct new one
|
|
|
|
box = getbox2d(lwgeom+4);
|
|
|
|
old_type = (unsigned char) lwgeom[4];
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
size = *((int *) lwgeom) +sizeof(BOX2DFLOAT4);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result = palloc ( size );// 16 for bbox2d
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
memcpy(result,&size,4); // size
|
|
|
|
result[4] = lwgeom_makeType_full( lwgeom_ndims(old_type), lwgeom_hasSRID(old_type), lwgeom_getType(old_type), 1);
|
|
|
|
memcpy(result+5, &box, sizeof(BOX2DFLOAT4)); // copy in bbox
|
|
|
|
memcpy(result+5+sizeof(BOX2DFLOAT4), lwgeom+5, *((int *) lwgeom) -5); // everything but the type and length
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_RETURN_POINTER(result);
|
|
|
|
}
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//for the wkt parser
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void elog_ERROR(const char* string)
|
2004-04-07 23:12:31 +00:00
|
|
|
{
|
2004-04-28 21:00:43 +00:00
|
|
|
elog(ERROR,string);
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void *palloc_fn(size_t size)
|
|
|
|
{
|
|
|
|
void * result;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result = palloc(size);
|
|
|
|
return result;
|
|
|
|
}
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
// parse WKT input
|
|
|
|
// parse_WKT_lwgeom(TEXT) -> LWGEOM
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_FUNCTION_INFO_V1(parse_WKT_lwgeom);
|
|
|
|
Datum parse_WKT_lwgeom(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
const char *wkt_input = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); // text
|
|
|
|
char *serialized_form; //with length
|
|
|
|
char *wkt;
|
|
|
|
int wkt_size ;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
wkt_size = (*(int*) wkt_input) -4; // actual letters
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
wkt = palloc( wkt_size+1); //+1 for null
|
|
|
|
memcpy(wkt, wkt_input+4, wkt_size );
|
|
|
|
wkt[wkt_size] = 0; // null term
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"in parse_WKT_lwgeom");
|
|
|
|
//elog(NOTICE,"in parse_WKT_lwgeom with input: '%s'",wkt);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//serialized_form = parse_WKT((const char *)wkt,(allocator) malloc, (report_error)elog_ERROR);
|
|
|
|
serialized_form = parse_lwg((const char *)wkt,(allocator) palloc_fn, (report_error)elog_ERROR);
|
|
|
|
//elog(NOTICE,"parse_WKT_lwgeom:: finished parse");
|
|
|
|
pfree (wkt);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
if (serialized_form == NULL)
|
|
|
|
elog(ERROR,"parse_WKT:: couldnt parse!");
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// printBYTES(serialized_form+4,*((int*) serialized_form)-4);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// result = palloc( (*((int*) serialized_form)));
|
|
|
|
// memcpy(result, serialized_form, *((int*) serialized_form));
|
|
|
|
// free(serialized_form);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// PG_RETURN_POINTER(result);
|
|
|
|
//PG_RETURN_NULL();
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
PG_RETURN_POINTER(serialized_form);
|
2004-04-07 23:12:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
char *parse_lwgeom_wkt(char *wkt_input)
|
|
|
|
{
|
|
|
|
char *serialized_form = parse_lwg((const char *)wkt_input,(allocator) palloc_fn, (report_error)elog_ERROR);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"parse_lwgeom_wkt with %s",wkt_input);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
if (serialized_form == NULL)
|
|
|
|
elog(ERROR,"parse_WKT:: couldnt parse!");
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
return serialized_form;
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// result = palloc( (*((int*) serialized_form)));
|
|
|
|
// memcpy(result, serialized_form, *((int*) serialized_form));
|
|
|
|
// free(serialized_form);
|
2004-04-07 23:12:31 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// return result;
|
|
|
|
}
|
2004-04-07 23:12:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|