2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
#include "liblwgeom.h"
|
2005-09-23 16:43:56 +00:00
|
|
|
#include "wktparse.h"
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
//#define PGIS_DEBUG 1
|
2004-09-21 10:57:26 +00:00
|
|
|
|
2004-04-29 18:44:36 +00:00
|
|
|
// This is an implementation of the functions defined in lwgeom.h
|
|
|
|
|
|
|
|
//forward decs
|
2005-09-23 16:43:56 +00:00
|
|
|
//extern uchar *parse_lwg(const char* geometry, lwallocator allocfunc, lwreporter errfunc);
|
2004-09-22 16:09:54 +00:00
|
|
|
|
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
|
2004-09-29 10:50:30 +00:00
|
|
|
// returned box2d is allocated with 'lwalloc'
|
2004-10-08 13:20:55 +00:00
|
|
|
BOX2DFLOAT4 *
|
|
|
|
box3d_to_box2df(BOX3D *box)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
BOX2DFLOAT4 *result = (BOX2DFLOAT4*) lwalloc(sizeof(BOX2DFLOAT4));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if (box == NULL)
|
2004-08-19 13:16:16 +00:00
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwerror("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-09-16 10:42:08 +00:00
|
|
|
// Convert BOX3D to BOX2D using pre-allocated BOX2D
|
2004-09-29 10:50:30 +00:00
|
|
|
// returned box2d is allocated with 'lwalloc'
|
2004-09-16 10:42:08 +00:00
|
|
|
// return 0 on error (NULL input box)
|
2004-10-08 13:20:55 +00:00
|
|
|
int
|
|
|
|
box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *result)
|
2004-09-16 10:42:08 +00:00
|
|
|
{
|
|
|
|
if (box == NULL)
|
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("box3d_to_box2df got NUL box");
|
2004-09-16 10:42:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->xmin = nextDown_f(box->xmin);
|
|
|
|
result->ymin = nextDown_f(box->ymin);
|
|
|
|
|
|
|
|
result->xmax = nextUp_f(box->xmax);
|
|
|
|
result->ymax = nextUp_f(box->ymax);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
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-10-08 13:20:55 +00:00
|
|
|
BOX3D
|
|
|
|
box2df_to_box3d(BOX2DFLOAT4 *box)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
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.
|
2004-10-08 13:20:55 +00:00
|
|
|
void
|
|
|
|
box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
|
2004-09-06 09:13:13 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
// returns a BOX3D that encloses b1 and b2
|
2005-03-18 12:36:27 +00:00
|
|
|
// box3d_union(NULL,A) --> A
|
|
|
|
// box3d_union(A,NULL) --> A
|
|
|
|
// box3d_union(A,B) --> A union B
|
|
|
|
BOX3D *
|
|
|
|
box3d_union(BOX3D *b1, BOX3D *b2)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
BOX3D *result;
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
result = lwalloc(sizeof(BOX3D));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if ( (b1 == NULL) && (b2 == NULL) )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1 == NULL)
|
|
|
|
{
|
|
|
|
//return b2
|
|
|
|
memcpy(result, b2, sizeof(BOX3D));
|
2005-03-18 12:36:27 +00:00
|
|
|
return result;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
if (b2 == NULL)
|
|
|
|
{
|
|
|
|
//return b1
|
|
|
|
memcpy(result, b1, sizeof(BOX3D));
|
2005-03-18 12:36:27 +00:00
|
|
|
return result;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
// Make given ubox a union of b1 and b2
|
|
|
|
int
|
|
|
|
box3d_union_p(BOX3D *b1, BOX3D *b2, BOX3D *ubox)
|
|
|
|
{
|
|
|
|
if ( (b1 == NULL) && (b2 == NULL) )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1 == NULL)
|
|
|
|
{
|
|
|
|
memcpy(ubox, b2, sizeof(BOX3D));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (b2 == NULL)
|
|
|
|
{
|
|
|
|
memcpy(ubox, b1, sizeof(BOX3D));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1->xmin < b2->xmin)
|
|
|
|
ubox->xmin = b1->xmin;
|
|
|
|
else
|
|
|
|
ubox->xmin = b2->xmin;
|
|
|
|
|
|
|
|
if (b1->ymin < b2->ymin)
|
|
|
|
ubox->ymin = b1->ymin;
|
|
|
|
else
|
|
|
|
ubox->ymin = b2->ymin;
|
|
|
|
|
|
|
|
|
|
|
|
if (b1->xmax > b2->xmax)
|
|
|
|
ubox->xmax = b1->xmax;
|
|
|
|
else
|
|
|
|
ubox->xmax = b2->xmax;
|
|
|
|
|
|
|
|
if (b1->ymax > b2->ymax)
|
|
|
|
ubox->ymax = b1->ymax;
|
|
|
|
else
|
|
|
|
ubox->ymax = b2->ymax;
|
|
|
|
|
|
|
|
if (b1->zmax > b2->zmax)
|
|
|
|
ubox->zmax = b1->zmax;
|
|
|
|
else
|
|
|
|
ubox->zmax = b2->zmax;
|
|
|
|
|
|
|
|
if (b1->zmin > b2->zmin)
|
|
|
|
ubox->zmin = b1->zmin;
|
|
|
|
else
|
|
|
|
ubox->zmin = b2->zmin;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-10-08 13:20:55 +00:00
|
|
|
// returns a pointer to internal storage, or NULL
|
|
|
|
// if the serialized form does not have a BBOX.
|
2005-02-10 17:41:55 +00:00
|
|
|
//BOX2DFLOAT4 *
|
|
|
|
//getbox2d_internal(uchar *srl)
|
|
|
|
//{
|
|
|
|
// if (TYPE_HASBBOX(srl[0])) return (BOX2DFLOAT4 *)(srl+1);
|
|
|
|
// else return NULL;
|
|
|
|
//}
|
2004-10-08 13:20:55 +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
|
2005-03-18 12:36:27 +00:00
|
|
|
getbox2d_p(uchar *srl, BOX2DFLOAT4 *box)
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
uchar type = srl[0];
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *loc;
|
2005-03-18 12:36:27 +00:00
|
|
|
BOX3D box3d;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("getbox2d_p call");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
loc = srl+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
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("getbox2d_p: has box");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
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
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("getbox2d_p: has no box - computing");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
|
2004-08-20 14:08:41 +00:00
|
|
|
//we have to actually compute it!
|
2005-03-18 12:36:27 +00:00
|
|
|
//lwnotice("getbox2d_p:: computing box");
|
|
|
|
if ( ! compute_serialized_box3d_p(srl, &box3d) ) return 0;
|
2004-09-18 22:15:35 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2005-03-18 12:36:27 +00:00
|
|
|
lwnotice("getbox2d_p: compute_serialized_box3d returned %p", box3d);
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
if ( ! box3d_to_box2df_p(&box3d, box) ) return 0;
|
2004-09-16 10:42:08 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("getbox2d_p: box3d converted to box2d");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
|
|
|
//************************************************************************
|
|
|
|
// 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
|
2004-09-28 08:21:42 +00:00
|
|
|
POINT4D
|
|
|
|
getPoint4d(const POINTARRAY *pa, int n)
|
2004-04-02 19:03:06 +00:00
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
POINT4D result;
|
|
|
|
getPoint4d_p(pa, n, &result);
|
|
|
|
return result;
|
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: this will modify the point4d pointed to by 'point'.
|
2004-10-05 16:28:34 +00:00
|
|
|
int
|
|
|
|
getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
|
2004-04-02 19:03:06 +00:00
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
int size;
|
|
|
|
|
|
|
|
if ( ! pa ) return 0;
|
2004-04-02 19:03:06 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
lwerror("getPoint4d_p: point offset out of range");
|
|
|
|
return 0; //error
|
|
|
|
}
|
|
|
|
|
2005-02-10 17:41:55 +00:00
|
|
|
memset(point, 0, sizeof(POINT3DZ));
|
2004-10-05 16:28:34 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2005-02-10 17:41:55 +00:00
|
|
|
memcpy(point, getPoint_internal(pa, n), size);
|
2004-10-05 16:28:34 +00:00
|
|
|
return 1;
|
2004-04-02 19:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
2004-10-05 16:28:34 +00:00
|
|
|
// NOTE: point is a real POINT3DZ *not* a pointer
|
|
|
|
POINT3DZ
|
|
|
|
getPoint3dz(const POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
POINT3DZ result;
|
|
|
|
getPoint3dz_p(pa, n, &result);
|
|
|
|
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: point is a real POINT3DZ *not* a pointer
|
|
|
|
POINT3DM
|
|
|
|
getPoint3dm(const POINTARRAY *pa, int n)
|
|
|
|
{
|
|
|
|
POINT3DM result;
|
|
|
|
getPoint3dm_p(pa, n, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
|
|
|
// will set point's z=NO_Z_VALUE if pa is 2d
|
|
|
|
// NOTE: this will modify the point3dz pointed to by 'point'.
|
|
|
|
int
|
|
|
|
getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *op)
|
2004-09-18 22:15:35 +00:00
|
|
|
{
|
|
|
|
int size;
|
2004-10-05 16:28:34 +00:00
|
|
|
|
|
|
|
if ( ! pa ) return 0;
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 16:28:34 +00:00
|
|
|
lwnotice("getPoint3dz_p called on array of %d-dimensions / %u pts",
|
|
|
|
TYPE_NDIMS(pa->dims), pa->npoints);
|
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-18 22:15:35 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
lwnotice("%d out of numpoint range (%d)", n, pa->npoints);
|
|
|
|
return 0; //error
|
2004-09-18 22:15:35 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-10 17:41:55 +00:00
|
|
|
/* initialize point */
|
|
|
|
memset(op, 0, sizeof(POINT3DZ));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-10 17:41:55 +00:00
|
|
|
/* copy */
|
|
|
|
size = pointArray_ptsize(pa);
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 16:28:34 +00:00
|
|
|
lwnotice("getPoint3dz_p: point size: %d", size);
|
|
|
|
#endif
|
2005-02-10 17:41:55 +00:00
|
|
|
memcpy(op, getPoint_internal(pa, n), size);
|
2004-10-05 16:28:34 +00:00
|
|
|
return 1;
|
2005-02-10 17:41:55 +00:00
|
|
|
|
2004-09-18 22:15:35 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
// copies a point from the point array into the parameter point
|
2004-10-05 16:28:34 +00:00
|
|
|
// will set point's m=NO_Z_VALUE if pa has no M
|
|
|
|
// NOTE: this will modify the point3dm pointed to by 'point'.
|
|
|
|
int
|
|
|
|
getPoint3dm_p(const POINTARRAY *pa, int n, POINT3DM *op)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
int size;
|
2004-09-18 22:15:35 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
if ( ! pa ) return 0;
|
2004-09-18 22:15:35 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 16:28:34 +00:00
|
|
|
lwnotice("getPoint3dm_p(%d) called on array of %d-dimensions / %u pts",
|
|
|
|
n, TYPE_NDIMS(pa->dims), pa->npoints);
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
lwerror("%d out of numpoint range (%d)", n, pa->npoints);
|
|
|
|
return 0; //error
|
2004-08-19 13:16:16 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-10 17:41:55 +00:00
|
|
|
/* initialize point */
|
|
|
|
memset(op, 0, sizeof(POINT3DM));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-10 17:41:55 +00:00
|
|
|
/* copy */
|
|
|
|
size = pointArray_ptsize(pa);
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2005-02-10 17:41:55 +00:00
|
|
|
lwnotice("getPoint3dz_p: point size: %d", size);
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
2005-02-10 17:41:55 +00:00
|
|
|
memcpy(op, getPoint_internal(pa, n), size);
|
2004-10-05 16:28:34 +00:00
|
|
|
return 1;
|
2004-09-18 22:15:35 +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)
|
2004-09-22 17:13:26 +00:00
|
|
|
// NOTE: point is a real POINT2D *not* a pointer
|
|
|
|
POINT2D
|
2004-09-28 08:21:42 +00:00
|
|
|
getPoint2d(const POINTARRAY *pa, int n)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-22 17:13:26 +00:00
|
|
|
POINT2D result;
|
|
|
|
int size;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-22 17:13:26 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return result; //error
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-22 17:13:26 +00:00
|
|
|
size = pointArray_ptsize(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-22 17:13:26 +00:00
|
|
|
// this does x,y
|
|
|
|
memcpy(&result.x, &pa->serialized_pointlist[size*n],sizeof(double)*2 );
|
|
|
|
return result;
|
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: this will modify the point2d pointed to by 'point'.
|
2004-10-05 16:28:34 +00:00
|
|
|
int
|
|
|
|
getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-23 13:38:54 +00:00
|
|
|
int size;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
if ( ! pa ) return 0;
|
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
lwerror("getPoint2d_p: point offset out of range");
|
|
|
|
return 0; //error
|
2004-08-23 13:38:54 +00:00
|
|
|
}
|
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-10-05 16:28:34 +00:00
|
|
|
return 1;
|
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
|
2005-02-10 17:41:55 +00:00
|
|
|
// You cannot safely cast this to a real POINT, due to memory alignment
|
|
|
|
// constraints. Use getPoint*_p for that.
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
2005-02-10 17:41:55 +00:00
|
|
|
getPoint_internal(const POINTARRAY *pa, int n)
|
2004-08-23 13:38:54 +00:00
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
2004-10-01 14:49:34 +00:00
|
|
|
if ( pa == NULL ) {
|
|
|
|
lwerror("getPoint got NULL pointarray");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-08-23 13:38:54 +00:00
|
|
|
if ( (n<0) || (n>=pa->npoints))
|
|
|
|
{
|
|
|
|
return NULL; //error
|
|
|
|
}
|
|
|
|
|
|
|
|
size = pointArray_ptsize(pa);
|
|
|
|
|
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-10-05 16:28:34 +00:00
|
|
|
POINTARRAY *
|
2005-02-10 10:52:53 +00:00
|
|
|
pointArray_construct(uchar *points, char hasz, char hasm,
|
|
|
|
uint32 npoints)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
POINTARRAY *pa;
|
2004-09-29 10:50:30 +00:00
|
|
|
pa = (POINTARRAY*)lwalloc(sizeof(POINTARRAY));
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
pa->dims = 0;
|
2005-08-31 16:49:26 +00:00
|
|
|
TYPE_SETZM(pa->dims, hasz?1:0, hasm?1:0);
|
2004-03-09 17:29:52 +00:00
|
|
|
pa->npoints = npoints;
|
2005-02-10 17:41:55 +00:00
|
|
|
|
2005-02-17 09:19:20 +00:00
|
|
|
pa->serialized_pointlist = points;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return pa;
|
|
|
|
}
|
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//size of point represeneted in the POINTARRAY
|
|
|
|
// 16 for 2d, 24 for 3d, 32 for 4d
|
|
|
|
int
|
|
|
|
pointArray_ptsize(const POINTARRAY *pa)
|
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
//fprintf(stderr, "pointArray_ptsize: TYPE_NDIMS(pa->dims)=%x\n", TYPE_NDIMS(pa->dims));
|
2004-10-05 16:28:34 +00:00
|
|
|
return sizeof(double)*TYPE_NDIMS(pa->dims);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//***************************************************************************
|
|
|
|
// basic type handling
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// returns true if this type says it has an SRID (S bit set)
|
2004-10-04 13:53:42 +00:00
|
|
|
char
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_hasSRID(uchar type)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2004-10-04 13:53:42 +00:00
|
|
|
return TYPE_HASSRID(type);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// returns either 2,3, or 4 -- 2=2D, 3=3D, 4=4D
|
2004-10-04 13:53:42 +00:00
|
|
|
int
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_ndims(uchar type)
|
2004-10-04 13:53:42 +00:00
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
return TYPE_NDIMS(type);
|
2004-10-04 13:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// has M ?
|
2005-02-10 10:52:53 +00:00
|
|
|
int lwgeom_hasM(uchar type)
|
2004-10-04 13:53:42 +00:00
|
|
|
{
|
|
|
|
return ( (type & 0x10) >>4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// has Z ?
|
2005-02-10 10:52:53 +00:00
|
|
|
int lwgeom_hasZ(uchar type)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-10-04 13:53:42 +00:00
|
|
|
return ( (type & 0x20) >>5);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// get base type (ie. POLYGONTYPE)
|
2005-02-10 10:52:53 +00:00
|
|
|
int
|
|
|
|
lwgeom_getType(uchar type)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
return (type & 0x0F);
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//construct a type (hasBOX=false)
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar
|
2004-10-05 16:28:34 +00:00
|
|
|
lwgeom_makeType(char hasz, char hasm, char hasSRID, int type)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2004-10-05 16:28:34 +00:00
|
|
|
return lwgeom_makeType_full(hasz, hasm, hasSRID, type, 0);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-10-04 13:53:42 +00:00
|
|
|
/*
|
|
|
|
* Construct a type
|
|
|
|
* TODO: needs to be expanded to accept explicit MZ type
|
|
|
|
*/
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar
|
2004-10-05 16:28:34 +00:00
|
|
|
lwgeom_makeType_full(char hasz, char hasm, char hasSRID, int type, char hasBBOX)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar result = (char)type;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
TYPE_SETZM(result, hasz, hasm);
|
|
|
|
TYPE_SETHASSRID(result, hasSRID);
|
|
|
|
TYPE_SETHASBBOX(result, hasBBOX);
|
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-09-29 10:50:30 +00:00
|
|
|
//returns true if there's a bbox in this LWGEOM (B bit set)
|
2004-10-05 16:28:34 +00:00
|
|
|
char
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_hasBBOX(uchar type)
|
2004-08-25 12:29:31 +00:00
|
|
|
{
|
2004-10-04 13:53:42 +00:00
|
|
|
return TYPE_HASBBOX(type);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//*****************************************************************************
|
|
|
|
// basic sub-geometry types
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// handle missaligned unsigned int32 data
|
|
|
|
uint32
|
2005-02-10 10:52:53 +00:00
|
|
|
get_uint32(const uchar *loc)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
uint32 result;
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
memcpy(&result, loc, sizeof(uint32));
|
|
|
|
return result;
|
|
|
|
}
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// handle missaligned signed int32 data
|
|
|
|
int32
|
2005-02-10 10:52:53 +00:00
|
|
|
get_int32(const uchar *loc)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
int32 result;
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
memcpy(&result,loc, sizeof(int32));
|
|
|
|
return result;
|
|
|
|
}
|
2004-08-25 12:29:31 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//******************************************************************************
|
2004-08-25 12:29:31 +00:00
|
|
|
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2004-09-22 16:52:13 +00:00
|
|
|
//*************************************************************************
|
|
|
|
// multi-geometry support
|
2004-03-09 17:29:52 +00:00
|
|
|
// 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.
|
2004-09-28 08:21:42 +00:00
|
|
|
LWGEOM_INSPECTED *
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_inspect(const uchar *serialized_form)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
LWGEOM_INSPECTED *result = lwalloc(sizeof(LWGEOM_INSPECTED));
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar typefl = (uchar)serialized_form[0];
|
|
|
|
uchar type;
|
|
|
|
uchar **sub_geoms;
|
|
|
|
const uchar *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
int t;
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 21:08:38 +00:00
|
|
|
lwnotice("lwgeom_inspect: serialized@%p", serialized_form);
|
|
|
|
#endif
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (serialized_form == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2004-09-28 08:21:42 +00:00
|
|
|
result->serialized_form = serialized_form;
|
2005-02-10 10:52:53 +00:00
|
|
|
result->type = (uchar) serialized_form[0];
|
2004-08-23 08:32:14 +00:00
|
|
|
result->SRID = -1; // assume
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-10-05 21:08:38 +00:00
|
|
|
type = lwgeom_getType(typefl);
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
2004-10-05 21:08:38 +00:00
|
|
|
if ( lwgeom_hasBBOX(typefl) )
|
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( lwgeom_hasSRID(typefl) )
|
|
|
|
{
|
|
|
|
result->SRID = get_int32(loc);
|
|
|
|
loc += 4;
|
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if ( (type==POINTTYPE) || (type==LINETYPE) || (type==POLYGONTYPE) )
|
|
|
|
{
|
|
|
|
//simple geometry (point/line/polygon)-- not multi!
|
|
|
|
result->ngeometries = 1;
|
2005-02-10 10:52:53 +00:00
|
|
|
sub_geoms = (uchar**) lwalloc(sizeof(char*));
|
|
|
|
sub_geoms[0] = (uchar *)serialized_form;
|
|
|
|
result->sub_geoms = (uchar **)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
|
|
|
|
|
|
|
|
result->ngeometries = get_uint32(loc);
|
|
|
|
loc +=4;
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_inspect: geometry is a collection of %d elements",
|
2004-08-23 10:49:08 +00:00
|
|
|
result->ngeometries);
|
|
|
|
#endif
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
if ( ! result->ngeometries ) return result;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
sub_geoms = lwalloc(sizeof(uchar*) * result->ngeometries );
|
2004-08-23 10:49:08 +00:00
|
|
|
result->sub_geoms = sub_geoms;
|
2005-02-10 10:52:53 +00:00
|
|
|
sub_geoms[0] = (uchar *)loc;
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 21:08:38 +00:00
|
|
|
lwnotice("subgeom[0] @ %p (+%d)", sub_geoms[0], sub_geoms[0]-serialized_form);
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
|
|
|
for (t=1;t<result->ngeometries; t++)
|
|
|
|
{
|
2004-09-22 16:09:54 +00:00
|
|
|
int sub_length = lwgeom_size_subgeom(sub_geoms[t-1], -1);//-1 = entire object
|
2004-08-23 10:49:08 +00:00
|
|
|
sub_geoms[t] = sub_geoms[t-1] + sub_length;
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-05 21:08:38 +00:00
|
|
|
lwnotice("subgeom[%d] @ %p (+%d)",
|
|
|
|
t, sub_geoms[t], sub_geoms[0]-serialized_form);
|
2004-08-23 10:49:08 +00:00
|
|
|
#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.
|
2005-02-10 10:52:53 +00:00
|
|
|
// this is fine to call on a point (with geom_num=0),
|
|
|
|
// multipoint or geometrycollection
|
|
|
|
LWPOINT *
|
|
|
|
lwgeom_getpoint(uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
int type = lwgeom_getType((uchar)serialized_form[0]);
|
|
|
|
uchar *sub_geom;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType(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;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar 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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType( (uchar) sub_geom[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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
|
2005-02-10 10:52:53 +00:00
|
|
|
LWLINE *
|
|
|
|
lwgeom_getline(uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom_getType( (uchar) serialized_form[0]);
|
|
|
|
uchar *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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType((uchar) sub_geom[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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)
|
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *sub_geom;
|
|
|
|
uchar 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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType((uchar) sub_geom[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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
|
2005-02-10 10:52:53 +00:00
|
|
|
LWPOLY *
|
|
|
|
lwgeom_getpoly(uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom_getType((uchar)serialized_form[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType((uchar) sub_geom[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar 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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = lwgeom_getType((uchar) sub_geom[0]);
|
2004-08-24 13:35:51 +00:00
|
|
|
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.
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
|
|
|
lwgeom_getsubgeometry(const uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
//major cheat!!
|
|
|
|
char * result;
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized_form);
|
|
|
|
|
|
|
|
result = lwgeom_getsubgeometry_inspected(inspected, geom_number);
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
2004-10-05 21:08:38 +00:00
|
|
|
lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
if ((geom_number <0) || (geom_number >= inspected->ngeometries) )
|
2004-10-05 21:08:38 +00:00
|
|
|
{
|
|
|
|
lwerror("lwgeom_getsubgeometry_inspected: geom_number out of range");
|
2004-03-09 17:29:52 +00:00
|
|
|
return NULL;
|
2004-10-05 21:08:38 +00:00
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
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
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar
|
|
|
|
lwgeom_getsubtype(uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar
|
|
|
|
lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
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.
|
2005-02-10 10:52:53 +00:00
|
|
|
int
|
|
|
|
lwgeom_getnumgeometries(uchar *serialized_form)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom_getType((uchar)serialized_form[0]);
|
|
|
|
uchar *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;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
if (lwgeom_hasBBOX((uchar) serialized_form[0]))
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
if (lwgeom_hasSRID((uchar) serialized_form[0]) )
|
2004-08-24 13:35:51 +00:00
|
|
|
{
|
|
|
|
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...
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
|
|
|
lwgeom_serialized_construct(int SRID, int finalType, char hasz, char hasm, int nsubgeometries, uchar **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;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *result;
|
|
|
|
uchar *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if (nsubgeometries == 0)
|
2004-10-05 16:28:34 +00:00
|
|
|
return lwgeom_constructempty(SRID, hasz, hasm);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lengths = lwalloc(sizeof(int32) * nsubgeometries);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
for (t=0;t<nsubgeometries;t++)
|
|
|
|
{
|
2004-09-22 16:09:54 +00:00
|
|
|
lengths[t] = lwgeom_size_subgeom(serialized_subs[t],-1);
|
2004-03-09 17:29:52 +00:00
|
|
|
total_length += lengths[t];
|
2005-02-10 10:52:53 +00:00
|
|
|
this_type = lwgeom_getType((uchar) (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
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
result = lwalloc(total_length);
|
2005-02-10 10:52:53 +00:00
|
|
|
result[0] = (uchar) lwgeom_makeType(hasz, hasm, 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] ;
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lwfree(lengths);
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
|
|
|
|
//returns serialized form
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
2004-10-05 16:28:34 +00:00
|
|
|
lwgeom_constructempty(int SRID, char hasz, char hasm)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
int size = 0;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *result;
|
2004-03-09 17:29:52 +00:00
|
|
|
int ngeoms = 0;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
if (SRID != -1)
|
|
|
|
size +=4;
|
|
|
|
|
|
|
|
size += 5;
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
result = lwalloc(size);
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
result[0] = lwgeom_makeType(hasz, hasm, 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;
|
|
|
|
}
|
|
|
|
|
2005-01-09 20:28:59 +00:00
|
|
|
size_t
|
2004-09-21 15:44:53 +00:00
|
|
|
lwgeom_empty_length(int SRID)
|
|
|
|
{
|
|
|
|
int size = 5;
|
|
|
|
if ( SRID != 1 ) size += 4;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
|
|
|
|
// writing it into the provided buffer.
|
|
|
|
void
|
2005-01-09 20:28:59 +00:00
|
|
|
lwgeom_constructempty_buf(int SRID, char hasz, char hasm,
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *buf, size_t *retsize)
|
2004-09-21 15:44:53 +00:00
|
|
|
{
|
|
|
|
int ngeoms = 0;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
buf[0] =(uchar) lwgeom_makeType( hasz, hasm, SRID != -1, COLLECTIONTYPE);
|
2004-09-21 15:44:53 +00:00
|
|
|
if (SRID != -1)
|
|
|
|
{
|
|
|
|
memcpy(&buf[1],&SRID,4);
|
|
|
|
buf += 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
buf += 1;
|
|
|
|
|
|
|
|
memcpy(buf, &ngeoms, 4);
|
|
|
|
|
2004-09-21 16:07:25 +00:00
|
|
|
if (retsize) *retsize = lwgeom_empty_length(SRID);
|
2004-09-21 15:44:53 +00:00
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
// 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
|
2004-10-05 17:15:42 +00:00
|
|
|
size_t
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_size(const uchar *serialized_form)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom_getType((uchar) serialized_form[0]);
|
2004-03-09 17:29:52 +00:00
|
|
|
int t;
|
2005-02-10 10:52:53 +00:00
|
|
|
const uchar *loc;
|
2004-03-09 17:29:52 +00:00
|
|
|
uint32 ngeoms;
|
|
|
|
int sub_size;
|
|
|
|
int result = 1; //"type"
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size called");
|
2004-08-24 13:35:51 +00:00
|
|
|
#endif
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
if (type == POINTTYPE)
|
2004-08-23 10:49:08 +00:00
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size: is a point");
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size_point(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
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size: is a line");
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size_line(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
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size: is a polygon");
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size_poly(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 )
|
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwerror("lwgeom_size called with unknown-typed serialized geometry");
|
2004-08-23 10:49:08 +00:00
|
|
|
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
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size called on a geoemtry with type %d", type);
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-04-26 23:05:20 +00:00
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
if (lwgeom_hasBBOX((uchar) serialized_form[0]))
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size: has bbox");
|
2004-08-23 10:49:08 +00:00
|
|
|
#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
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
if (lwgeom_hasSRID( (uchar) serialized_form[0]) )
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size: has srid");
|
2004-08-23 10:49:08 +00:00
|
|
|
#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-10-05 16:28:34 +00:00
|
|
|
ngeoms = get_uint32(loc);
|
2004-03-09 17:29:52 +00:00
|
|
|
loc +=4;
|
2004-08-23 10:49:08 +00:00
|
|
|
result += 4; // numgeoms
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
for (t=0;t<ngeoms;t++)
|
|
|
|
{
|
2004-09-22 16:09:54 +00:00
|
|
|
sub_size = lwgeom_size(loc);
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" subsize %d", sub_size);
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
loc += sub_size;
|
|
|
|
result += sub_size;
|
|
|
|
}
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size returning %d", result);
|
2004-08-23 10:49:08 +00:00
|
|
|
#endif
|
2004-03-09 17:29:52 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-10-05 17:15:42 +00:00
|
|
|
size_t
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_size_subgeom(const uchar *serialized_form, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
|
|
|
if (geom_number == -1)
|
|
|
|
{
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size(serialized_form);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size( lwgeom_getsubgeometry(serialized_form,geom_number));
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-09-22 16:52:13 +00:00
|
|
|
int
|
2004-09-28 08:21:42 +00:00
|
|
|
lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-09-22 16:09:54 +00:00
|
|
|
return lwgeom_size(inspected->sub_geoms[geom_number]);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
int
|
|
|
|
compute_serialized_box3d_p(uchar *srl, BOX3D *out)
|
|
|
|
{
|
2005-09-03 06:11:20 +00:00
|
|
|
BOX3D *box = compute_serialized_box3d(srl);
|
|
|
|
if ( ! box ) return 0;
|
|
|
|
out->xmin = box->xmin;
|
|
|
|
out->ymin = box->ymin;
|
|
|
|
out->zmin = box->zmin;
|
|
|
|
out->xmax = box->xmax;
|
|
|
|
out->ymax = box->ymax;
|
|
|
|
out->zmax = box->zmax;
|
|
|
|
lwfree(box);
|
|
|
|
|
|
|
|
return 1;
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
2004-12-30 15:58:27 +00:00
|
|
|
// Compute bounding box of a serialized LWGEOM, even if it is
|
|
|
|
// already cached. The computed BOX2DFLOAT4 is stored at
|
|
|
|
// the given location, the function returns 0 is the geometry
|
|
|
|
// does not have a bounding box (EMPTY GEOM)
|
|
|
|
int
|
2005-03-18 12:36:27 +00:00
|
|
|
compute_serialized_box2d_p(uchar *srl, BOX2DFLOAT4 *out)
|
2004-12-30 15:58:27 +00:00
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
BOX3D *result = compute_serialized_box3d(srl);
|
2004-12-30 15:58:27 +00:00
|
|
|
if ( ! result ) return 0;
|
|
|
|
out->xmin = result->xmin;
|
|
|
|
out->xmax = result->xmax;
|
|
|
|
out->ymin = result->ymin;
|
|
|
|
out->ymax = result->ymax;
|
|
|
|
lwfree(result);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
//dont forget to lwfree() result
|
2005-03-18 12:36:27 +00:00
|
|
|
BOX3D *
|
|
|
|
compute_serialized_box3d(uchar *srl)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
int type = lwgeom_getType(srl[0]);
|
2004-08-19 13:16:16 +00:00
|
|
|
int t;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *loc;
|
2004-08-19 13:16:16 +00:00
|
|
|
uint32 ngeoms;
|
|
|
|
BOX3D *result;
|
2005-03-18 12:36:27 +00:00
|
|
|
BOX3D b1;
|
2004-08-19 13:16:16 +00:00
|
|
|
int sub_size;
|
2005-03-18 12:36:27 +00:00
|
|
|
char nboxes=0;
|
|
|
|
|
|
|
|
//lwnotice("compute_serialized_box3d called");
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2005-03-18 12:36:27 +00:00
|
|
|
lwnotice("compute_serialized_box3d called on type %d", type);
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
if (type == POINTTYPE)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
LWPOINT *pt = lwpoint_deserialize(srl);
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2005-03-18 12:36:27 +00:00
|
|
|
lwnotice("compute_serialized_box3d: lwpoint deserialized");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
2005-03-18 12:36:27 +00:00
|
|
|
result = lwpoint_compute_box3d(pt);
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2005-03-18 12:36:27 +00:00
|
|
|
lwnotice("compute_serialized_box3d: bbox found");
|
2004-09-18 22:15:35 +00:00
|
|
|
#endif
|
2004-08-19 13:16:16 +00:00
|
|
|
pfree_point(pt);
|
|
|
|
return result;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-08-19 13:16:16 +00:00
|
|
|
else if (type == LINETYPE)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
LWLINE *line = lwline_deserialize(srl);
|
|
|
|
result = lwline_compute_box3d(line);
|
2004-08-19 13:16:16 +00:00
|
|
|
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)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
LWPOLY *poly = lwpoly_deserialize(srl);
|
|
|
|
result = lwpoly_compute_box3d(poly);
|
2004-08-19 13:16:16 +00:00
|
|
|
pfree_polygon(poly);
|
|
|
|
return result;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-18 22:15:35 +00:00
|
|
|
if ( ! ( type == MULTIPOINTTYPE || type == MULTILINETYPE ||
|
|
|
|
type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) )
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
lwnotice("compute_serialized_box3d called on unknown type %d", type);
|
2004-09-18 22:15:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
loc = srl+1;
|
2004-09-18 22:15:35 +00:00
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
if (lwgeom_hasBBOX(srl[0]))
|
2004-09-18 22:15:35 +00:00
|
|
|
{
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
if (lwgeom_hasSRID(srl[0]) )
|
2004-08-19 13:16:16 +00:00
|
|
|
{
|
|
|
|
loc +=4;
|
|
|
|
}
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
ngeoms = get_uint32(loc);
|
|
|
|
loc += 4;
|
2004-04-26 23:05:20 +00:00
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
// each sub-type
|
2004-08-19 13:16:16 +00:00
|
|
|
result = NULL;
|
2005-03-18 12:36:27 +00:00
|
|
|
for (t=0; t<ngeoms; t++)
|
2004-08-19 13:16:16 +00:00
|
|
|
{
|
2005-03-23 16:23:45 +00:00
|
|
|
if ( compute_serialized_box3d_p(loc, &b1) )
|
|
|
|
{
|
|
|
|
#ifdef PGIS_DEBUG
|
|
|
|
lwnotice("Geom %d have box:"); printBOX3D(&b1);
|
|
|
|
#endif
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
nboxes += box3d_union_p(result, &b1, result);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = lwalloc(sizeof(BOX3D));
|
|
|
|
memcpy(result, &b1, sizeof(BOX3D));
|
|
|
|
}
|
2005-03-18 12:36:27 +00:00
|
|
|
}
|
|
|
|
|
2004-09-22 16:09:54 +00:00
|
|
|
sub_size = lwgeom_size(loc);
|
2004-08-19 13:16:16 +00:00
|
|
|
loc += sub_size;
|
|
|
|
}
|
2004-03-09 17:29:52 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//****************************************************************
|
|
|
|
// memory management -- these only delete the memory associated
|
|
|
|
// directly with the structure - NOT the stuff pointing into
|
|
|
|
// the original de-serialized info
|
|
|
|
|
2005-03-16 11:41:08 +00:00
|
|
|
void
|
|
|
|
pfree_inspected(LWGEOM_INSPECTED *inspected)
|
2004-03-09 17:29:52 +00:00
|
|
|
{
|
2004-08-27 14:35:26 +00:00
|
|
|
if ( inspected->ngeometries )
|
2004-09-29 10:50:30 +00:00
|
|
|
lwfree(inspected->sub_geoms);
|
|
|
|
lwfree(inspected);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void pfree_POINTARRAY(POINTARRAY *pa)
|
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwfree(pa);
|
2004-03-09 17:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
//************************************************
|
|
|
|
//** debugging routines
|
|
|
|
|
|
|
|
|
2005-03-23 16:23:45 +00:00
|
|
|
void printBOX3D(BOX3D *box)
|
|
|
|
{
|
|
|
|
lwnotice("BOX3D: %g %g, %g %g", box->xmin, box->ymin,
|
|
|
|
box->xmax, box->ymax);
|
|
|
|
}
|
|
|
|
|
2004-03-11 00:54:37 +00:00
|
|
|
void printPA(POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
int t;
|
2005-02-10 17:41:55 +00:00
|
|
|
POINT4D pt;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *mflag;
|
2004-10-05 16:28:34 +00:00
|
|
|
|
|
|
|
if ( TYPE_HASM(pa->dims) ) mflag = "M";
|
|
|
|
else mflag = "";
|
2004-03-11 00:54:37 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
lwnotice(" POINTARRAY%s{", mflag);
|
|
|
|
lwnotice(" ndims=%i, ptsize=%i",
|
|
|
|
TYPE_NDIMS(pa->dims), pointArray_ptsize(pa));
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" npoints = %i", pa->npoints);
|
2004-03-11 00:54:37 +00:00
|
|
|
|
|
|
|
for (t =0; t<pa->npoints;t++)
|
|
|
|
{
|
2005-02-10 17:41:55 +00:00
|
|
|
getPoint4d_p(pa, t, &pt);
|
2004-10-05 16:28:34 +00:00
|
|
|
if (TYPE_NDIMS(pa->dims) == 2)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
2005-02-10 17:41:55 +00:00
|
|
|
lwnotice(" %i : %lf,%lf",t,pt.x,pt.y);
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
2004-10-05 16:28:34 +00:00
|
|
|
if (TYPE_NDIMS(pa->dims) == 3)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
2005-02-10 17:41:55 +00:00
|
|
|
lwnotice(" %i : %lf,%lf,%lf",t,pt.x,pt.y,pt.z);
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
2004-10-05 16:28:34 +00:00
|
|
|
if (TYPE_NDIMS(pa->dims) == 4)
|
2004-04-02 19:03:06 +00:00
|
|
|
{
|
2005-02-10 17:41:55 +00:00
|
|
|
lwnotice(" %i : %lf,%lf,%lf,%lf",t,pt.x,pt.y,pt.z,pt.m);
|
2004-04-02 19:03:06 +00:00
|
|
|
}
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" }");
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
void printBYTES(uchar *a, int n)
|
2004-03-11 00:54:37 +00:00
|
|
|
{
|
|
|
|
int t;
|
|
|
|
char buff[3];
|
|
|
|
|
|
|
|
buff[2] = 0; //null terminate
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" 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);
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" %i : %s", t,buff );
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" }");
|
2004-03-11 00:54:37 +00:00
|
|
|
}
|
|
|
|
|
2004-03-09 17:29:52 +00:00
|
|
|
|
2004-09-28 08:21:42 +00:00
|
|
|
void
|
2005-02-10 10:52:53 +00:00
|
|
|
printMULTI(uchar *serialized)
|
2004-04-06 22:58:11 +00:00
|
|
|
{
|
|
|
|
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized);
|
|
|
|
LWLINE *line;
|
|
|
|
LWPOINT *point;
|
|
|
|
LWPOLY *poly;
|
|
|
|
int t;
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
lwnotice("MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType((uchar)serialized[0]), inspected->ngeometries);
|
2004-04-06 22:58:11 +00:00
|
|
|
|
|
|
|
for (t=0;t<inspected->ngeometries;t++)
|
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" sub-geometry %i:", t);
|
2004-04-06 22:58:11 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("end multi*");
|
2004-04-06 22:58:11 +00:00
|
|
|
|
|
|
|
pfree_inspected(inspected);
|
|
|
|
}
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
void printType(uchar type)
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("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-04-26 23:05:20 +00:00
|
|
|
}
|
|
|
|
|
2004-08-27 14:35:26 +00:00
|
|
|
// get the SRID from the LWGEOM
|
|
|
|
// none present => -1
|
2005-02-10 10:52:53 +00:00
|
|
|
int
|
|
|
|
lwgeom_getsrid(uchar *serialized)
|
2004-08-27 14:35:26 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = serialized[0];
|
|
|
|
uchar *loc = serialized+1;
|
2004-08-27 14:35:26 +00:00
|
|
|
|
|
|
|
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
|
2005-09-23 11:23:47 +00:00
|
|
|
int
|
|
|
|
pglwgeom_getSRID(PG_LWGEOM *lwgeom)
|
2004-08-20 14:08:41 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom->type;
|
|
|
|
uchar *loc = lwgeom->data;
|
2004-08-20 14:08:41 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2005-09-23 11:23:47 +00:00
|
|
|
/*
|
|
|
|
* Make a PG_LWGEOM object from a WKB binary representation.
|
|
|
|
* Currently unoptimized as it will convert WKB to HEXWKB first.
|
|
|
|
*/
|
|
|
|
PG_LWGEOM *
|
|
|
|
pglwgeom_from_ewkb(uchar *ewkb, size_t ewkblen)
|
|
|
|
{
|
|
|
|
PG_LWGEOM *ret;
|
|
|
|
char *hexewkb;
|
|
|
|
size_t hexewkblen = ewkblen*2;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
hexewkb = lwalloc(hexewkblen+1);
|
|
|
|
for (i=0; i<ewkblen; i++)
|
|
|
|
{
|
|
|
|
deparse_hex(ewkb[i], &hexewkb[i*2]);
|
|
|
|
}
|
|
|
|
hexewkb[hexewkblen] = '\0';
|
|
|
|
|
|
|
|
ret = (PG_LWGEOM *)parse_lwgeom_wkt(hexewkb);
|
|
|
|
|
|
|
|
lwfree(hexewkb);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-09-23 16:43:56 +00:00
|
|
|
/*
|
|
|
|
* Return the EWKB (binary) representation for a PG_LWGEOM.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
pglwgeom_to_ewkb(PG_LWGEOM *geom, char byteorder, size_t *outsize)
|
|
|
|
{
|
|
|
|
uchar *srl = &(geom->type);
|
|
|
|
return unparse_WKB(srl, lwalloc, lwfree,
|
|
|
|
byteorder, outsize, 0);
|
|
|
|
}
|
|
|
|
|
2005-01-05 12:44:47 +00:00
|
|
|
// Set the SRID of a PG_LWGEOM
|
|
|
|
// Returns a newly allocated PG_LWGEOM object.
|
2004-09-29 10:50:30 +00:00
|
|
|
// Allocation will be done using the lwalloc.
|
2004-10-05 16:28:34 +00:00
|
|
|
PG_LWGEOM *
|
2005-01-05 12:44:47 +00:00
|
|
|
pglwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID)
|
2004-04-26 23:05:20 +00:00
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type = lwgeom->type;
|
2004-08-20 14:08:41 +00:00
|
|
|
int bbox_offset=0; //0=no bbox, otherwise sizeof(BOX2DFLOAT4)
|
|
|
|
int len,len_new,len_left;
|
2004-09-29 06:31:42 +00:00
|
|
|
PG_LWGEOM *result;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *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-12-21 15:17:30 +00:00
|
|
|
if ( newSRID != -1 ) {
|
|
|
|
//we create a new one and copy the SRID in
|
|
|
|
result = lwalloc(len);
|
|
|
|
memcpy(result, lwgeom, len);
|
|
|
|
memcpy(result->data+bbox_offset, &newSRID,4);
|
|
|
|
} else {
|
|
|
|
//we create a new one dropping the SRID
|
|
|
|
result = lwalloc(len-4);
|
|
|
|
result->size = len-4;
|
|
|
|
result->type = lwgeom_makeType_full(
|
|
|
|
TYPE_HASZ(type), TYPE_HASM(type),
|
|
|
|
0, lwgeom_getType(type),
|
|
|
|
lwgeom_hasBBOX(type));
|
|
|
|
loc_new = result->data;
|
|
|
|
loc_old = lwgeom->data;
|
|
|
|
len_left = len-4-1;
|
|
|
|
|
|
|
|
// handle bbox (if there)
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4));
|
|
|
|
loc_new += sizeof(BOX2DFLOAT4);
|
|
|
|
loc_old += sizeof(BOX2DFLOAT4);
|
|
|
|
len_left -= sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip SRID, copy the remaining
|
|
|
|
loc_old += 4;
|
|
|
|
len_left -= 4;
|
|
|
|
memcpy(loc_new, loc_old, len_left);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-04-26 23:05:20 +00:00
|
|
|
}
|
2004-12-21 15:17:30 +00:00
|
|
|
else
|
2004-08-20 14:08:41 +00:00
|
|
|
{
|
2004-12-21 15:17:30 +00:00
|
|
|
// just copy input, already w/out a SRID
|
|
|
|
if ( newSRID == -1 ) {
|
|
|
|
result = lwalloc(len);
|
|
|
|
memcpy(result, lwgeom, len);
|
|
|
|
}
|
|
|
|
// need to add one
|
|
|
|
else {
|
|
|
|
len_new = len + 4;//+4 for SRID
|
|
|
|
result = lwalloc(len_new);
|
|
|
|
memcpy(result, &len_new, 4); // size copy in
|
|
|
|
result->type = lwgeom_makeType_full(
|
|
|
|
TYPE_HASZ(type), TYPE_HASM(type),
|
|
|
|
1, lwgeom_getType(type),lwgeom_hasBBOX(type));
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
loc_new = result->data;
|
|
|
|
loc_old = lwgeom->data;
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
len_left = len -4-1;// old length - size - type
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
// handle bbox (if there)
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
|
|
|
memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ;//copy in bbox
|
|
|
|
loc_new += sizeof(BOX2DFLOAT4);
|
|
|
|
loc_old += sizeof(BOX2DFLOAT4);
|
|
|
|
len_left -= sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
//put in SRID
|
2004-08-20 14:08:41 +00:00
|
|
|
|
2004-12-21 15:17:30 +00:00
|
|
|
memcpy(loc_new, &newSRID,4);
|
|
|
|
loc_new +=4;
|
|
|
|
memcpy(loc_new, loc_old, len_left);
|
|
|
|
}
|
2004-08-20 14:08:41 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2004-08-24 14:47:25 +00:00
|
|
|
|
2004-09-21 10:57:26 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
char
|
2004-09-28 09:00:33 +00:00
|
|
|
ptarray_isccw(const POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double area = 0;
|
2005-02-10 17:41:55 +00:00
|
|
|
POINT2D p1, p2;
|
2004-09-28 09:00:33 +00:00
|
|
|
|
|
|
|
for (i=0; i<pa->npoints-1; i++)
|
|
|
|
{
|
2005-02-10 17:41:55 +00:00
|
|
|
getPoint2d_p(pa, i, &p1);
|
|
|
|
getPoint2d_p(pa, i+1, &p2);
|
|
|
|
area += (p1.x * p2.y) - (p1.y * p2.x);
|
2004-09-28 09:00:33 +00:00
|
|
|
}
|
|
|
|
if ( area > 0 ) return 0;
|
|
|
|
else return 1;
|
|
|
|
}
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
// returns a BOX2DFLOAT4 that encloses b1 and b2
|
2005-03-18 12:36:27 +00:00
|
|
|
// box2d_union(NULL,A) --> A
|
|
|
|
// box2d_union(A,NULL) --> A
|
|
|
|
// box2d_union(A,B) --> A union B
|
2004-09-30 15:42:28 +00:00
|
|
|
BOX2DFLOAT4 *
|
|
|
|
box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2)
|
|
|
|
{
|
|
|
|
BOX2DFLOAT4 *result;
|
|
|
|
|
|
|
|
if ( (b1 == NULL) && (b2 == NULL) )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = lwalloc(sizeof(BOX2DFLOAT4));
|
|
|
|
|
|
|
|
if (b1 == NULL)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
memcpy(result, b2, sizeof(BOX2DFLOAT4));
|
2004-09-30 15:42:28 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (b2 == NULL)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
memcpy(result, b1, sizeof(BOX2DFLOAT4));
|
2004-09-30 15:42:28 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 result->xmax = b2->xmax;
|
|
|
|
|
|
|
|
if (b1->ymax > b2->ymax) result->ymax = b1->ymax;
|
|
|
|
else result->ymax = b2->ymax;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
/*
|
|
|
|
* ubox may be one of the two args...
|
|
|
|
* return 1 if done something to ubox, 0 otherwise.
|
|
|
|
*/
|
2004-09-30 15:42:28 +00:00
|
|
|
int
|
|
|
|
box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox)
|
|
|
|
{
|
|
|
|
if ( (b1 == NULL) && (b2 == NULL) )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1 == NULL)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
memcpy(ubox, b2, sizeof(BOX2DFLOAT4));
|
2004-09-30 15:42:28 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (b2 == NULL)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
memcpy(ubox, b1, sizeof(BOX2DFLOAT4));
|
2004-09-30 15:42:28 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1->xmin < b2->xmin) ubox->xmin = b1->xmin;
|
|
|
|
else ubox->xmin = b2->xmin;
|
|
|
|
|
|
|
|
if (b1->ymin < b2->ymin) ubox->ymin = b1->ymin;
|
|
|
|
else ubox->ymin = b2->ymin;
|
|
|
|
|
|
|
|
if (b1->xmax > b2->xmax) ubox->xmax = b1->xmax;
|
|
|
|
else ubox->xmax = b2->xmax;
|
|
|
|
|
|
|
|
if (b1->ymax > b2->ymax) ubox->ymax = b1->ymax;
|
|
|
|
else ubox->ymax = b2->ymax;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-04 13:53:42 +00:00
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
const uchar *
|
|
|
|
lwgeom_typeflags(uchar type)
|
2004-10-04 13:53:42 +00:00
|
|
|
{
|
|
|
|
static char flags[5];
|
|
|
|
int flagno=0;
|
|
|
|
if ( TYPE_HASZ(type) ) flags[flagno++] = 'Z';
|
|
|
|
if ( TYPE_HASM(type) ) flags[flagno++] = 'M';
|
|
|
|
if ( TYPE_HASBBOX(type) ) flags[flagno++] = 'B';
|
|
|
|
if ( TYPE_HASSRID(type) ) flags[flagno++] = 'S';
|
|
|
|
flags[flagno] = '\0';
|
|
|
|
//lwnotice("Flags: %s - returning %p", flags, flags);
|
|
|
|
return flags;
|
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
//given a string with at least 2 chars in it, convert them to
|
|
|
|
// a byte value. No error checking done!
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar
|
2004-10-07 10:03:23 +00:00
|
|
|
parse_hex(char *str)
|
|
|
|
{
|
|
|
|
//do this a little brute force to make it faster
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar result_high = 0;
|
|
|
|
uchar result_low = 0;
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
switch (str[0])
|
|
|
|
{
|
|
|
|
case '0' :
|
|
|
|
result_high = 0;
|
|
|
|
break;
|
|
|
|
case '1' :
|
|
|
|
result_high = 1;
|
|
|
|
break;
|
|
|
|
case '2' :
|
|
|
|
result_high = 2;
|
|
|
|
break;
|
|
|
|
case '3' :
|
|
|
|
result_high = 3;
|
|
|
|
break;
|
|
|
|
case '4' :
|
|
|
|
result_high = 4;
|
|
|
|
break;
|
|
|
|
case '5' :
|
|
|
|
result_high = 5;
|
|
|
|
break;
|
|
|
|
case '6' :
|
|
|
|
result_high = 6;
|
|
|
|
break;
|
|
|
|
case '7' :
|
|
|
|
result_high = 7;
|
|
|
|
break;
|
|
|
|
case '8' :
|
|
|
|
result_high = 8;
|
|
|
|
break;
|
|
|
|
case '9' :
|
|
|
|
result_high = 9;
|
|
|
|
break;
|
|
|
|
case 'A' :
|
|
|
|
result_high = 10;
|
|
|
|
break;
|
|
|
|
case 'B' :
|
|
|
|
result_high = 11;
|
|
|
|
break;
|
|
|
|
case 'C' :
|
|
|
|
result_high = 12;
|
|
|
|
break;
|
|
|
|
case 'D' :
|
|
|
|
result_high = 13;
|
|
|
|
break;
|
|
|
|
case 'E' :
|
|
|
|
result_high = 14;
|
|
|
|
break;
|
|
|
|
case 'F' :
|
|
|
|
result_high = 15;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (str[1])
|
|
|
|
{
|
|
|
|
case '0' :
|
|
|
|
result_low = 0;
|
|
|
|
break;
|
|
|
|
case '1' :
|
|
|
|
result_low = 1;
|
|
|
|
break;
|
|
|
|
case '2' :
|
|
|
|
result_low = 2;
|
|
|
|
break;
|
|
|
|
case '3' :
|
|
|
|
result_low = 3;
|
|
|
|
break;
|
|
|
|
case '4' :
|
|
|
|
result_low = 4;
|
|
|
|
break;
|
|
|
|
case '5' :
|
|
|
|
result_low = 5;
|
|
|
|
break;
|
|
|
|
case '6' :
|
|
|
|
result_low = 6;
|
|
|
|
break;
|
|
|
|
case '7' :
|
|
|
|
result_low = 7;
|
|
|
|
break;
|
|
|
|
case '8' :
|
|
|
|
result_low = 8;
|
|
|
|
break;
|
|
|
|
case '9' :
|
|
|
|
result_low = 9;
|
|
|
|
break;
|
|
|
|
case 'A' :
|
|
|
|
result_low = 10;
|
|
|
|
break;
|
|
|
|
case 'B' :
|
|
|
|
result_low = 11;
|
|
|
|
break;
|
|
|
|
case 'C' :
|
|
|
|
result_low = 12;
|
|
|
|
break;
|
|
|
|
case 'D' :
|
|
|
|
result_low = 13;
|
|
|
|
break;
|
|
|
|
case 'E' :
|
|
|
|
result_low = 14;
|
|
|
|
break;
|
|
|
|
case 'F' :
|
|
|
|
result_low = 15;
|
|
|
|
break;
|
|
|
|
}
|
2005-02-10 10:52:53 +00:00
|
|
|
return (uchar) ((result_high<<4) + result_low);
|
2004-10-07 10:03:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//given one byte, populate result with two byte representing
|
|
|
|
// the hex number
|
|
|
|
// ie deparse_hex( 255, mystr)
|
|
|
|
// -> mystr[0] = 'F' and mystr[1] = 'F'
|
|
|
|
// no error checking done
|
|
|
|
void
|
2005-02-10 10:52:53 +00:00
|
|
|
deparse_hex(uchar str, uchar *result)
|
2004-10-07 10:03:23 +00:00
|
|
|
{
|
|
|
|
int input_high;
|
|
|
|
int input_low;
|
|
|
|
|
|
|
|
input_high = (str>>4);
|
|
|
|
input_low = (str & 0x0F);
|
|
|
|
|
|
|
|
switch (input_high)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
result[0] = '0';
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result[0] = '1';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
result[0] = '2';
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
result[0] = '3';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
result[0] = '4';
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
result[0] = '5';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
result[0] = '6';
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
result[0] = '7';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
result[0] = '8';
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
result[0] = '9';
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
result[0] = 'A';
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
result[0] = 'B';
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
result[0] = 'C';
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
result[0] = 'D';
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
result[0] = 'E';
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
result[0] = 'F';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (input_low)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
result[1] = '0';
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result[1] = '1';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
result[1] = '2';
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
result[1] = '3';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
result[1] = '4';
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
result[1] = '5';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
result[1] = '6';
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
result[1] = '7';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
result[1] = '8';
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
result[1] = '9';
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
result[1] = 'A';
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
result[1] = 'B';
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
result[1] = 'C';
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
result[1] = 'D';
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
result[1] = 'E';
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
result[1] = 'F';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
2004-10-07 10:03:23 +00:00
|
|
|
parse_lwgeom_wkt(char *wkt_input)
|
|
|
|
{
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *serialized_form = parse_lwg(wkt_input,
|
2004-10-07 10:03:23 +00:00
|
|
|
lwalloc, lwerror);
|
|
|
|
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-10-07 10:03:23 +00:00
|
|
|
lwnotice("parse_lwgeom_wkt with %s",wkt_input);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (serialized_form == NULL)
|
|
|
|
{
|
|
|
|
lwerror("parse_WKT:: couldnt parse!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return serialized_form;
|
|
|
|
|
|
|
|
}
|