2004-03-09 17:29:52 +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-29 18:44:36 +00:00
|
|
|
// This is an implementation of the functions defined in lwgeom.h
|
|
|
|
|
|
|
|
//forward decs
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
extern BOX3D *lw_geom_getBB_simple(char *serialized_form);
|
|
|
|
|
|
|
|
|
|
|
|
// this will change to NaN when I figure out how to
|
|
|
|
// get NaN in a platform-independent way
|
|
|
|
|
|
|
|
#define NO_Z_VALUE 0
|
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
//#define DEBUG 1
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
//*********************************************************************
|
|
|
|
// BOX routines
|
|
|
|
|
|
|
|
// returns the float thats very close to the input, but <=
|
|
|
|
// handles the funny differences in float4 and float8 reps.
|
2004-04-27 20:49:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
//these are taken from glibc
|
|
|
|
// some machines do *not* have these functions defined, so we give
|
|
|
|
// an implementation of them here.
|
|
|
|
|
2004-04-28 18:27:07 +00:00
|
|
|
typedef int int32_tt;
|
|
|
|
typedef unsigned int u_int32_tt;
|
2004-04-27 20:49:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
float nextafterf_custom(float x, float y);
|
|
|
|
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
float value;
|
2004-04-28 18:27:07 +00:00
|
|
|
u_int32_tt word;
|
2004-04-27 20:49:25 +00:00
|
|
|
} ieee_float_shape_type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define GET_FLOAT_WORD(i,d) \
|
|
|
|
do { \
|
|
|
|
ieee_float_shape_type gf_u; \
|
|
|
|
gf_u.value = (d); \
|
|
|
|
(i) = gf_u.word; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
#define SET_FLOAT_WORD(d,i) \
|
|
|
|
do { \
|
|
|
|
ieee_float_shape_type sf_u; \
|
|
|
|
sf_u.word = (i); \
|
|
|
|
(d) = sf_u.value; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// returns the next smaller or next larger float
|
|
|
|
// from x (in direction of y).
|
2004-04-27 20:49:25 +00:00
|
|
|
float nextafterf_custom(float x, float y)
|
|
|
|
{
|
2004-04-28 18:27:07 +00:00
|
|
|
int32_tt hx,hy,ix,iy;
|
2004-04-27 20:49:25 +00:00
|
|
|
|
|
|
|
GET_FLOAT_WORD(hx,x);
|
|
|
|
GET_FLOAT_WORD(hy,y);
|
|
|
|
ix = hx&0x7fffffff; /* |x| */
|
|
|
|
iy = hy&0x7fffffff; /* |y| */
|
|
|
|
|
|
|
|
if((ix>0x7f800000) || /* x is nan */
|
|
|
|
(iy>0x7f800000)) /* y is nan */
|
|
|
|
return x+y;
|
|
|
|
if(x==y) return y; /* x=y, return y */
|
|
|
|
if(ix==0) { /* x == 0 */
|
|
|
|
SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
|
|
|
|
y = x*x;
|
|
|
|
if(y==x) return y; else return x; /* raise underflow flag */
|
|
|
|
}
|
|
|
|
if(hx>=0) { /* x > 0 */
|
|
|
|
if(hx>hy) { /* x > y, x -= ulp */
|
|
|
|
hx -= 1;
|
|
|
|
} else { /* x < y, x += ulp */
|
|
|
|
hx += 1;
|
|
|
|
}
|
|
|
|
} else { /* x < 0 */
|
|
|
|
if(hy>=0||hx>hy){ /* x < y, x -= ulp */
|
|
|
|
hx -= 1;
|
|
|
|
} else { /* x > y, x += ulp */
|
|
|
|
hx += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hy = hx&0x7f800000;
|
|
|
|
if(hy>=0x7f800000) return x+x; /* overflow */
|
|
|
|
if(hy<0x00800000) { /* underflow */
|
|
|
|
y = x*x;
|
|
|
|
if(y!=x) { /* raise underflow flag */
|
|
|
|
SET_FLOAT_WORD(y,hx);
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SET_FLOAT_WORD(x,hx);
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
float nextDown_f(double d)
|
|
|
|
{
|
|
|
|
float result = d;
|
|
|
|
|
|
|
|
if ( ((double) result) <=d)
|
|
|
|
return result;
|
|
|
|
|
2004-04-27 20:49:25 +00:00
|
|
|
return nextafterf_custom(result, result - 1000000);
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns the float thats very close to the input, but >=
|
|
|
|
// handles the funny differences in float4 and float8 reps.
|
|
|
|
float nextUp_f(double d)
|
|
|
|
{
|
|
|
|
float result = d;
|
|
|
|
|
|
|
|
if ( ((double) result) >=d)
|
|
|
|
return result;
|
|
|
|
|
2004-04-27 20:49:25 +00:00
|
|
|
return nextafterf_custom(result, result + 1000000);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// returns the double thats very close to the input, but <
|
|
|
|
// handles the funny differences in float4 and float8 reps.
|
|
|
|
double nextDown_d(float d)
|
|
|
|
{
|
|
|
|
double result = d;
|
|
|
|
|
|
|
|
if ( result < d)
|
|
|
|
return result;
|
|
|
|
|
2004-04-27 20:49:25 +00:00
|
|
|
return nextafterf_custom(result, result - 1000000);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns the double thats very close to the input, but >
|
|
|
|
// handles the funny differences in float4 and float8 reps.
|
|
|
|
double nextUp_d(float d)
|
|
|
|
{
|
|
|
|
double result = d;
|
|
|
|
|
|
|
|
if ( result > d)
|
|
|
|
return result;
|
|
|
|
|
2004-04-27 20:49:25 +00:00
|
|
|
return nextafterf_custom(result, result + 1000000);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
// Convert BOX3D to BOX2D
|
|
|
|
// returned box2d is allocated with 'palloc'
|
2004-04-26 23:05:20 +00:00
|
|
|
BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if (box == NULL)
|
2004-08-19 13:16:16 +00:00
|
|
|
{
|
|
|
|
elog(NOTICE, "box3d_to_box2df got NUL box");
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
2004-08-19 13:16:16 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result->xmin = nextDown_f(box->xmin);
|
|
|
|
result->ymin = nextDown_f(box->ymin);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result->xmax = nextUp_f(box->xmax);
|
|
|
|
result->ymax = nextUp_f(box->ymax);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//convert postgresql BOX to BOX2D
|
2004-04-26 23:05:20 +00:00
|
|
|
BOX2DFLOAT4 *box_to_box2df(BOX *box)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
BOX2DFLOAT4 *result = (BOX2DFLOAT4*) palloc(sizeof(BOX2DFLOAT4));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if (box == NULL)
|
|
|
|
return result;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result->xmin = nextDown_f(box->low.x);
|
|
|
|
result->ymin = nextDown_f(box->low.y);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result->xmax = nextUp_f(box->high.x);
|
|
|
|
result->ymax = nextUp_f(box->high.x);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// convert BOX2D to BOX3D
|
2004-09-06 09:13:13 +00:00
|
|
|
// zmin and zmax are set to 0.0
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX3D box2df_to_box3d(BOX2DFLOAT4 *box)
|
|
|
|
{
|
|
|
|
BOX3D result;
|
|
|
|
|
|
|
|
if (box == NULL)
|
|
|
|
return result;
|
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
result.xmin = box->xmin;
|
|
|
|
result.ymin = box->ymin;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
result.xmax = box->xmax;
|
|
|
|
result.ymax = box->ymax;
|
|
|
|
|
|
|
|
result.zmin = result.zmax = 0.0;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
// convert BOX2D to BOX3D, using pre-allocated BOX3D as output
|
|
|
|
// Z values are set to 0.0.
|
|
|
|
void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
|
|
|
|
{
|
|
|
|
if (box == NULL) return;
|
|
|
|
|
|
|
|
out->xmin = box->xmin;
|
|
|
|
out->ymin = box->ymin;
|
|
|
|
|
|
|
|
out->xmax = box->xmax;
|
|
|
|
out->ymax = box->ymax;
|
|
|
|
|
|
|
|
out->zmin = out->zmax = 0.0;
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
// convert BOX2D to postgresql BOX
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX box2df_to_box(BOX2DFLOAT4 *box)
|
|
|
|
{
|
|
|
|
BOX result;
|
|
|
|
|
|
|
|
if (box == NULL)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
result.low.x = nextDown_d(box->xmin);
|
|
|
|
result.low.y = nextDown_d(box->ymin);
|
|
|
|
|
|
|
|
result.high.x = nextUp_d(box->xmax);
|
|
|
|
result.high.y = nextUp_d(box->ymax);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-09-06 10:37:09 +00:00
|
|
|
// convert BOX2D to postgresql BOX
|
|
|
|
void
|
|
|
|
box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out)
|
|
|
|
{
|
|
|
|
if (box == NULL) return;
|
|
|
|
|
|
|
|
out->low.x = nextDown_d(box->xmin);
|
|
|
|
out->low.y = nextDown_d(box->ymin);
|
|
|
|
|
|
|
|
out->high.x = nextUp_d(box->xmax);
|
|
|
|
out->high.y = nextUp_d(box->ymax);
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
// returns a BOX3D that encloses b1 and b2
|
|
|
|
// combine_boxes(NULL,A) --> A
|
|
|
|
// combine_boxes(A,NULL) --> A
|
|
|
|
// combine_boxes(A,B) --> A union B
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2)
|
|
|
|
{
|
|
|
|
BOX3D *result;
|
|
|
|
|
|
|
|
result =(BOX3D*) palloc(sizeof(BOX3D));
|
|
|
|
|
|
|
|
if ( (b1 == NULL) && (b2 == NULL) )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1 == NULL)
|
|
|
|
{
|
|
|
|
//return b2
|
|
|
|
memcpy(result, b2, sizeof(BOX3D));
|
|
|
|
}
|
|
|
|
if (b2 == NULL)
|
|
|
|
{
|
|
|
|
//return b1
|
|
|
|
memcpy(result, b1, sizeof(BOX3D));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1->xmin < b2->xmin)
|
|
|
|
result->xmin = b1->xmin;
|
|
|
|
else
|
|
|
|
result->xmin = b2->xmin;
|
|
|
|
|
|
|
|
if (b1->ymin < b2->ymin)
|
|
|
|
result->ymin = b1->ymin;
|
|
|
|
else
|
|
|
|
result->ymin = b2->ymin;
|
|
|
|
|
|
|
|
|
|
|
|
if (b1->xmax > b2->xmax)
|
|
|
|
result->xmax = b1->xmax;
|
|
|
|
else
|
2004-04-26 23:05:20 +00:00
|
|
|
result->xmax = b2->xmax;
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (b1->ymax > b2->ymax)
|
2004-04-26 23:05:20 +00:00
|
|
|
result->ymax = b1->ymax;
|
2004-03-09 17:29:52 +00:00
|
|
|
else
|
|
|
|
result->ymax = b2->ymax;
|
|
|
|
|
|
|
|
if (b1->zmax > b2->zmax)
|
|
|
|
result->zmax = b1->zmax;
|
|
|
|
else
|
|
|
|
result->zmax = b2->zmax;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (b1->zmin > b2->zmin)
|
2004-04-26 23:05:20 +00:00
|
|
|
result->zmin = b1->zmin;
|
2004-03-09 17:29:52 +00:00
|
|
|
else
|
|
|
|
result->zmin = b2->zmin;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// returns a real entity so it doesnt leak
|
|
|
|
// if this has a pre-built BOX2d, then we use it,
|
|
|
|
// otherwise we need to compute it.
|
|
|
|
BOX2DFLOAT4 getbox2d(char *serialized_form)
|
|
|
|
{
|
2004-08-19 13:16:16 +00:00
|
|
|
int type = (unsigned char) serialized_form[0];
|
|
|
|
char *loc;
|
|
|
|
BOX2DFLOAT4 result;
|
|
|
|
BOX3D *box3d;
|
|
|
|
BOX2DFLOAT4 *box;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
loc = serialized_form+1;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
//elog(NOTICE,"getbox2d: type is %d", type);
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
//woot - this is easy
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"getbox2d has box");
|
2004-08-19 13:16:16 +00:00
|
|
|
memcpy(&result,loc, sizeof(BOX2DFLOAT4));
|
|
|
|
return result;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
//we have to actually compute it!
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"getbox2d -- computing bbox");
|
2004-08-19 13:16:16 +00:00
|
|
|
box3d = lw_geom_getBB_simple(serialized_form);
|
|
|
|
//elog(NOTICE,"lw_geom_getBB_simple got bbox3d(%.15g %.15g,%.15g %.15g)",box3d->xmin,box3d->ymin,box3d->xmax,box3d->ymax);
|
|
|
|
box = box3d_to_box2df(box3d);
|
|
|
|
//elog(NOTICE,"box3d made box2d(%.15g %.15g,%.15g %.15g)",box->xmin,box->ymin,box->xmax,box->ymax);
|
|
|
|
memcpy(&result,box, sizeof(BOX2DFLOAT4));
|
|
|
|
pfree(box3d);
|
|
|
|
pfree(box);
|
|
|
|
return result;
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// same as getbox2d, but modifies box instead of returning result on the stack
|
2004-09-06 16:04:13 +00:00
|
|
|
int
|
2004-08-20 14:08:41 +00:00
|
|
|
getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2004-08-20 14:08:41 +00:00
|
|
|
unsigned char type = (unsigned char) serialized_form[0];
|
|
|
|
char *loc;
|
|
|
|
BOX3D *box3d;
|
|
|
|
BOX2DFLOAT4 *box2;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
loc = serialized_form+1;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
//woot - this is easy
|
|
|
|
//elog(NOTICE,"getbox2d has box");
|
|
|
|
memcpy(box,loc, sizeof(BOX2DFLOAT4));
|
2004-09-06 16:04:13 +00:00
|
|
|
return 1;
|
2004-08-20 14:08:41 +00:00
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
//we have to actually compute it!
|
2004-04-26 23:05:20 +00:00
|
|
|
//elog(NOTICE,"getbox2d_p:: computing box");
|
2004-08-20 14:08:41 +00:00
|
|
|
box3d = lw_geom_getBB_simple(serialized_form);
|
2004-09-06 16:04:13 +00:00
|
|
|
if ( ! box3d )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2004-08-20 14:08:41 +00:00
|
|
|
box2 = box3d_to_box2df(box3d);
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
memcpy(box,box2, sizeof(BOX2DFLOAT4));
|
|
|
|
pfree(box3d);
|
|
|
|
pfree(box2);
|
2004-09-06 16:04:13 +00:00
|
|
|
return 1;
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-16 09:05:10 +00:00
|
|
|
// this function returns a pointer to the 'internal' bounding
|
|
|
|
// box of a serialized-form geometry. If the geometry does
|
|
|
|
// not have an embedded bounding box the function returns NULL.
|
|
|
|
// READ-ONLY!
|
|
|
|
const BOX2DFLOAT4 *
|
|
|
|
getbox2d_internal(char *serialized_form)
|
|
|
|
{
|
|
|
|
unsigned char type = (unsigned char) serialized_form[0];
|
|
|
|
|
|
|
|
// No embedded bounding box ...
|
|
|
|
if (!lwgeom_hasBBOX(type)) return NULL;
|
|
|
|
|
|
|
|
return (BOX2DFLOAT4 *)(serialized_form+1);
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
//************************************************************************
|
|
|
|
// POINTARRAY support functions
|
|
|
|
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// will set point's z=0 (or NaN) if pa is 2d
|
|
|
|
// will set point's m=0 (or NaN( if pa is 3d or 2d
|
|
|
|
// NOTE: point is a real POINT3D *not* a pointer
|
|
|
|
POINT4D getPoint4d(POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
POINT4D result;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return result; //error
|
|
|
|
}
|
|
|
|
|
|
|
|
size = pointArray_ptsize(pa);
|
|
|
|
|
|
|
|
// this does x,y
|
|
|
|
memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
|
|
|
if (pa->ndims >2)
|
|
|
|
memcpy(&result.z, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) );
|
|
|
|
else
|
|
|
|
result.z = NO_Z_VALUE;
|
|
|
|
if (pa->ndims >3)
|
|
|
|
memcpy(&result.m, &pa->serialized_pointlist[size*n + sizeof(double)*3],sizeof(double) );
|
|
|
|
else
|
|
|
|
result.m = NO_Z_VALUE;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// will set point's z=0 (or NaN) if pa is 2d
|
|
|
|
// will set point's m=0 (or NaN( if pa is 3d or 2d
|
|
|
|
// NOTE: this will modify the point4d pointed to by 'point'.
|
|
|
|
void getPoint4d_p(POINTARRAY *pa, int n, char *point)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return ; //error
|
|
|
|
}
|
|
|
|
|
|
|
|
size = pointArray_ptsize(pa);
|
|
|
|
|
|
|
|
// this does x,y
|
|
|
|
memcpy(point, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
|
|
|
if (pa->ndims >2)
|
|
|
|
memcpy(point+16, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double bad=NO_Z_VALUE;
|
|
|
|
memcpy(point+16, &bad,sizeof(double) );
|
|
|
|
//point->z = NO_Z_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pa->ndims >3)
|
2004-04-26 23:05:20 +00:00
|
|
|
memcpy(point+24, &pa->serialized_pointlist[size*n + sizeof(double)*3],sizeof(double) );
|
2004-04-02 19:03:06 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
double bad=NO_Z_VALUE;
|
|
|
|
memcpy(point+24, &bad,sizeof(double) );
|
|
|
|
//point->z = NO_Z_VALUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// will set point's z=0 (or NaN) if pa is 2d
|
|
|
|
// NOTE: point is a real POINT3D *not* a pointer
|
|
|
|
POINT3D getPoint3d(POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
POINT3D result;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return result; //error
|
|
|
|
}
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// this does x,y
|
|
|
|
memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
2004-04-02 19:03:06 +00:00
|
|
|
if (pa->ndims >2)
|
2004-03-09 17:29:52 +00:00
|
|
|
memcpy(&result.z, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) );
|
|
|
|
else
|
|
|
|
result.z = NO_Z_VALUE;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// will set point's z=0 (or NaN) if pa is 2d
|
|
|
|
// NOTE: this will modify the point3d pointed to by 'point'.
|
|
|
|
// we use a char* instead of a POINT3D because we want to use this function
|
|
|
|
// for serialization/de-serialization
|
|
|
|
void getPoint3d_p(POINTARRAY *pa, int n, char *point)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
elog(NOTICE, "%d out of numpoint range (%d)", n, pa->npoints);
|
|
|
|
return ; //error
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
// this does x,y
|
|
|
|
memcpy(point,
|
|
|
|
&pa->serialized_pointlist[size*n],
|
|
|
|
sizeof(double)*2 );
|
|
|
|
|
|
|
|
if (pa->ndims >2)
|
|
|
|
memcpy(point+16, &pa->serialized_pointlist[size*n + sizeof(double)*2],sizeof(double) );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double bad=NO_Z_VALUE;
|
2004-04-02 19:03:06 +00:00
|
|
|
memcpy(point+16, &bad,sizeof(double) );
|
2004-03-09 17:29:52 +00:00
|
|
|
//point->z = NO_Z_VALUE;
|
2004-08-19 13:16:16 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// z value (if present is not returned)
|
|
|
|
// NOTE: point is a real POINT3D *not* a pointer
|
|
|
|
POINT2D getPoint2d(POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
POINT2D result;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return result; //error
|
|
|
|
}
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// this does x,y
|
|
|
|
memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// z value (if present is not returned)
|
|
|
|
// NOTE: this will modify the point2d pointed to by 'point'.
|
|
|
|
// we use a char* instead of a POINT2D because we want to use this function
|
|
|
|
// for serialization/de-serialization
|
|
|
|
void getPoint2d_p(POINTARRAY *pa, int n, char *point)
|
|
|
|
{
|
2004-08-23 13:38:54 +00:00
|
|
|
int size;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return; //error
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
// this does x,y
|
|
|
|
memcpy(point, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
// get a pointer to nth point of a POINTARRAY
|
|
|
|
// You'll need to cast it to appropriate dimensioned point.
|
|
|
|
// Note that if you cast to a higher dimensional point you'll
|
|
|
|
// possibly corrupt the POINTARRAY.
|
|
|
|
char *
|
|
|
|
getPoint(POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return NULL; //error
|
|
|
|
}
|
|
|
|
|
|
|
|
size = pointArray_ptsize(pa);
|
|
|
|
|
|
|
|
// this does x,y
|
2004-08-23 16:05:45 +00:00
|
|
|
return &(pa->serialized_pointlist[size*n]);
|
2004-08-23 13:38:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// constructs a POINTARRAY.
|
|
|
|
// NOTE: points is *not* copied, so be careful about modification (can be aligned/missaligned)
|
2004-04-02 19:03:06 +00:00
|
|
|
// NOTE: ndims is descriptive - it describes what type of data 'points'
|
2004-03-09 17:29:52 +00:00
|
|
|
// points to. No data conversion is done.
|
2004-04-02 19:03:06 +00:00
|
|
|
POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
POINTARRAY *pa;
|
|
|
|
pa = (POINTARRAY*)palloc(sizeof(pa));
|
|
|
|
|
2004-04-06 22:58:11 +00:00
|
|
|
if (ndims>4)
|
2004-04-02 19:03:06 +00:00
|
|
|
elog(ERROR,"pointArray_construct:: called with dims = %i", (int) ndims);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
pa->ndims = ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
pa->npoints = npoints;
|
|
|
|
pa->serialized_pointlist = points;
|
|
|
|
|
|
|
|
return pa;
|
|
|
|
}
|
|
|
|
|
|
|
|
//calculate the bounding box of a set of points
|
|
|
|
// returns a postgresql box
|
|
|
|
BOX3D *pointArray_bbox(POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
BOX3D *result;
|
|
|
|
POINT3D pt;
|
|
|
|
|
|
|
|
result = (BOX3D*) palloc(sizeof(BOX3D));
|
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if (pa->npoints == 0)
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
|
|
|
|
getPoint3d_p(pa,0,(char*)&pt);
|
|
|
|
result->xmin = pt.x;
|
|
|
|
result->ymin = pt.y;
|
|
|
|
result->zmin = pt.z;
|
|
|
|
|
|
|
|
result->xmax = pt.x;
|
|
|
|
result->ymax = pt.y;
|
|
|
|
result->zmax = pt.z;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
for (t=1;t<pa->npoints;t++)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
getPoint3d_p(pa,t,(char*)&pt);
|
|
|
|
if (pt.x < result->xmin)
|
|
|
|
result->xmin = pt.x;
|
2004-08-19 13:16:16 +00:00
|
|
|
if (pt.y <
|
|
|
|
result->ymin)
|
2004-03-09 17:29:52 +00:00
|
|
|
result->ymin = pt.y;
|
|
|
|
if (pt.x > result->xmax)
|
|
|
|
result->xmax = pt.x;
|
|
|
|
if (pt.y > result->ymax)
|
|
|
|
result->ymax = pt.y;
|
|
|
|
|
|
|
|
if (pt.z > result->zmax)
|
|
|
|
result->zmax = pt.z;
|
|
|
|
if (pt.z < result->zmax)
|
|
|
|
result->zmax = pt.z;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
//size of point represeneted in the POINTARRAY
|
|
|
|
// 16 for 2d, 24 for 3d, 32 for 4d
|
|
|
|
int pointArray_ptsize(POINTARRAY *pa)
|
|
|
|
{
|
2004-04-02 19:03:06 +00:00
|
|
|
if (pa->ndims == 3)
|
2004-03-10 01:15:06 +00:00
|
|
|
return 24;
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (pa->ndims == 2)
|
2004-03-10 01:15:06 +00:00
|
|
|
return 16;
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (pa->ndims == 4)
|
|
|
|
return 32;
|
|
|
|
elog(ERROR,"pointArray_ptsize:: ndims isnt 2,3, or 4");
|
|
|
|
return 0; // never get here
|
2004-03-10 01:15:06 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// basic type handling
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// returns true if this type says it has an SRID (S bit set)
|
2004-04-26 23:05:20 +00:00
|
|
|
bool lwgeom_hasSRID(unsigned char type)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-03-11 00:54:37 +00:00
|
|
|
return (type & 0x40);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D
|
2004-04-26 23:05:20 +00:00
|
|
|
int lwgeom_ndims(unsigned char type)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-04-02 19:03:06 +00:00
|
|
|
return ( (type & 0x30) >>4) +2;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
// get base type (ie. POLYGONTYPE)
|
2004-04-26 23:05:20 +00:00
|
|
|
int lwgeom_getType(unsigned char type)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
return (type & 0x0F);
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
|
|
|
|
//construct a type (hasBOX=false)
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char lwgeom_makeType(int ndims, char hasSRID, int type)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char result = type;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
if (ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
result = result | 0x10;
|
2004-04-02 19:03:06 +00:00
|
|
|
if (ndims == 4)
|
2004-03-09 17:29:52 +00:00
|
|
|
result = result | 0x20;
|
2004-04-02 19:03:06 +00:00
|
|
|
if (hasSRID)
|
|
|
|
result = result | 0x40;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//construct a type
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, bool hasBBOX)
|
|
|
|
{
|
|
|
|
unsigned char result = type;
|
|
|
|
|
|
|
|
if (ndims == 3)
|
|
|
|
result = result | 0x10;
|
|
|
|
if (ndims == 4)
|
|
|
|
result = result | 0x20;
|
|
|
|
if (hasSRID)
|
|
|
|
result = result | 0x40;
|
|
|
|
if (hasBBOX)
|
|
|
|
result = result | 0x80;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//returns true if there's a bbox in this LWGEOM (B bit set)
|
2004-04-26 23:05:20 +00:00
|
|
|
bool lwgeom_hasBBOX(unsigned char type)
|
|
|
|
{
|
|
|
|
return (type & 0x80);
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
//*****************************************************************************
|
|
|
|
// basic sub-geometry types
|
|
|
|
|
|
|
|
// handle missaligned unsigned int32 data
|
|
|
|
uint32 get_uint32(char *loc)
|
|
|
|
{
|
|
|
|
uint32 result;
|
|
|
|
|
2004-08-23 08:32:14 +00:00
|
|
|
memcpy(&result, loc, sizeof(uint32));
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle missaligned signed int32 data
|
|
|
|
int32 get_int32(char *loc)
|
|
|
|
{
|
|
|
|
int32 result;
|
|
|
|
|
|
|
|
memcpy(&result,loc, sizeof(int32));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
// basic LWLINE functions
|
|
|
|
|
|
|
|
|
2004-09-06 16:04:13 +00:00
|
|
|
// construct a new LWLINE. points will *NOT* be copied
|
2004-03-09 17:29:52 +00:00
|
|
|
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
2004-04-02 19:03:06 +00:00
|
|
|
LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
LWLINE *result;
|
|
|
|
result = (LWLINE*) palloc( sizeof(LWLINE));
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims =ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
result->SRID = SRID;
|
|
|
|
result->points = points;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// given the LWGEOM serialized form (or a pointer into a muli* one)
|
|
|
|
// construct a proper LWLINE.
|
|
|
|
// serialized_form should point to the 8bit type format (with type = 2)
|
|
|
|
// See serialized form doc
|
|
|
|
LWLINE *lwline_deserialize(char *serialized_form)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
LWLINE *result;
|
|
|
|
char *loc =NULL;
|
|
|
|
uint32 npoints;
|
|
|
|
POINTARRAY *pa;
|
|
|
|
|
2004-08-23 08:32:14 +00:00
|
|
|
result = (LWLINE*) palloc(sizeof(LWLINE)) ;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
type = (unsigned char) serialized_form[0];
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( lwgeom_getType(type) != LINETYPE)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
|
|
|
elog(ERROR,"lwline_deserialize: attempt to deserialize a line when its not really a line");
|
2004-03-09 17:29:52 +00:00
|
|
|
return NULL;
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
2004-08-23 08:32:14 +00:00
|
|
|
{
|
|
|
|
//elog(NOTICE, "line has bbox");
|
2004-04-26 23:05:20 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
2004-08-23 08:32:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//elog(NOTICE, "line has NO bbox");
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2004-08-23 08:32:14 +00:00
|
|
|
//elog(NOTICE, "line has srid");
|
2004-04-26 23:05:20 +00:00
|
|
|
result->SRID = get_int32(loc);
|
|
|
|
loc +=4; // type + SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-23 08:32:14 +00:00
|
|
|
//elog(NOTICE, "line has NO srid");
|
2004-03-09 17:29:52 +00:00
|
|
|
result->SRID = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we've read the type (1 byte) and SRID (4 bytes, if present)
|
|
|
|
|
|
|
|
npoints = get_uint32(loc);
|
2004-08-23 08:32:14 +00:00
|
|
|
//elog(NOTICE, "line npoints = %d", npoints);
|
2004-03-09 17:29:52 +00:00
|
|
|
loc +=4;
|
2004-04-02 19:03:06 +00:00
|
|
|
pa = pointArray_construct( loc, lwgeom_ndims(type), npoints);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
result->points = pa;
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims = lwgeom_ndims(type);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert this line into its serialize form
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
char *lwline_serialize(LWLINE *line)
|
|
|
|
{
|
|
|
|
int size=1; // type byte
|
|
|
|
char hasSRID;
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char * result;
|
2004-03-09 17:29:52 +00:00
|
|
|
int t;
|
|
|
|
char *loc;
|
|
|
|
|
2004-03-11 01:27:43 +00:00
|
|
|
if (line == NULL)
|
|
|
|
elog(ERROR,"lwline_serialize:: given null line");
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
hasSRID = (line->SRID != -1);
|
|
|
|
|
|
|
|
if (hasSRID)
|
|
|
|
size +=4; //4 byte SRID
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
if (line->ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
size += 24 * line->points->npoints; //x,y,z
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (line->ndims == 2)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-03-11 00:54:37 +00:00
|
|
|
size += 16 * line->points->npoints; //x,y
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (line->ndims == 4)
|
|
|
|
{
|
|
|
|
size += 32 * line->points->npoints; //x,y
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-03-11 01:27:43 +00:00
|
|
|
size+=4; // npoints
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
result = palloc(size);
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result[0] = (unsigned char) lwgeom_makeType(line->ndims,hasSRID, LINETYPE);
|
2004-03-09 17:29:52 +00:00
|
|
|
loc = result+1;
|
|
|
|
|
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &line->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
memcpy(loc, &line->points->npoints, sizeof(int32));
|
|
|
|
loc +=4;
|
2004-03-09 17:29:52 +00:00
|
|
|
//copy in points
|
|
|
|
|
2004-04-06 22:58:11 +00:00
|
|
|
//elog(NOTICE," line serialize - size = %i", size);
|
2004-03-11 01:27:43 +00:00
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
if (line->ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint3d_p(line->points, t, loc);
|
|
|
|
loc += 24; // size of a 3d point
|
|
|
|
}
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (line->ndims == 2)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint2d_p(line->points, t, loc);
|
|
|
|
loc += 16; // size of a 2d point
|
|
|
|
}
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (line->ndims == 4)
|
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint4d_p(line->points, t, loc);
|
|
|
|
loc += 32; // size of a 2d point
|
|
|
|
}
|
|
|
|
}
|
2004-03-11 01:27:43 +00:00
|
|
|
//printBYTES((unsigned char *)result, size);
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
// convert this line into its serialize form writing it into
|
|
|
|
// the given buffer, and returning number of bytes written into
|
|
|
|
// the given int pointer.
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize)
|
|
|
|
{
|
|
|
|
int size=1; // type byte
|
|
|
|
char hasSRID;
|
|
|
|
int t;
|
|
|
|
char *loc;
|
|
|
|
|
|
|
|
if (line == NULL)
|
|
|
|
elog(ERROR,"lwline_serialize:: given null line");
|
|
|
|
|
|
|
|
hasSRID = (line->SRID != -1);
|
|
|
|
|
|
|
|
if (hasSRID) size +=4; //4 byte SRID
|
|
|
|
|
|
|
|
if (line->ndims == 3)
|
|
|
|
{
|
|
|
|
size += 24 * line->points->npoints; //x,y,z
|
|
|
|
}
|
|
|
|
else if (line->ndims == 2)
|
|
|
|
{
|
|
|
|
size += 16 * line->points->npoints; //x,y
|
|
|
|
}
|
|
|
|
else if (line->ndims == 4)
|
|
|
|
{
|
|
|
|
size += 32 * line->points->npoints; //x,y
|
|
|
|
}
|
|
|
|
|
|
|
|
size+=4; // npoints
|
|
|
|
|
|
|
|
buf[0] = (unsigned char) lwgeom_makeType(line->ndims,
|
|
|
|
hasSRID, LINETYPE);
|
|
|
|
loc = buf+1;
|
|
|
|
|
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &line->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(loc, &line->points->npoints, sizeof(int32));
|
|
|
|
loc +=4;
|
|
|
|
//copy in points
|
|
|
|
|
|
|
|
//elog(NOTICE," line serialize - size = %i", size);
|
|
|
|
|
|
|
|
if (line->ndims == 3)
|
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint3d_p(line->points, t, loc);
|
|
|
|
loc += 24; // size of a 3d point
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (line->ndims == 2)
|
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint2d_p(line->points, t, loc);
|
|
|
|
loc += 16; // size of a 2d point
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (line->ndims == 4)
|
|
|
|
{
|
|
|
|
for (t=0; t< line->points->npoints;t++)
|
|
|
|
{
|
|
|
|
getPoint4d_p(line->points, t, loc);
|
|
|
|
loc += 32; // size of a 2d point
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//printBYTES((unsigned char *)result, size);
|
|
|
|
|
|
|
|
*retsize = size;
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
|
|
|
BOX3D *lwline_findbbox(LWLINE *line)
|
|
|
|
{
|
|
|
|
if (line == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return pointArray_bbox(line->points);
|
|
|
|
}
|
|
|
|
|
|
|
|
//find length of this serialized line
|
|
|
|
uint32 lwline_findlength(char *serialized_line)
|
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
int type = (unsigned char) serialized_line[0];
|
|
|
|
uint32 result =1; //type
|
|
|
|
char *loc;
|
|
|
|
uint32 npoints;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if ( lwgeom_getType(type) != LINETYPE)
|
|
|
|
elog(ERROR,"lwline_findlength::attempt to find the length of a non-line");
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_line+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
loc += 4; // type + SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
result +=4;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we've read the type (1 byte) and SRID (4 bytes, if present)
|
|
|
|
|
|
|
|
npoints = get_uint32(loc);
|
2004-03-11 00:54:37 +00:00
|
|
|
result += 4; //npoints
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
if (lwgeom_ndims(type) ==3)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
return result + npoints * 24;
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (lwgeom_ndims(type) ==2)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
return result+ npoints * 16;
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (lwgeom_ndims(type) ==4)
|
|
|
|
{
|
|
|
|
return result+ npoints * 32;
|
|
|
|
}
|
2004-04-06 22:58:11 +00:00
|
|
|
elog(ERROR,"lwline_findlength :: invalid ndims");
|
2004-04-02 19:03:06 +00:00
|
|
|
return 0; //never get here
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//********************************************************************
|
|
|
|
// support for the LWPOINT sub-type
|
|
|
|
|
|
|
|
// construct a new point. point will not be copied
|
|
|
|
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
2004-04-02 19:03:06 +00:00
|
|
|
LWPOINT *lwpoint_construct(int ndims, int SRID, POINTARRAY *point)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
LWPOINT *result ;
|
|
|
|
|
|
|
|
if (point == NULL)
|
|
|
|
return NULL; // error
|
|
|
|
|
|
|
|
result = palloc(sizeof(LWPOINT));
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims = ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
result->SRID = SRID;
|
|
|
|
|
2004-03-10 01:15:06 +00:00
|
|
|
result->point = point;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// given the LWPOINT serialized form (or a pointer into a muli* one)
|
|
|
|
// construct a proper LWPOINT.
|
|
|
|
// serialized_form should point to the 8bit type format (with type = 1)
|
|
|
|
// See serialized form doc
|
|
|
|
LWPOINT *lwpoint_deserialize(char *serialized_form)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
LWPOINT *result;
|
|
|
|
char *loc = NULL;
|
|
|
|
POINTARRAY *pa;
|
|
|
|
|
|
|
|
result = (LWPOINT*) palloc( sizeof(LWPOINT)) ;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
type = (unsigned char) serialized_form[0];
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
if ( lwgeom_getType(type) != POINTTYPE)
|
|
|
|
return NULL;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
result->SRID = get_int32(loc);
|
|
|
|
loc +=4; // type + SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->SRID = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we've read the type (1 byte) and SRID (4 bytes, if present)
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
pa = pointArray_construct( loc, lwgeom_ndims(type), 1);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
result->point = pa;
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims = lwgeom_ndims(type);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
// convert this point into its serialize form
|
2004-03-09 17:29:52 +00:00
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
char *lwpoint_serialize(LWPOINT *point)
|
|
|
|
{
|
2004-08-25 12:29:31 +00:00
|
|
|
int size=1;
|
|
|
|
char hasSRID;
|
|
|
|
char * result;
|
|
|
|
char *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
hasSRID = (point->SRID != -1);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
if (hasSRID) size +=4; //4 byte SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
if (point->ndims == 3) size += 24; //x,y,z
|
|
|
|
else if (point->ndims == 2) size += 16 ; //x,y,z
|
|
|
|
else if (point->ndims == 4) size += 32 ; //x,y,z,m
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
result = palloc(size);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
result[0] = (unsigned char) lwgeom_makeType(point->ndims,
|
|
|
|
hasSRID, POINTTYPE);
|
|
|
|
loc = result+1;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &point->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
//copy in points
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
if (point->ndims == 3) getPoint3d_p(point->point, 0, loc);
|
|
|
|
else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc);
|
|
|
|
else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc);
|
|
|
|
return result;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
// convert this point into its serialize form writing it into
|
|
|
|
// the given buffer, and returning number of bytes written into
|
|
|
|
// the given int pointer.
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
void lwpoint_serialize_buf(LWPOINT *point, char *buf, int *retsize)
|
|
|
|
{
|
|
|
|
int size=1;
|
|
|
|
char hasSRID;
|
|
|
|
char *loc;
|
2004-04-02 19:03:06 +00:00
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
hasSRID = (point->SRID != -1);
|
|
|
|
|
|
|
|
if (hasSRID) size +=4; //4 byte SRID
|
|
|
|
|
|
|
|
if (point->ndims == 3) size += 24; //x,y,z
|
|
|
|
else if (point->ndims == 2) size += 16 ; //x,y,z
|
|
|
|
else if (point->ndims == 4) size += 32 ; //x,y,z,m
|
|
|
|
|
|
|
|
buf[0] = (unsigned char) lwgeom_makeType(point->ndims,
|
|
|
|
hasSRID, POINTTYPE);
|
|
|
|
loc = buf+1;
|
|
|
|
|
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &point->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
//copy in points
|
|
|
|
|
|
|
|
if (point->ndims == 3) getPoint3d_p(point->point, 0, loc);
|
|
|
|
else if (point->ndims == 2) getPoint2d_p(point->point, 0, loc);
|
|
|
|
else if (point->ndims == 4) getPoint4d_p(point->point, 0, loc);
|
|
|
|
|
|
|
|
*retsize = size;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
|
|
|
BOX3D *lwpoint_findbbox(LWPOINT *point)
|
|
|
|
{
|
|
|
|
if (point == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return pointArray_bbox(point->point);
|
|
|
|
}
|
|
|
|
|
|
|
|
// convenience functions to hide the POINTARRAY
|
|
|
|
POINT2D lwpoint_getPoint2d(LWPOINT *point)
|
|
|
|
{
|
|
|
|
POINT2D result;
|
|
|
|
|
|
|
|
if (point == NULL)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
return getPoint2d(point->point,0);
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// convenience functions to hide the POINTARRAY
|
2004-03-09 17:29:52 +00:00
|
|
|
POINT3D lwpoint_getPoint3d(LWPOINT *point)
|
|
|
|
{
|
|
|
|
POINT3D result;
|
|
|
|
|
|
|
|
if (point == NULL)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
return getPoint3d(point->point,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//find length of this serialized point
|
|
|
|
uint32 lwpoint_findlength(char *serialized_point)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
uint result = 1;
|
|
|
|
unsigned char type;
|
|
|
|
char *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = (unsigned char) serialized_point[0];
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
if ( lwgeom_getType(type) != POINTTYPE) return 0;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength called (%d)", result);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
loc = serialized_point+1;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength: has bbox (%d)", result);
|
|
|
|
#endif
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength: has srid (%d)", result);
|
|
|
|
#endif
|
|
|
|
loc +=4; // type + SRID
|
|
|
|
result +=4;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (lwgeom_ndims(type) == 3)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength: returning (%d)", result+24);
|
|
|
|
#endif
|
|
|
|
return result + 24;
|
|
|
|
}
|
|
|
|
else if (lwgeom_ndims(type) == 2)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength: returning (%d)", result+16);
|
|
|
|
#endif
|
|
|
|
return result + 16;
|
|
|
|
}
|
|
|
|
else if (lwgeom_ndims(type) == 4)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoint_findlength: returning (%d)", result+32);
|
|
|
|
#endif
|
|
|
|
return result + 32;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
elog(ERROR,"lwpoint_findlength :: invalid ndims = %i",
|
|
|
|
lwgeom_ndims(type));
|
|
|
|
return 0; //never get here
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//********************************************************************
|
|
|
|
// basic polygon manipulation
|
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
// construct a new LWPOLY. arrays (points/points per ring) will NOT be copied
|
2004-03-09 17:29:52 +00:00
|
|
|
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
2004-04-02 19:03:06 +00:00
|
|
|
LWPOLY *lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
LWPOLY *result;
|
|
|
|
|
|
|
|
result = (LWPOLY*) palloc(sizeof(LWPOLY));
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims = ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
result->SRID = SRID;
|
|
|
|
result->nrings = nrings;
|
|
|
|
result->rings = points;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// given the LWPOLY serialized form (or a pointer into a muli* one)
|
|
|
|
// construct a proper LWPOLY.
|
|
|
|
// serialized_form should point to the 8bit type format (with type = 3)
|
|
|
|
// See serialized form doc
|
|
|
|
LWPOLY *lwpoly_deserialize(char *serialized_form)
|
|
|
|
{
|
|
|
|
|
|
|
|
LWPOLY *result;
|
|
|
|
uint32 nrings;
|
2004-04-02 19:03:06 +00:00
|
|
|
int ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
uint32 npoints;
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
char *loc;
|
|
|
|
int t;
|
|
|
|
|
|
|
|
if (serialized_form == NULL)
|
2004-08-27 14:35:26 +00:00
|
|
|
{
|
|
|
|
elog(ERROR, "lwpoly_deserialize called with NULL arg");
|
2004-03-09 17:29:52 +00:00
|
|
|
return NULL;
|
2004-08-27 14:35:26 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
result = (LWPOLY*) palloc(sizeof(LWPOLY));
|
|
|
|
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
type = (unsigned char) serialized_form[0];
|
2004-04-02 19:03:06 +00:00
|
|
|
ndims = lwgeom_ndims(type);
|
2004-03-09 17:29:52 +00:00
|
|
|
loc = serialized_form;
|
|
|
|
|
|
|
|
if ( lwgeom_getType(type) != POLYGONTYPE)
|
2004-08-27 14:35:26 +00:00
|
|
|
{
|
|
|
|
elog(ERROR, "lwpoly_deserialize called with arg of type %d",
|
|
|
|
lwgeom_getType(type));
|
2004-03-09 17:29:52 +00:00
|
|
|
return NULL;
|
2004-08-27 14:35:26 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
result->SRID = get_int32(loc);
|
|
|
|
loc +=4; // type + SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->SRID = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nrings = get_uint32(loc);
|
2004-03-11 00:54:37 +00:00
|
|
|
result->nrings = nrings;
|
2004-03-09 17:29:52 +00:00
|
|
|
loc +=4;
|
|
|
|
result->rings = (POINTARRAY**) palloc(nrings* sizeof(POINTARRAY*));
|
|
|
|
|
|
|
|
for (t =0;t<nrings;t++)
|
|
|
|
{
|
|
|
|
//read in a single ring and make a PA
|
|
|
|
npoints = get_uint32(loc);
|
|
|
|
loc +=4;
|
|
|
|
|
2004-04-02 19:03:06 +00:00
|
|
|
result->rings[t] = pointArray_construct(loc, ndims, npoints);
|
|
|
|
if (ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
loc += 24*npoints;
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (ndims == 2)
|
2004-03-09 17:29:52 +00:00
|
|
|
loc += 16*npoints;
|
2004-04-02 19:03:06 +00:00
|
|
|
else if (ndims == 4)
|
|
|
|
loc += 32*npoints;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
result->ndims = ndims;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the serialized form of the polygon
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
// points copied
|
|
|
|
char *lwpoly_serialize(LWPOLY *poly)
|
|
|
|
{
|
2004-09-06 09:13:13 +00:00
|
|
|
int size=1; // type byte
|
|
|
|
char hasSRID;
|
|
|
|
char *result;
|
|
|
|
int t,u;
|
|
|
|
int total_points = 0;
|
|
|
|
int npoints;
|
|
|
|
char *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
hasSRID = (poly->SRID != -1);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
if (hasSRID)
|
|
|
|
size +=4; //4 byte SRID
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
size += 4; // nrings
|
|
|
|
size += 4*poly->nrings; //npoints/ring
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
total_points += poly->rings[t]->npoints;
|
|
|
|
}
|
|
|
|
if (poly->ndims == 3)
|
|
|
|
size += 24*total_points;
|
|
|
|
else if (poly->ndims == 2)
|
|
|
|
size += 16*total_points;
|
|
|
|
else if (poly->ndims == 4)
|
|
|
|
size += 32*total_points;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
result = palloc(size);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
result[0] = (unsigned char) lwgeom_makeType(poly->ndims,hasSRID, POLYGONTYPE);
|
|
|
|
loc = result+1;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &poly->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
memcpy(loc, &poly->nrings, sizeof(int32)); // nrings
|
|
|
|
loc+=4;
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
POINTARRAY *pa = poly->rings[t];
|
|
|
|
npoints = poly->rings[t]->npoints;
|
|
|
|
memcpy(loc, &npoints, sizeof(int32)); //npoints this ring
|
|
|
|
loc+=4;
|
|
|
|
if (poly->ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-06 09:13:13 +00:00
|
|
|
for (u=0;u<npoints;u++)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-06 09:13:13 +00:00
|
|
|
getPoint3d_p(pa, u, loc);
|
|
|
|
loc+= 24;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-09-06 09:13:13 +00:00
|
|
|
}
|
|
|
|
else if (poly->ndims == 2)
|
|
|
|
{
|
|
|
|
for (u=0;u<npoints;u++)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-06 09:13:13 +00:00
|
|
|
getPoint2d_p(pa, u, loc);
|
|
|
|
loc+= 16;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-09-06 09:13:13 +00:00
|
|
|
}
|
|
|
|
else if (poly->ndims == 4)
|
|
|
|
{
|
|
|
|
for (u=0;u<npoints;u++)
|
2004-04-02 19:03:06 +00:00
|
|
|
{
|
2004-09-06 09:13:13 +00:00
|
|
|
getPoint4d_p(pa, u, loc);
|
|
|
|
loc+= 32;
|
2004-04-02 19:03:06 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-09-06 09:13:13 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-06 09:13:13 +00:00
|
|
|
return result;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 12:29:31 +00:00
|
|
|
// create the serialized form of the polygon writing it into the
|
|
|
|
// given buffer, and returning number of bytes written into
|
|
|
|
// the given int pointer.
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
// points copied
|
|
|
|
void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *retsize)
|
|
|
|
{
|
|
|
|
int size=1; // type byte
|
|
|
|
char hasSRID;
|
|
|
|
int t,u;
|
|
|
|
int total_points = 0;
|
|
|
|
int npoints;
|
|
|
|
char *loc;
|
|
|
|
|
|
|
|
hasSRID = (poly->SRID != -1);
|
|
|
|
|
|
|
|
if (hasSRID) size +=4; //4 byte SRID
|
|
|
|
|
|
|
|
size += 4; // nrings
|
|
|
|
size += 4*poly->nrings; //npoints/ring
|
|
|
|
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
total_points += poly->rings[t]->npoints;
|
|
|
|
}
|
|
|
|
if (poly->ndims == 3) size += 24*total_points;
|
|
|
|
else if (poly->ndims == 2) size += 16*total_points;
|
|
|
|
else if (poly->ndims == 4) size += 32*total_points;
|
|
|
|
|
|
|
|
buf[0] = (unsigned char) lwgeom_makeType(poly->ndims,
|
|
|
|
hasSRID, POLYGONTYPE);
|
|
|
|
loc = buf+1;
|
|
|
|
|
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &poly->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(loc, &poly->nrings, sizeof(int32)); // nrings
|
|
|
|
loc+=4;
|
|
|
|
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
POINTARRAY *pa = poly->rings[t];
|
|
|
|
npoints = poly->rings[t]->npoints;
|
|
|
|
memcpy(loc, &npoints, sizeof(int32)); //npoints this ring
|
|
|
|
loc+=4;
|
|
|
|
if (poly->ndims == 3)
|
|
|
|
{
|
|
|
|
for (u=0;u<npoints;u++)
|
|
|
|
{
|
|
|
|
getPoint3d_p(pa, u, loc);
|
|
|
|
loc+= 24;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (poly->ndims == 2)
|
|
|
|
{
|
|
|
|
for (u=0;u<npoints;u++)
|
|
|
|
{
|
|
|
|
getPoint2d_p(pa, u, loc);
|
|
|
|
loc+= 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (poly->ndims == 4)
|
|
|
|
{
|
|
|
|
for (u=0;u<npoints;u++)
|
|
|
|
{
|
|
|
|
getPoint4d_p(pa, u, loc);
|
|
|
|
loc+= 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*retsize = size;
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
|
|
|
BOX3D *lwpoly_findbbox(LWPOLY *poly)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
// int t;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
BOX3D *result;
|
|
|
|
// BOX3D *abox,*abox2;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
POINTARRAY *pa = poly->rings[0]; // just need to check outer ring -- interior rings are inside
|
2004-03-09 17:29:52 +00:00
|
|
|
result = pointArray_bbox(pa);
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
// for (t=1;t<poly->nrings;t++)
|
|
|
|
//{
|
|
|
|
// pa = poly->rings[t];
|
|
|
|
// abox = pointArray_bbox(pa);
|
|
|
|
// abox2 = result;
|
|
|
|
// result = combine_boxes( abox, abox2);
|
|
|
|
// pfree(abox);
|
|
|
|
// pfree(abox2);
|
|
|
|
// }
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//find length of this serialized polygon
|
|
|
|
uint32 lwpoly_findlength(char *serialized_poly)
|
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
uint32 result = 1; // char type
|
|
|
|
uint32 nrings;
|
|
|
|
int ndims;
|
|
|
|
int t;
|
|
|
|
unsigned char type;
|
|
|
|
uint32 npoints;
|
|
|
|
char *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if (serialized_poly == NULL)
|
|
|
|
return -9999;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
type = (unsigned char) serialized_poly[0];
|
|
|
|
ndims = lwgeom_ndims(type);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if ( lwgeom_getType(type) != POLYGONTYPE)
|
|
|
|
return -9999;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_poly+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoly_findlength: has bbox");
|
|
|
|
#endif
|
2004-04-26 23:05:20 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwpoly_findlength: has srid");
|
|
|
|
#endif
|
|
|
|
loc +=4; // type + SRID
|
|
|
|
result += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nrings = get_uint32(loc);
|
|
|
|
loc +=4;
|
|
|
|
result +=4;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
for (t =0;t<nrings;t++)
|
|
|
|
{
|
|
|
|
//read in a single ring and make a PA
|
|
|
|
npoints = get_uint32(loc);
|
2004-03-09 17:29:52 +00:00
|
|
|
loc +=4;
|
|
|
|
result +=4;
|
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if (ndims == 3)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
loc += 24*npoints;
|
|
|
|
result += 24*npoints;
|
|
|
|
}
|
|
|
|
else if (ndims == 2)
|
|
|
|
{
|
|
|
|
loc += 16*npoints;
|
|
|
|
result += 16*npoints;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-08-23 10:49:08 +00:00
|
|
|
else if (ndims == 4)
|
|
|
|
{
|
|
|
|
loc += 32*npoints;
|
|
|
|
result += 32*npoints;
|
|
|
|
}
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*************************************************************************
|
|
|
|
// multi-geometry support
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// note - for a simple type (ie. point), this will have sub_geom[0] = serialized_form.
|
|
|
|
// for multi-geomtries sub_geom[0] will be a few bytes into the serialized form
|
|
|
|
// This function just computes the length of each sub-object and pre-caches this info.
|
|
|
|
// For a geometry collection of multi* geometries, you can inspect the sub-components
|
|
|
|
// as well.
|
|
|
|
LWGEOM_INSPECTED *lwgeom_inspect(char *serialized_form)
|
|
|
|
{
|
|
|
|
LWGEOM_INSPECTED *result = palloc(sizeof(LWGEOM_INSPECTED));
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
char **sub_geoms;
|
|
|
|
char *loc;
|
|
|
|
int t;
|
|
|
|
|
|
|
|
if (serialized_form == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result->serialized_form = serialized_form;
|
2004-04-26 23:05:20 +00:00
|
|
|
result->type = (unsigned char) serialized_form[0];
|
2004-08-23 08:32:14 +00:00
|
|
|
result->SRID = -1; // assume
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
type = lwgeom_getType( (unsigned char) serialized_form[0]);
|
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) )
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 08:32:14 +00:00
|
|
|
result->SRID = get_int32(loc);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
//simple geometry (point/line/polygon)-- not multi!
|
|
|
|
result->ngeometries = 1;
|
|
|
|
sub_geoms = (char**) palloc(sizeof(char*));
|
|
|
|
sub_geoms[0] = serialized_form;
|
|
|
|
result->sub_geoms = sub_geoms;
|
2004-08-23 10:49:08 +00:00
|
|
|
return result;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-08-23 10:49:08 +00:00
|
|
|
|
|
|
|
// its a GeometryCollection or multi* geometry
|
|
|
|
|
|
|
|
if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
result->SRID= get_int32(loc);
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->ngeometries = get_uint32(loc);
|
|
|
|
loc +=4;
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_inspect: geometry is a collection of %d elements",
|
|
|
|
result->ngeometries);
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
if ( ! result->ngeometries ) return result;
|
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries );
|
|
|
|
result->sub_geoms = sub_geoms;
|
|
|
|
sub_geoms[0] = loc;
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "subgeom[0] @ %i", sub_geoms[0]);
|
|
|
|
#endif
|
|
|
|
for (t=1;t<result->ngeometries; t++)
|
|
|
|
{
|
|
|
|
int sub_length = lwgeom_seralizedformlength(sub_geoms[t-1], -1);//-1 = entire object
|
|
|
|
sub_geoms[t] = sub_geoms[t-1] + sub_length;
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "subgeom[%d] @ %i (sub_length: %d)",
|
|
|
|
t, sub_geoms[t], sub_length);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-08-23 08:32:14 +00:00
|
|
|
return result;
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a point (with geom_num=0), multipoint or geometrycollection
|
|
|
|
LWPOINT *lwgeom_getpoint(char *serialized_form, int geom_number)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
char type = lwgeom_getType((unsigned char)serialized_form[0]);
|
2004-03-09 17:29:52 +00:00
|
|
|
char *sub_geom;
|
|
|
|
|
|
|
|
if ((type == POINTTYPE) && (geom_number == 0))
|
|
|
|
{
|
|
|
|
//be nice and do as they want instead of what they say
|
|
|
|
return lwpoint_deserialize(serialized_form);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((type != MULTIPOINTTYPE) && (type != COLLECTIONTYPE) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
|
|
|
|
if (sub_geom == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
type = lwgeom_getType( (unsigned char) sub_geom[0]);
|
2004-03-09 17:29:52 +00:00
|
|
|
if (type != POINTTYPE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return lwpoint_deserialize(sub_geom);
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual sub-geometry isnt a POINT, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a point (with geom_num=0), multipoint or geometrycollection
|
2004-03-09 17:29:52 +00:00
|
|
|
LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
char *sub_geom;
|
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (sub_geom == NULL) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = lwgeom_getType( (unsigned char) sub_geom[0]);
|
|
|
|
if (type != POINTTYPE) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
return lwpoint_deserialize(sub_geom);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual geometry isnt a LINE, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a line, multiline or geometrycollection
|
|
|
|
LWLINE *lwgeom_getline(char *serialized_form, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
unsigned char type = lwgeom_getType( (unsigned char) serialized_form[0]);
|
|
|
|
char *sub_geom;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ((type == LINETYPE) && (geom_number == 0))
|
|
|
|
{
|
|
|
|
//be nice and do as they want instead of what they say
|
|
|
|
return lwline_deserialize(serialized_form);
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ((type != MULTILINETYPE) && (type != COLLECTIONTYPE) )
|
|
|
|
return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
|
|
|
|
if (sub_geom == NULL) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = lwgeom_getType((unsigned char) sub_geom[0]);
|
|
|
|
if (type != LINETYPE) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return lwline_deserialize(sub_geom);
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual geometry isnt a LINE, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a line, multiline or geometrycollection
|
2004-03-09 17:29:52 +00:00
|
|
|
LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
char *sub_geom;
|
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (sub_geom == NULL) return NULL;
|
2004-04-06 22:58:11 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = lwgeom_getType((unsigned char) sub_geom[0]);
|
|
|
|
if (type != LINETYPE) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
return lwline_deserialize(sub_geom);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a polygon, multipolygon or geometrycollection
|
|
|
|
LWPOLY *lwgeom_getpoly(char *serialized_form, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
unsigned char type = lwgeom_getType((unsigned char)serialized_form[0]);
|
|
|
|
char *sub_geom;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ((type == POLYGONTYPE) && (geom_number == 0))
|
|
|
|
{
|
|
|
|
//be nice and do as they want instead of what they say
|
|
|
|
return lwpoly_deserialize(serialized_form);
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ((type != MULTIPOLYGONTYPE) && (type != COLLECTIONTYPE) )
|
|
|
|
return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
sub_geom = lwgeom_getsubgeometry(serialized_form, geom_number);
|
|
|
|
if (sub_geom == NULL) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = lwgeom_getType((unsigned char) sub_geom[0]);
|
|
|
|
if (type != POLYGONTYPE) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
return lwpoly_deserialize(sub_geom);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if the actual geometry isnt a POLYGON, null is returned (see _gettype()).
|
|
|
|
// if there arent enough geometries, return null.
|
|
|
|
// this is fine to call on a polygon, multipolygon or geometrycollection
|
2004-03-09 17:29:52 +00:00
|
|
|
LWPOLY *lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
char *sub_geom;
|
|
|
|
unsigned char type;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (sub_geom == NULL) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
type = lwgeom_getType((unsigned char) sub_geom[0]);
|
|
|
|
if (type != POLYGONTYPE) return NULL;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
return lwpoly_deserialize(sub_geom);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// this gets the serialized form of a sub-geometry
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// if this isnt a multi* geometry, and geom_number ==0 then it returns
|
|
|
|
// itself
|
|
|
|
// returns null on problems.
|
|
|
|
// in the future this is how you would access a muli* portion of a
|
|
|
|
// geometry collection.
|
|
|
|
// GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), LINESTRING(0 0, 1 1))
|
|
|
|
// ie. lwgeom_getpoint( lwgeom_getsubgeometry( serialized, 0), 1)
|
|
|
|
// --> POINT(1 1)
|
|
|
|
// you can inspect the sub-geometry as well if you wish.
|
|
|
|
char *lwgeom_getsubgeometry(char *serialized_form, int geom_number)
|
|
|
|
{
|
|
|
|
//major cheat!!
|
|
|
|
char * result;
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
|
|
|
|
|
|
|
|
result = lwgeom_getsubgeometry_inspected(inspected, geom_number);
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
|
|
|
if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return inspected->sub_geoms[geom_number];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// use geom_number = -1 to find the actual type of the serialized form.
|
|
|
|
// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
|
|
|
|
// --> multipoint
|
|
|
|
// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
|
|
|
|
// --> point
|
|
|
|
// gets the 8bit type of the geometry at location geom_number
|
|
|
|
char lwgeom_getsubtype(char *serialized_form, int geom_number)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
//major cheat!!
|
|
|
|
char result;
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
result = lwgeom_getsubtype_inspected(inspected, geom_number);
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
return result;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-08-24 13:35:51 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
char lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
2004-08-23 08:32:14 +00:00
|
|
|
if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
|
|
|
|
return 99;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 08:32:14 +00:00
|
|
|
return inspected->sub_geoms[geom_number][0]; // 1st byte is type
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// how many sub-geometries are there?
|
|
|
|
// for point,line,polygon will return 1.
|
|
|
|
int lwgeom_getnumgeometries(char *serialized_form)
|
|
|
|
{
|
2004-08-24 13:35:51 +00:00
|
|
|
unsigned char type = lwgeom_getType((unsigned char)serialized_form[0]);
|
|
|
|
char *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) )
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
|
|
|
|
{
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
//its a GeometryCollection or multi* geometry
|
|
|
|
return get_uint32(loc);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// how many sub-geometries are there?
|
|
|
|
// for point,line,polygon will return 1.
|
2004-03-09 17:29:52 +00:00
|
|
|
int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected)
|
|
|
|
{
|
|
|
|
return inspected->ngeometries;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// set finalType to COLLECTIONTYPE or 0 (0 means choose a best type)
|
|
|
|
// (ie. give it 2 points and ask it to be a multipoint)
|
|
|
|
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
|
|
|
// all subgeometries must have the same SRID
|
|
|
|
// if you want to construct an inspected, call this then inspect the result...
|
2004-04-02 19:03:06 +00:00
|
|
|
extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometries, char **serialized_subs)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
uint32 *lengths;
|
|
|
|
int t;
|
|
|
|
int total_length = 0;
|
|
|
|
char type = -1;
|
|
|
|
char this_type = -1;
|
|
|
|
char *result;
|
|
|
|
char *loc;
|
|
|
|
|
|
|
|
if (nsubgeometries == 0)
|
2004-04-02 19:03:06 +00:00
|
|
|
return lwgeom_constructempty(SRID,ndims);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
lengths = palloc(sizeof(int32) * nsubgeometries);
|
|
|
|
|
|
|
|
for (t=0;t<nsubgeometries;t++)
|
|
|
|
{
|
|
|
|
lengths[t] = lwgeom_seralizedformlength(serialized_subs[t],-1);
|
|
|
|
total_length += lengths[t];
|
2004-04-26 23:05:20 +00:00
|
|
|
this_type = lwgeom_getType((unsigned char) (serialized_subs[t][0]));
|
2004-03-09 17:29:52 +00:00
|
|
|
if (type == -1)
|
|
|
|
{
|
|
|
|
type = this_type;
|
|
|
|
}
|
|
|
|
else if (type == COLLECTIONTYPE)
|
|
|
|
{
|
|
|
|
//still a collection type...
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( (this_type == MULTIPOINTTYPE) || (this_type == MULTILINETYPE) || (this_type == MULTIPOLYGONTYPE) || (this_type == COLLECTIONTYPE) )
|
|
|
|
{
|
|
|
|
type = COLLECTIONTYPE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( (this_type == POINTTYPE) && (type==POINTTYPE) )
|
|
|
|
type=MULTIPOINTTYPE;
|
|
|
|
else if ( (this_type == LINETYPE) && (type==LINETYPE) )
|
|
|
|
type=MULTILINETYPE;
|
|
|
|
else if ( (this_type == POLYGONTYPE) && (type==POLYGONTYPE) )
|
|
|
|
type=MULTIPOLYGONTYPE;
|
|
|
|
else if ( (this_type == POLYGONTYPE) && (type==MULTIPOLYGONTYPE) )
|
|
|
|
;//nop
|
|
|
|
else if ( (this_type == LINETYPE) && (type==MULTILINETYPE) )
|
|
|
|
;//nop
|
|
|
|
else if ( (this_type == POINTTYPE) && (type==MULTIPOINTTYPE) )
|
|
|
|
;//nop
|
|
|
|
else
|
|
|
|
type = COLLECTIONTYPE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == POINTTYPE)
|
|
|
|
type = MULTIPOINTTYPE;
|
|
|
|
if (type == LINETYPE)
|
|
|
|
type = MULTILINETYPE;
|
|
|
|
if (type == POINTTYPE)
|
|
|
|
type = MULTIPOINTTYPE;
|
|
|
|
|
|
|
|
if (finalType == COLLECTIONTYPE)
|
|
|
|
type = COLLECTIONTYPE;
|
|
|
|
|
|
|
|
// now we have a mutli* or GEOMETRYCOLLECTION, lets serialize it
|
|
|
|
|
|
|
|
if (SRID != -1)
|
|
|
|
total_length +=4; // space for SRID
|
|
|
|
|
|
|
|
total_length +=1 ; // main type;
|
|
|
|
total_length +=4 ; // nsubgeometries
|
|
|
|
|
|
|
|
result = palloc(total_length);
|
2004-04-26 23:05:20 +00:00
|
|
|
result[0] = (unsigned char) lwgeom_makeType( ndims, SRID != -1, type);
|
2004-03-09 17:29:52 +00:00
|
|
|
if (SRID != -1)
|
|
|
|
{
|
|
|
|
memcpy(&result[1],&SRID,4);
|
|
|
|
loc = result+5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
loc = result+1;
|
|
|
|
|
|
|
|
memcpy(loc,&nsubgeometries,4);
|
|
|
|
loc +=4;
|
|
|
|
|
|
|
|
for (t=0;t<nsubgeometries;t++)
|
|
|
|
{
|
|
|
|
memcpy(loc, serialized_subs[t], lengths[t] );
|
|
|
|
loc += lengths[t] ;
|
|
|
|
}
|
|
|
|
|
|
|
|
pfree(lengths);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
|
|
|
|
//returns serialized form
|
2004-04-02 19:03:06 +00:00
|
|
|
char *lwgeom_constructempty(int SRID,int ndims)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
int size = 0;
|
|
|
|
char *result;
|
|
|
|
int ngeoms = 0;
|
|
|
|
char *loc;
|
|
|
|
|
|
|
|
if (SRID != -1)
|
|
|
|
size +=4;
|
|
|
|
|
|
|
|
size += 5;
|
|
|
|
|
|
|
|
result = palloc(size);
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
result[0] =(unsigned char) lwgeom_makeType( ndims, SRID != -1, COLLECTIONTYPE);
|
2004-03-09 17:29:52 +00:00
|
|
|
if (SRID != -1)
|
|
|
|
{
|
|
|
|
memcpy(&result[1],&SRID,4);
|
|
|
|
loc = result+5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
loc = result+1;
|
|
|
|
|
|
|
|
memcpy(loc,&ngeoms,4);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// helper function (not for general use)
|
|
|
|
// find the size a geometry (or a sub-geometry)
|
|
|
|
// 1st geometry has geom_number = 0
|
|
|
|
// use geom_number = -1 to find the actual type of the serialized form.
|
|
|
|
// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, -1)
|
|
|
|
// --> size of the multipoint
|
|
|
|
// ie lwgeom_gettype( <'MULTIPOINT(0 0, 1 1)'>, 0)
|
|
|
|
// --> size of the point
|
|
|
|
|
|
|
|
// take a geometry, and find its length
|
|
|
|
int lwgeom_seralizedformlength_simple(char *serialized_form)
|
|
|
|
{
|
2004-04-26 23:05:20 +00:00
|
|
|
unsigned char type = lwgeom_getType((unsigned char) serialized_form[0]);
|
2004-03-09 17:29:52 +00:00
|
|
|
int t;
|
|
|
|
char *loc;
|
|
|
|
uint32 ngeoms;
|
|
|
|
int sub_size;
|
|
|
|
int result = 1; //"type"
|
|
|
|
|
2004-08-24 13:35:51 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple called");
|
|
|
|
#endif
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (type == POINTTYPE)
|
2004-08-23 10:49:08 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple: is a point");
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
return lwpoint_findlength(serialized_form);
|
2004-08-23 10:49:08 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
else if (type == LINETYPE)
|
2004-08-23 10:49:08 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple: is a line");
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
return lwline_findlength(serialized_form);
|
2004-08-23 10:49:08 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
else if (type == POLYGONTYPE)
|
2004-08-23 10:49:08 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple: is a polygon");
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
return lwpoly_findlength(serialized_form);
|
2004-08-23 10:49:08 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
if ( type == 0 )
|
|
|
|
{
|
|
|
|
elog(ERROR, "lwgeom_seralizedformlength_simple called with unknown-typed serialized geometry");
|
|
|
|
return 0;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
//handle all the multi* and geometrycollections the same
|
|
|
|
//NOTE: for a geometry collection of GC of GC of GC we will be recursing...
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with type %d", type);
|
|
|
|
#endif
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple: has bbox");
|
|
|
|
#endif
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
if (lwgeom_hasSRID( (unsigned char) serialized_form[0]) )
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple: has srid");
|
|
|
|
#endif
|
2004-04-26 23:05:20 +00:00
|
|
|
result +=4;
|
|
|
|
loc +=4;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
ngeoms = get_uint32(loc);
|
|
|
|
loc +=4;
|
2004-08-23 10:49:08 +00:00
|
|
|
result += 4; // numgeoms
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
for (t=0;t<ngeoms;t++)
|
|
|
|
{
|
|
|
|
sub_size = lwgeom_seralizedformlength_simple(loc);
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, " subsize %d", sub_size);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
loc += sub_size;
|
|
|
|
result += sub_size;
|
|
|
|
}
|
|
|
|
|
2004-08-23 10:49:08 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_seralizedformlength_simple returning %d", result);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int lwgeom_seralizedformlength(char *serialized_form, int geom_number)
|
|
|
|
{
|
|
|
|
if (geom_number == -1)
|
|
|
|
{
|
|
|
|
return lwgeom_seralizedformlength_simple(serialized_form);
|
|
|
|
}
|
|
|
|
return lwgeom_seralizedformlength_simple( lwgeom_getsubgeometry(serialized_form,geom_number));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int lwgeom_seralizedformlength_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
|
|
|
{
|
|
|
|
return lwgeom_seralizedformlength( inspected->sub_geoms[geom_number], -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//get bounding box of LWGEOM (automatically calls the sub-geometries bbox generators)
|
2004-04-29 18:44:36 +00:00
|
|
|
//dont forget to pfree() result
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX3D *lw_geom_getBB(char *serialized_form)
|
|
|
|
{
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
|
|
|
|
|
|
|
|
BOX3D *result = lw_geom_getBB_inspected(inspected);
|
|
|
|
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//dont forget to pfree() result
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX3D *lw_geom_getBB_simple(char *serialized_form)
|
|
|
|
{
|
2004-08-19 13:16:16 +00:00
|
|
|
char type = lwgeom_getType((unsigned char) serialized_form[0]);
|
|
|
|
int t;
|
|
|
|
char *loc;
|
|
|
|
uint32 ngeoms;
|
|
|
|
BOX3D *result;
|
|
|
|
BOX3D *b1,*b2;
|
|
|
|
int sub_size;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if (type == POINTTYPE)
|
|
|
|
{
|
|
|
|
LWPOINT *pt = lwpoint_deserialize(serialized_form);
|
|
|
|
result = lwpoint_findbbox(pt);
|
|
|
|
pfree_point(pt);
|
|
|
|
return result;
|
|
|
|
/*
|
|
|
|
result = palloc(sizeof(BOX3D));
|
|
|
|
memcpy(result, serialized_form+1, sizeof(BOX2DFLOAT4));
|
|
|
|
memcpy(( (char *)result)+24, serialized_form+1, sizeof(BOX2DFLOAT4));
|
|
|
|
return result;
|
|
|
|
*/
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
else if (type == LINETYPE)
|
|
|
|
{
|
|
|
|
LWLINE *line = lwline_deserialize(serialized_form);
|
|
|
|
result = lwline_findbbox(line);
|
|
|
|
pfree_line(line);
|
|
|
|
return result;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
}
|
|
|
|
else if (type == POLYGONTYPE)
|
|
|
|
{
|
|
|
|
LWPOLY *poly = lwpoly_deserialize(serialized_form);
|
|
|
|
result = lwpoly_findbbox(poly);
|
|
|
|
pfree_polygon(poly);
|
|
|
|
return result;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
loc = serialized_form+1;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-19 13:16:16 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
|
|
|
|
{
|
|
|
|
loc +=4;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
ngeoms = get_uint32(loc);
|
|
|
|
loc +=4;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
result = NULL;
|
|
|
|
// each sub-type
|
|
|
|
for (t=0;t<ngeoms;t++)
|
|
|
|
{
|
|
|
|
b1 = lw_geom_getBB_simple(loc);
|
|
|
|
sub_size = lwgeom_seralizedformlength_simple(loc);
|
|
|
|
loc += sub_size;
|
|
|
|
if (result != NULL)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-19 13:16:16 +00:00
|
|
|
b2= result;
|
|
|
|
result = combine_boxes(b2, b1);
|
|
|
|
pfree(b1);
|
|
|
|
pfree(b2);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-08-19 13:16:16 +00:00
|
|
|
else
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-19 13:16:16 +00:00
|
|
|
result = b1;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-08-19 13:16:16 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
//dont forget to pfree() result
|
2004-03-09 17:29:52 +00:00
|
|
|
BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
BOX3D *b1,*b2,*result;
|
|
|
|
|
|
|
|
result = NULL;
|
|
|
|
|
|
|
|
//handle all the multi* and geometrycollections the same
|
|
|
|
//NOTE: for a geometry collection of GC of GC of GC we will be recursing...
|
|
|
|
for (t=0;t<inspected->ngeometries;t++)
|
|
|
|
{
|
|
|
|
b1 = lw_geom_getBB_simple( inspected->sub_geoms[t] );
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
// elog(NOTICE,"%i has box :: BBOX3D(%g %g, %g %g)",t,b1->xmin, b1->ymin,b1->xmax, b1->ymax);
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (result != NULL)
|
|
|
|
{
|
|
|
|
b2= result;
|
|
|
|
result = combine_boxes(b2, b1);
|
2004-04-26 23:05:20 +00:00
|
|
|
// elog(NOTICE,"combined has :: BBOX3D(%g %g, %g %g)",result->xmin, result->ymin,result->xmax, result->ymax);
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
pfree(b1);
|
|
|
|
pfree(b2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = b1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************
|
|
|
|
// memory management -- these only delete the memory associated
|
|
|
|
// directly with the structure - NOT the stuff pointing into
|
|
|
|
// the original de-serialized info
|
|
|
|
|
|
|
|
void pfree_inspected(LWGEOM_INSPECTED *inspected)
|
|
|
|
{
|
2004-08-27 14:35:26 +00:00
|
|
|
if ( inspected->ngeometries )
|
|
|
|
pfree(inspected->sub_geoms);
|
2004-03-09 17:29:52 +00:00
|
|
|
pfree(inspected);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfree_point (LWPOINT *pt)
|
|
|
|
{
|
2004-03-10 01:15:06 +00:00
|
|
|
pfree_POINTARRAY(pt->point);
|
2004-03-09 17:29:52 +00:00
|
|
|
pfree(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfree_line (LWLINE *line)
|
|
|
|
{
|
|
|
|
pfree(line->points);
|
|
|
|
pfree(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfree_polygon (LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
pfree_POINTARRAY(poly->rings[t]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pfree(poly);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfree_POINTARRAY(POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
pfree(pa);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
//************************************************
|
|
|
|
//** debugging routines
|
|
|
|
|
|
|
|
|
|
|
|
void printLWLINE(LWLINE *line)
|
|
|
|
{
|
|
|
|
elog(NOTICE,"LWLINE {");
|
2004-04-02 19:03:06 +00:00
|
|
|
elog(NOTICE," ndims = %i", (int)line->ndims);
|
2004-03-11 00:54:37 +00:00
|
|
|
elog(NOTICE," SRID = %i", (int)line->SRID);
|
|
|
|
printPA(line->points);
|
|
|
|
elog(NOTICE,"}");
|
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void printLWPOINT(LWPOINT *point)
|
|
|
|
{
|
|
|
|
elog(NOTICE,"LWPOINT {");
|
|
|
|
elog(NOTICE," ndims = %i", (int)point->ndims);
|
|
|
|
elog(NOTICE," SRID = %i", (int)point->SRID);
|
|
|
|
printPA(point->point);
|
|
|
|
elog(NOTICE,"}");
|
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
void printPA(POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
POINT2D pt2;
|
|
|
|
POINT3D pt3;
|
2004-04-02 19:03:06 +00:00
|
|
|
POINT4D pt4;
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
elog(NOTICE," POINTARRAY{");
|
2004-04-02 19:03:06 +00:00
|
|
|
elog(NOTICE," ndims =%i, ptsize=%i", (int) pa->ndims,pointArray_ptsize(pa));
|
2004-03-11 00:54:37 +00:00
|
|
|
elog(NOTICE," npoints = %i", pa->npoints);
|
|
|
|
|
|
|
|
for (t =0; t<pa->npoints;t++)
|
|
|
|
{
|
2004-04-02 19:03:06 +00:00
|
|
|
if (pa->ndims == 2)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
|
|
|
pt2 = getPoint2d(pa,t);
|
|
|
|
elog(NOTICE," %i : %lf,%lf",t,pt2.x,pt2.y);
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
if (pa->ndims == 3)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
|
|
|
pt3 = getPoint3d(pa,t);
|
|
|
|
elog(NOTICE," %i : %lf,%lf,%lf",t,pt3.x,pt3.y,pt3.z);
|
|
|
|
}
|
2004-04-02 19:03:06 +00:00
|
|
|
if (pa->ndims == 4)
|
|
|
|
{
|
|
|
|
pt4 = getPoint4d(pa,t);
|
|
|
|
elog(NOTICE," %i : %lf,%lf,%lf,%lf",t,pt3.x,pt4.y,pt4.z,pt4.m);
|
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
elog(NOTICE," }");
|
|
|
|
}
|
|
|
|
|
|
|
|
void printBYTES(unsigned char *a, int n)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
char buff[3];
|
|
|
|
|
|
|
|
buff[2] = 0; //null terminate
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
elog(NOTICE," BYTE ARRAY (n=%i) IN HEX: {", n);
|
2004-03-11 00:54:37 +00:00
|
|
|
for (t=0;t<n;t++)
|
|
|
|
{
|
|
|
|
deparse_hex(a[t], buff);
|
|
|
|
elog(NOTICE, " %i : %s", t,buff );
|
|
|
|
}
|
|
|
|
elog(NOTICE, " }");
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
void printLWPOLY(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
elog(NOTICE,"LWPOLY {");
|
2004-04-02 19:03:06 +00:00
|
|
|
elog(NOTICE," ndims = %i", (int)poly->ndims);
|
2004-03-11 00:54:37 +00:00
|
|
|
elog(NOTICE," SRID = %i", (int)poly->SRID);
|
|
|
|
elog(NOTICE," nrings = %i", (int)poly->nrings);
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
elog(NOTICE," RING # %i :",t);
|
|
|
|
printPA(poly->rings[t]);
|
|
|
|
}
|
|
|
|
elog(NOTICE,"}");
|
|
|
|
}
|
2004-04-06 22:58:11 +00:00
|
|
|
|
|
|
|
void printMULTI(char *serialized)
|
|
|
|
{
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized);
|
|
|
|
LWLINE *line;
|
|
|
|
LWPOINT *point;
|
|
|
|
LWPOLY *poly;
|
|
|
|
int t;
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
elog(NOTICE,"MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((unsigned char)serialized[0]), inspected->ngeometries);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
|
|
|
for (t=0;t<inspected->ngeometries;t++)
|
|
|
|
{
|
|
|
|
elog(NOTICE," sub-geometry %i:", t);
|
|
|
|
line = NULL; point = NULL; poly = NULL;
|
|
|
|
|
|
|
|
line = lwgeom_getline_inspected(inspected,t);
|
|
|
|
if (line !=NULL)
|
|
|
|
{
|
|
|
|
printLWLINE(line);
|
|
|
|
}
|
|
|
|
poly = lwgeom_getpoly_inspected(inspected,t);
|
|
|
|
if (poly !=NULL)
|
|
|
|
{
|
|
|
|
printLWPOLY(poly);
|
|
|
|
}
|
|
|
|
point = lwgeom_getpoint_inspected(inspected,t);
|
|
|
|
if (point !=NULL)
|
|
|
|
{
|
|
|
|
printPA(point->point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
elog(NOTICE,"end multi*");
|
|
|
|
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
void printType(unsigned char type)
|
|
|
|
{
|
|
|
|
elog(NOTICE,"type 0x%x ==> hasBBOX=%i, hasSRID=%i, ndims=%i, type=%i",(unsigned int) type, lwgeom_hasBBOX(type), lwgeom_hasSRID(type),lwgeom_ndims(type), lwgeom_getType(type));
|
|
|
|
}
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
// get the SRID from the LWGEOM
|
|
|
|
// none present => -1
|
|
|
|
int lwgeom_getsrid(char *serialized)
|
|
|
|
{
|
|
|
|
unsigned char type = serialized[0];
|
|
|
|
char *loc = serialized+1;
|
|
|
|
|
|
|
|
if ( ! lwgeom_hasSRID(type)) return -1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return get_int32(loc);
|
|
|
|
}
|
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
// get the SRID from the LWGEOM
|
|
|
|
// none present => -1
|
|
|
|
int lwgeom_getSRID(LWGEOM *lwgeom)
|
|
|
|
{
|
|
|
|
unsigned char type = lwgeom->type;
|
|
|
|
char *loc = lwgeom->data;
|
|
|
|
|
|
|
|
if ( ! lwgeom_hasSRID(type)) return -1;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-24 13:45:05 +00:00
|
|
|
return get_int32(loc);
|
2004-08-20 14:08:41 +00:00
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
// Set the SRID of a LWGEOM
|
|
|
|
// Returns a newly allocated LWGEOM object.
|
2004-08-23 08:32:14 +00:00
|
|
|
// Allocation will be done using the palloc.
|
2004-08-20 14:08:41 +00:00
|
|
|
LWGEOM *lwgeom_setSRID(LWGEOM *lwgeom, int32 newSRID)
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2004-08-20 14:08:41 +00:00
|
|
|
unsigned char type = lwgeom->type;
|
|
|
|
int bbox_offset=0; //0=no bbox, otherwise sizeof(BOX2DFLOAT4)
|
|
|
|
int len,len_new,len_left;
|
|
|
|
LWGEOM *result;
|
|
|
|
char *loc_new, *loc_old;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
bbox_offset = sizeof(BOX2DFLOAT4);
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
len = lwgeom->size;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
if (lwgeom_hasSRID(type))
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2004-08-20 14:08:41 +00:00
|
|
|
//we create a new one and copy the SRID in
|
2004-08-23 08:32:14 +00:00
|
|
|
result = palloc(len);
|
2004-08-20 14:08:41 +00:00
|
|
|
memcpy(result, lwgeom, len);
|
|
|
|
memcpy(result->data+bbox_offset, &newSRID,4);
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
2004-08-20 14:08:41 +00:00
|
|
|
else // need to add one
|
|
|
|
{
|
|
|
|
len_new = len + 4;//+4 for SRID
|
2004-08-23 08:32:14 +00:00
|
|
|
result = palloc(len_new);
|
2004-08-20 14:08:41 +00:00
|
|
|
memcpy(result, &len_new, 4); // size copy in
|
|
|
|
result->type = lwgeom_makeType_full(lwgeom_ndims(type), true, lwgeom_getType(type),lwgeom_hasBBOX(type));
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
loc_new = result->data;
|
|
|
|
loc_old = lwgeom->data;
|
|
|
|
|
|
|
|
len_left = len -4-1;// old length - size - type
|
|
|
|
|
|
|
|
// handle bbox (if there)
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2004-08-20 14:08:41 +00:00
|
|
|
memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ;//copy in bbox
|
|
|
|
loc_new += sizeof(BOX2DFLOAT4);
|
|
|
|
loc_old += sizeof(BOX2DFLOAT4);
|
|
|
|
len_left -= sizeof(BOX2DFLOAT4);
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
2004-08-20 14:08:41 +00:00
|
|
|
|
|
|
|
//put in SRID
|
|
|
|
|
|
|
|
memcpy(loc_new, &newSRID,4);
|
|
|
|
loc_new +=4;
|
|
|
|
memcpy(loc_new, loc_old, len_left);
|
|
|
|
|
|
|
|
// TODO: add SRID presence flag in type.
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2004-08-24 14:47:25 +00:00
|
|
|
|
|
|
|
LWGEOM *
|
|
|
|
LWGEOM_construct(char *ser, int SRID, int wantbbox)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
char *iptr, *optr, *eptr;
|
|
|
|
int wantsrid = 0;
|
|
|
|
BOX2DFLOAT4 box;
|
|
|
|
LWGEOM *result;
|
|
|
|
|
|
|
|
size = lwgeom_seralizedformlength_simple(ser);
|
|
|
|
eptr = ser+size; // end of subgeom
|
|
|
|
|
|
|
|
iptr = ser+1; // skip type
|
|
|
|
if ( lwgeom_hasSRID(ser[0]) )
|
|
|
|
{
|
|
|
|
iptr += 4; // skip SRID
|
|
|
|
size -= 4;
|
|
|
|
}
|
|
|
|
if ( lwgeom_hasBBOX(ser[0]) )
|
|
|
|
{
|
|
|
|
iptr += sizeof(BOX2DFLOAT4); // skip BBOX
|
|
|
|
size -= sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( SRID != -1 )
|
|
|
|
{
|
|
|
|
wantsrid = 1;
|
|
|
|
size += 4;
|
|
|
|
}
|
|
|
|
if ( wantbbox )
|
|
|
|
{
|
|
|
|
size += sizeof(BOX2DFLOAT4);
|
|
|
|
getbox2d_p(ser, &box);
|
|
|
|
}
|
|
|
|
|
|
|
|
size+=4; // size header
|
|
|
|
|
|
|
|
result = palloc(size);
|
|
|
|
result->size = size;
|
|
|
|
|
|
|
|
result->type = lwgeom_makeType_full(lwgeom_ndims(ser[0]),
|
|
|
|
wantsrid, lwgeom_getType(ser[0]), wantbbox);
|
|
|
|
optr = result->data;
|
|
|
|
if ( wantbbox )
|
|
|
|
{
|
|
|
|
memcpy(optr, &box, sizeof(BOX2DFLOAT4));
|
|
|
|
optr += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
if ( wantsrid )
|
|
|
|
{
|
|
|
|
memcpy(optr, &SRID, 4);
|
|
|
|
optr += 4;
|
|
|
|
}
|
|
|
|
memcpy(optr, iptr, eptr-iptr);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2004-08-27 14:35:26 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
pfree_exploded(LWGEOM_EXPLODED *exploded)
|
|
|
|
{
|
|
|
|
if ( exploded->npoints )
|
|
|
|
pfree(exploded->points);
|
|
|
|
if ( exploded->nlines )
|
|
|
|
pfree(exploded->lines);
|
|
|
|
if ( exploded->npolys )
|
|
|
|
pfree(exploded->polys);
|
|
|
|
pfree(exploded);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function recursively scan the given serialized geometry
|
|
|
|
* and returns a list of _all_ subgeoms in it (deep-first)
|
|
|
|
*/
|
|
|
|
LWGEOM_EXPLODED *
|
|
|
|
lwgeom_explode(char *serialized)
|
|
|
|
{
|
2004-09-07 17:04:03 +00:00
|
|
|
LWGEOM_INSPECTED *inspected;
|
2004-08-27 14:35:26 +00:00
|
|
|
LWGEOM_EXPLODED *subexploded, *result;
|
|
|
|
int i;
|
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode called");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
inspected = lwgeom_inspect(serialized);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode: serialized inspected");
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
result = palloc(sizeof(LWGEOM_EXPLODED));
|
|
|
|
result->points = palloc(1);
|
|
|
|
result->lines = palloc(1);
|
|
|
|
result->polys = palloc(1);
|
|
|
|
result->npoints = 0;
|
|
|
|
result->nlines = 0;
|
|
|
|
result->npolys = 0;
|
|
|
|
|
|
|
|
if ( ! inspected->ngeometries )
|
|
|
|
{
|
|
|
|
pfree(result->points);
|
|
|
|
pfree(result->lines);
|
|
|
|
pfree(result->polys);
|
|
|
|
result->SRID = -1;
|
|
|
|
result->ndims = 0;
|
2004-08-27 15:03:11 +00:00
|
|
|
pfree_inspected(inspected);
|
|
|
|
elog(NOTICE, "lwgeom_explode: no geometries");
|
2004-08-27 14:35:26 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->SRID = lwgeom_getsrid(serialized);
|
|
|
|
result->ndims = lwgeom_ndims(serialized[0]);
|
|
|
|
|
|
|
|
for (i=0; i<inspected->ngeometries; i++)
|
|
|
|
{
|
|
|
|
|
|
|
|
char *subgeom = inspected->sub_geoms[i];
|
|
|
|
int type = lwgeom_getType(subgeom[0]);
|
|
|
|
|
|
|
|
if ( type == POINTTYPE )
|
|
|
|
{
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode: it's a point");
|
|
|
|
#endif
|
2004-08-27 14:35:26 +00:00
|
|
|
result->points = repalloc(result->points,
|
2004-09-07 17:04:03 +00:00
|
|
|
(result->npoints+1)*sizeof(char *));
|
2004-08-27 14:35:26 +00:00
|
|
|
result->points[result->npoints] = subgeom;
|
|
|
|
result->npoints++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( type == LINETYPE )
|
|
|
|
{
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode: it's a line");
|
|
|
|
#endif
|
2004-08-27 14:35:26 +00:00
|
|
|
result->lines = repalloc(result->lines,
|
2004-09-07 17:04:03 +00:00
|
|
|
(result->nlines+1)*sizeof(char *));
|
2004-08-27 14:35:26 +00:00
|
|
|
result->lines[result->nlines] = subgeom;
|
|
|
|
result->nlines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( type == POLYGONTYPE )
|
|
|
|
{
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode: it's a polygon");
|
|
|
|
#endif
|
2004-08-27 14:35:26 +00:00
|
|
|
result->polys = repalloc(result->polys,
|
2004-09-07 17:04:03 +00:00
|
|
|
(result->npolys+1)*sizeof(char *));
|
2004-08-27 14:35:26 +00:00
|
|
|
result->polys[result->npolys] = subgeom;
|
|
|
|
result->npolys++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2004-08-27 15:03:11 +00:00
|
|
|
#ifdef DEBUG
|
2004-09-07 17:04:03 +00:00
|
|
|
elog(NOTICE, "type of subgeom %d is %d, recursing", i, type);
|
2004-08-27 15:03:11 +00:00
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
// it's a multi geometry, recurse
|
|
|
|
subexploded = lwgeom_explode(subgeom);
|
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys);
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
// Re-allocate adding space for new exploded geoms
|
|
|
|
// (-1 because 1 was already allocated for the collection)
|
|
|
|
// Copy subgeom pointers from subexploded to current
|
|
|
|
// exploded.
|
|
|
|
|
|
|
|
if ( subexploded->npoints )
|
|
|
|
{
|
|
|
|
result->points = repalloc(result->points,
|
2004-09-07 17:04:03 +00:00
|
|
|
sizeof(char *)*(result->npoints+subexploded->npoints-1));
|
|
|
|
if ( ! result )
|
|
|
|
elog(ERROR, "Out of virtual memory");
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "repalloc'ed exploded->points");
|
|
|
|
#endif
|
2004-08-27 14:35:26 +00:00
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
memcpy(&(result->points[result->npoints]),
|
2004-08-27 14:35:26 +00:00
|
|
|
subexploded->points,
|
|
|
|
subexploded->npoints*sizeof(char *));
|
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "memcpied exploded->points");
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
result->npoints += subexploded->npoints;
|
2004-09-07 17:04:03 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints);
|
|
|
|
#endif
|
2004-08-27 14:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( subexploded->nlines )
|
|
|
|
{
|
|
|
|
result->lines = repalloc(result->lines,
|
2004-09-07 17:04:03 +00:00
|
|
|
sizeof(char *)*
|
|
|
|
(result->nlines+subexploded->nlines-1));
|
2004-08-27 14:35:26 +00:00
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
memcpy(&(result->lines[result->nlines]),
|
2004-08-27 14:35:26 +00:00
|
|
|
subexploded->lines,
|
|
|
|
subexploded->nlines*sizeof(char *));
|
|
|
|
|
|
|
|
result->nlines += subexploded->nlines;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( subexploded->npolys )
|
|
|
|
{
|
|
|
|
result->polys = repalloc(result->polys,
|
2004-09-07 17:04:03 +00:00
|
|
|
sizeof(char *)*
|
|
|
|
(result->npolys+subexploded->npolys-1));
|
2004-08-27 14:35:26 +00:00
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
memcpy(&(result->polys[result->npolys]),
|
2004-08-27 14:35:26 +00:00
|
|
|
subexploded->polys,
|
|
|
|
subexploded->npolys*sizeof(char *));
|
|
|
|
|
|
|
|
result->npolys += subexploded->npolys;
|
|
|
|
}
|
|
|
|
|
|
|
|
// release subexploded memory
|
|
|
|
pfree_exploded(subexploded);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-08-27 15:03:11 +00:00
|
|
|
pfree_inspected(inspected);
|
|
|
|
|
2004-09-07 17:04:03 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwgeom_explode: returning");
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a 'palloced' union of the two input exploded geoms
|
|
|
|
// Returns NULL if SRID or ndims do not match.
|
|
|
|
LWGEOM_EXPLODED *
|
|
|
|
lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
|
|
|
|
{
|
|
|
|
LWGEOM_EXPLODED *expcoll;
|
|
|
|
char *loc;
|
|
|
|
|
|
|
|
if ( exp1->ndims != exp2->ndims ) return NULL;
|
|
|
|
if ( exp1->SRID != exp2->SRID ) return NULL;
|
|
|
|
|
|
|
|
expcoll = palloc(sizeof(LWGEOM_EXPLODED));
|
|
|
|
|
|
|
|
expcoll->npoints = exp1->npoints + exp2->npoints;
|
|
|
|
if ( expcoll->npoints ) {
|
|
|
|
expcoll->points = (char **)palloc(expcoll->npoints*sizeof(char *));
|
|
|
|
loc = (char *)&(expcoll->points[0]);
|
|
|
|
if ( exp1->npoints ) {
|
|
|
|
memcpy(loc, exp1->points,
|
|
|
|
exp1->npoints*sizeof(char *));
|
|
|
|
loc += exp1->npoints*sizeof(char *);
|
|
|
|
}
|
|
|
|
if ( exp2->npoints ) {
|
|
|
|
memcpy(loc, exp2->points,
|
|
|
|
exp2->npoints*sizeof(char *));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expcoll->nlines = exp1->nlines + exp2->nlines;
|
|
|
|
if ( expcoll->nlines ) {
|
|
|
|
expcoll->lines = palloc(expcoll->nlines*sizeof(char *));
|
|
|
|
loc = (char *)&(expcoll->lines[0]);
|
|
|
|
if ( exp1->nlines ) {
|
|
|
|
memcpy(loc, exp1->lines,
|
|
|
|
exp1->nlines*sizeof(char *));
|
|
|
|
loc += exp1->nlines*sizeof(char *);
|
|
|
|
}
|
|
|
|
if ( exp2->nlines ) {
|
|
|
|
memcpy(loc, exp2->lines,
|
|
|
|
exp2->nlines*sizeof(char *));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expcoll->npolys = exp1->npolys + exp2->npolys;
|
|
|
|
if ( expcoll->npolys ) {
|
|
|
|
expcoll->polys = palloc(expcoll->npolys*sizeof(char *));
|
|
|
|
loc = (char *)&(expcoll->polys[0]);
|
|
|
|
if ( exp1->npolys ) {
|
|
|
|
memcpy(loc, exp1->polys,
|
|
|
|
exp1->npolys*sizeof(char *));
|
|
|
|
loc += exp1->npolys*sizeof(char *);
|
|
|
|
}
|
|
|
|
if ( exp2->npolys ) {
|
|
|
|
memcpy(loc, exp2->polys,
|
|
|
|
exp2->npolys*sizeof(char *));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expcoll->ndims = exp1->ndims;
|
|
|
|
expcoll->SRID = exp1->SRID;
|
|
|
|
|
|
|
|
return expcoll;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Serialized a LWGEOM_EXPLODED structure
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox)
|
|
|
|
{
|
|
|
|
unsigned int size=0;
|
|
|
|
int i;
|
|
|
|
int ntypes = 0;
|
|
|
|
int ngeoms = 0;
|
|
|
|
char *result, *loc;
|
|
|
|
int outtype = 0;
|
|
|
|
LWPOLY *poly;
|
|
|
|
LWLINE *line;
|
|
|
|
LWPOINT *point;
|
|
|
|
BOX2DFLOAT4 *box2d;
|
|
|
|
BOX3D *box3d;
|
|
|
|
char *ser;
|
|
|
|
|
2004-09-06 16:04:13 +00:00
|
|
|
if ( exploded->npoints + exploded->nlines + exploded->npolys == 0 )
|
|
|
|
{
|
|
|
|
return lwgeom_constructempty(exploded->SRID, exploded->ndims);
|
|
|
|
}
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
// find size of all geoms.
|
|
|
|
// If BBOX and SRID are included this size could be
|
|
|
|
// larger then needed, but that should not be a problem
|
|
|
|
for (i=0; i<exploded->npoints; i++)
|
|
|
|
size += lwpoint_findlength(exploded->points[i]);
|
|
|
|
for (i=0; i<exploded->nlines; i++)
|
|
|
|
size += lwline_findlength(exploded->lines[i]);
|
|
|
|
for (i=0; i<exploded->npolys; i++)
|
|
|
|
size += lwpoly_findlength(exploded->polys[i]);
|
|
|
|
|
|
|
|
if ( exploded->npoints )
|
|
|
|
{
|
|
|
|
ntypes++;
|
|
|
|
outtype = (exploded->npoints>1) ? MULTIPOINTTYPE : POINTTYPE;
|
|
|
|
}
|
|
|
|
if ( exploded->nlines )
|
|
|
|
{
|
|
|
|
ntypes++;
|
|
|
|
if ( outtype ) outtype = COLLECTIONTYPE;
|
|
|
|
else outtype = (exploded->nlines>1) ? MULTILINETYPE : LINETYPE;
|
|
|
|
}
|
|
|
|
if ( exploded->npolys )
|
|
|
|
{
|
|
|
|
ntypes++;
|
|
|
|
if ( outtype ) outtype = COLLECTIONTYPE;
|
|
|
|
else outtype = (exploded->npolys>1) ? MULTIPOLYGONTYPE : POLYGONTYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ngeoms = exploded->npoints + exploded->nlines + exploded->npolys;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, " computed outtype: %d, ngeoms: %d", outtype, ngeoms);
|
|
|
|
#endif
|
|
|
|
|
2004-09-06 16:04:13 +00:00
|
|
|
if ( ! ngeoms )
|
|
|
|
{
|
|
|
|
return lwgeom_constructempty(exploded->SRID, exploded->ndims);
|
|
|
|
}
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
|
|
|
|
// For a single geometry just set SRID and BBOX (if requested)
|
|
|
|
if ( ngeoms < 2 )
|
|
|
|
{
|
|
|
|
if ( exploded->npoints )
|
|
|
|
{
|
|
|
|
point = lwpoint_deserialize(exploded->points[0]);
|
|
|
|
point->SRID = exploded->SRID;
|
|
|
|
ser = lwpoint_serialize(point);
|
|
|
|
pfree_point(point);
|
|
|
|
size = lwpoint_findlength(ser);
|
|
|
|
}
|
|
|
|
else if ( exploded->nlines )
|
|
|
|
{
|
|
|
|
line = lwline_deserialize(exploded->lines[0]);
|
|
|
|
line->SRID = exploded->SRID;
|
|
|
|
ser = lwline_serialize(line);
|
|
|
|
pfree_line(line);
|
|
|
|
size = lwline_findlength(ser);
|
|
|
|
}
|
|
|
|
else if ( exploded->npolys )
|
|
|
|
{
|
|
|
|
poly = lwpoly_deserialize(exploded->polys[0]);
|
|
|
|
poly->SRID = exploded->SRID;
|
|
|
|
ser = lwpoly_serialize(poly);
|
|
|
|
pfree_polygon(poly);
|
|
|
|
size = lwpoly_findlength(ser);
|
|
|
|
}
|
|
|
|
else return NULL;
|
|
|
|
if ( wantbbox && ! lwgeom_hasBBOX(ser[0]) )
|
|
|
|
{
|
|
|
|
result = palloc(size+4);
|
|
|
|
result[0] = TYPE_SETHASBBOX(ser[0], 1);
|
|
|
|
loc = result+1;
|
|
|
|
box3d = lw_geom_getBB_simple(ser);
|
|
|
|
box2d = box3d_to_box2df(box3d);
|
|
|
|
memcpy(loc, box2d, sizeof(BOX2DFLOAT4));
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
memcpy(loc, (ser+1), size-1);
|
|
|
|
pfree(ser);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ser;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add size for 3 multigeoms + root geom + bbox and srid.
|
|
|
|
// Also in this case we are considering worst case.
|
|
|
|
size += 24+sizeof(BOX2DFLOAT4);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, " computed totsize: %d", size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
result = palloc(size*2);
|
|
|
|
loc = result+1; // skip type
|
|
|
|
|
|
|
|
if ( wantbbox ) loc += sizeof(BOX2DFLOAT4); // skip box
|
|
|
|
if ( exploded->SRID != -1 ) loc += 4; // skip SRID
|
|
|
|
|
|
|
|
// If we have more then one type of geom
|
|
|
|
// write that number in the 'ngeoms' field of the
|
|
|
|
// output serialized form (internal geoms would be multi themself)
|
|
|
|
if ( ntypes > 1 )
|
|
|
|
{
|
|
|
|
memcpy(loc, &ntypes, 4);
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
loc--; // let the type be specified later.
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( exploded->npoints > 1 )
|
|
|
|
{
|
|
|
|
loc[0] = lwgeom_makeType_full(exploded->ndims, 0,
|
|
|
|
MULTIPOINTTYPE, 0);
|
|
|
|
loc++;
|
|
|
|
memcpy(loc, &exploded->npoints, 4); // numpoints
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
// Serialize points stripping BBOX and SRID if any
|
|
|
|
for (i=0; i<exploded->npoints; i++)
|
|
|
|
{
|
|
|
|
int subsize;
|
|
|
|
|
|
|
|
point = lwpoint_deserialize(exploded->points[i]);
|
|
|
|
point->SRID = -1;
|
|
|
|
ser = lwpoint_serialize(point);
|
|
|
|
subsize = lwpoint_findlength(ser);
|
|
|
|
memcpy(loc, ser, subsize);
|
|
|
|
loc += subsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( exploded->nlines > 1 )
|
|
|
|
{
|
|
|
|
loc[0] = lwgeom_makeType_full(exploded->ndims, 0,
|
|
|
|
MULTILINETYPE, 0);
|
|
|
|
loc++;
|
|
|
|
memcpy(loc, &exploded->nlines, 4); // numlines
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
// Serialize lines stripping BBOX and SRID if any
|
|
|
|
for (i=0; i<exploded->nlines; i++)
|
|
|
|
{
|
|
|
|
char *ser;
|
|
|
|
int subsize;
|
|
|
|
|
|
|
|
line = lwline_deserialize(exploded->lines[i]);
|
|
|
|
if ( line == NULL )
|
|
|
|
{
|
|
|
|
elog(ERROR, "Error deserializing %dnt line from exploded geom", i);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
line->SRID = -1;
|
|
|
|
ser = lwline_serialize(line);
|
|
|
|
pfree_line(line);
|
|
|
|
subsize = lwline_findlength(ser);
|
|
|
|
memcpy(loc, ser, subsize);
|
|
|
|
pfree(ser);
|
|
|
|
loc += subsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( exploded->npolys > 1 )
|
|
|
|
{
|
|
|
|
loc[0] = lwgeom_makeType_full(exploded->ndims, 0,
|
|
|
|
MULTIPOLYGONTYPE, 0);
|
|
|
|
loc++;
|
|
|
|
memcpy(loc, &exploded->npolys, 4); // numpolys
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
// Serialize polys stripping BBOX and SRID if any
|
|
|
|
for (i=0; i<exploded->npolys; i++)
|
|
|
|
{
|
|
|
|
char *ser;
|
|
|
|
int subsize;
|
|
|
|
|
|
|
|
poly = lwpoly_deserialize(exploded->polys[i]);
|
|
|
|
if ( poly == NULL )
|
|
|
|
{
|
|
|
|
elog(ERROR, "Error deserializing %dnt polygon from exploded geom", i);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
poly->SRID = -1;
|
|
|
|
ser = lwpoly_serialize(poly);
|
|
|
|
pfree_polygon(poly);
|
|
|
|
subsize = lwpoly_findlength(ser);
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "size of polygon %d: %d", i, subsize);
|
|
|
|
#endif
|
|
|
|
memcpy(loc, ser, subsize);
|
|
|
|
pfree(ser);
|
|
|
|
loc += subsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ok. now we need to add type, SRID and bbox
|
|
|
|
result[0] = lwgeom_makeType_full(exploded->ndims,
|
|
|
|
(exploded->SRID!=-1), outtype, wantbbox);
|
|
|
|
loc = result+1;
|
|
|
|
|
|
|
|
if ( wantbbox )
|
|
|
|
{
|
|
|
|
box3d = lw_geom_getBB_simple(result);
|
|
|
|
box2d = box3d_to_box2df(box3d);
|
|
|
|
memcpy(loc, box2d, sizeof(BOX2DFLOAT4));
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( exploded->SRID != -1 )
|
|
|
|
{
|
|
|
|
memcpy(loc, &(exploded->SRID), 4);
|
|
|
|
loc += 4; // useless.. we've finished
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
elog(NOTICE, "lwexploded_serialize finished");
|
|
|
|
elog(NOTICE, " type: %d", lwgeom_getType(result[0]));
|
|
|
|
elog(NOTICE, " SRID: %d", lwgeom_getsrid(result));
|
|
|
|
if ( lwgeom_hasBBOX(result[0]) )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
BOX2DFLOAT4 boxbuf;
|
|
|
|
getbox2d_p(result, &boxbuf);
|
|
|
|
elog(NOTICE, " BBOX: %f,%f %f,%f",
|
|
|
|
boxbuf.xmin, boxbuf.ymin,
|
|
|
|
boxbuf.xmax, boxbuf.ymax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elog(NOTICE, " numgeoms: %d", lwgeom_getnumgeometries(result));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|