mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-23 08:32:42 +00:00
Added missing liblwgeom.c file.
Made LWMPOINT, LWMLINE, LWMPOLY compatible with LWCOLLECTION. Fixed reverse() and forcerhr() to maintain geometry structure. git-svn-id: http://svn.osgeo.org/postgis/trunk@912 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
parent
fea9afb1f7
commit
406c2623b7
91
lwgeom/liblwgeom.c
Normal file
91
lwgeom/liblwgeom.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lwgeom_pg.h"
|
||||
#include "liblwgeom.h"
|
||||
|
||||
#define CONTEXT_PG 0
|
||||
#define CONTEXT_SA 1
|
||||
|
||||
#define DEFAULT_CONTEXT CONTEXT_PG
|
||||
|
||||
/* Global variables */
|
||||
#if DEFAULT_CONTEXT == SA
|
||||
lwallocator lwalloc = default_allocator;
|
||||
lwreallocator lwrealloc = default_reallocator;
|
||||
lwfreeor lwfree = default_freeor;
|
||||
lwreporter lwerror = default_errorreporter;
|
||||
lwreporter lwnotice = default_noticereporter;
|
||||
#else
|
||||
lwallocator lwalloc = pg_alloc;
|
||||
lwreallocator lwrealloc = pg_realloc;
|
||||
lwfreeor lwfree = pg_free;
|
||||
lwreporter lwerror = pg_error;
|
||||
lwreporter lwnotice = pg_notice;
|
||||
#endif
|
||||
|
||||
|
||||
void *
|
||||
default_allocator(size_t size)
|
||||
{
|
||||
void *mem = malloc(size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void
|
||||
default_freeor(void *mem)
|
||||
{
|
||||
free(mem);
|
||||
}
|
||||
|
||||
void *
|
||||
default_reallocator(void *mem, size_t size)
|
||||
{
|
||||
void *ret = realloc(mem, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
default_noticereporter(const char *fmt, ...)
|
||||
{
|
||||
char *msg;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
|
||||
/*
|
||||
* This is a GNU extension.
|
||||
* Dunno how to handle errors here.
|
||||
*/
|
||||
if (!vasprintf (&msg, fmt, ap))
|
||||
{
|
||||
va_end (ap);
|
||||
return;
|
||||
}
|
||||
va_end(ap);
|
||||
printf("%s", msg);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
void
|
||||
default_errorreporter(const char *fmt, ...)
|
||||
{
|
||||
char *msg;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
|
||||
/*
|
||||
* This is a GNU extension.
|
||||
* Dunno how to handle errors here.
|
||||
*/
|
||||
if (!vasprintf (&msg, fmt, ap))
|
||||
{
|
||||
va_end (ap);
|
||||
return;
|
||||
}
|
||||
va_end(ap);
|
||||
fprintf(stderr, "%s", msg);
|
||||
free(msg);
|
||||
}
|
|
@ -363,7 +363,7 @@ extern BOX3D *lwline_findbbox(LWLINE *line);
|
|||
|
||||
typedef struct
|
||||
{
|
||||
char type;
|
||||
int type;
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int nrings;
|
||||
|
@ -402,8 +402,8 @@ typedef struct
|
|||
int type;
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int npoints;
|
||||
LWPOINT **points;
|
||||
int ngeoms;
|
||||
LWPOINT **geoms;
|
||||
} LWMPOINT;
|
||||
|
||||
extern size_t lwmpoint_serialize_size(LWMPOINT *mpoint);
|
||||
|
@ -415,8 +415,8 @@ typedef struct
|
|||
int type;
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int nlines;
|
||||
LWLINE **lines;
|
||||
int ngeoms;
|
||||
LWLINE **geoms;
|
||||
} LWMLINE;
|
||||
|
||||
extern size_t lwmline_serialize_size(LWMLINE *mline);
|
||||
|
@ -428,8 +428,8 @@ typedef struct
|
|||
int type;
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int npolys;
|
||||
LWPOLY **polys;
|
||||
int ngeoms;
|
||||
LWPOLY **geoms;
|
||||
} LWMPOLY;
|
||||
|
||||
extern size_t lwmpoly_serialize_size(LWMPOLY *mpoly);
|
||||
|
@ -494,7 +494,7 @@ typedef struct
|
|||
const char *serialized_form; // orginal structure
|
||||
unsigned char type; // 8-bit type for the LWGEOM
|
||||
int ngeometries; // number of sub-geometries
|
||||
char * * const sub_geoms; // list of pointers (into serialized_form) of the sub-geoms
|
||||
char **sub_geoms; // list of pointers (into serialized_form) of the sub-geoms
|
||||
} LWGEOM_INSPECTED;
|
||||
|
||||
extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
@ -861,5 +861,10 @@ extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
|
|||
extern POINTARRAY *segmentize2d_ptarray(POINTARRAY *ipa, double dist);
|
||||
extern int32 lwgeom_npoints(char *serialized);
|
||||
extern char ptarray_isccw(const POINTARRAY *pa);
|
||||
extern void lwgeom_reverse(LWGEOM *lwgeom);
|
||||
extern void lwline_reverse(LWLINE *line);
|
||||
extern void lwpoly_reverse(LWPOLY *poly);
|
||||
extern void lwpoly_forceRHR(LWPOLY *poly);
|
||||
extern void lwgeom_forceRHR(LWGEOM *lwgeom);
|
||||
|
||||
#endif // !defined _LIBLWGEOM_H
|
||||
|
|
|
@ -128,3 +128,50 @@ lwgeom_serialize(LWGEOM *lwgeom, char wantbbox)
|
|||
return serialized;
|
||||
}
|
||||
|
||||
// Force Right-hand-rule on LWGEOM polygons
|
||||
void
|
||||
lwgeom_forceRHR(LWGEOM *lwgeom)
|
||||
{
|
||||
LWCOLLECTION *coll;
|
||||
int i;
|
||||
|
||||
switch (lwgeom->type)
|
||||
{
|
||||
case POLYGONTYPE:
|
||||
lwpoly_reverse((LWPOLY *)lwgeom);
|
||||
return;
|
||||
|
||||
case MULTIPOLYGONTYPE:
|
||||
case COLLECTIONTYPE:
|
||||
coll = (LWCOLLECTION *)lwgeom;
|
||||
for (i=0; i<coll->ngeoms; i++)
|
||||
lwgeom_forceRHR(coll->geoms[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse vertex order of LWGEOM
|
||||
void
|
||||
lwgeom_reverse(LWGEOM *lwgeom)
|
||||
{
|
||||
int i;
|
||||
LWCOLLECTION *col;
|
||||
|
||||
switch (lwgeom->type)
|
||||
{
|
||||
case LINETYPE:
|
||||
lwline_reverse((LWLINE *)lwgeom);
|
||||
return;
|
||||
case POLYGONTYPE:
|
||||
lwpoly_reverse((LWPOLY *)lwgeom);
|
||||
return;
|
||||
case MULTILINETYPE:
|
||||
case MULTIPOLYGONTYPE:
|
||||
case COLLECTIONTYPE:
|
||||
col = (LWCOLLECTION *)lwgeom;
|
||||
for (i=0; i<col->ngeoms; i++)
|
||||
lwgeom_reverse(col->geoms[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
828
lwgeom/lwgeom.h
828
lwgeom/lwgeom.h
|
@ -1,826 +1,4 @@
|
|||
//lwgeom.h
|
||||
typedef struct LWGEOM_T LWGEOM;
|
||||
|
||||
// basic API for handling the LWGEOM, BOX2DFLOAT4, LWPOINT, LWLINE, and LWPOLY.
|
||||
// See below for other support types like POINTARRAY and LWGEOM_INSPECTED
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "utils/geo_decls.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float xmin;
|
||||
float ymin;
|
||||
float xmax;
|
||||
float ymax;
|
||||
} BOX2DFLOAT4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double xmin, ymin, zmin;
|
||||
double xmax, ymax, zmax;
|
||||
} BOX3D;
|
||||
|
||||
|
||||
typedef struct chiptag
|
||||
{
|
||||
int size; //unused (for use by postgresql)
|
||||
|
||||
int endian_hint; // the number 1 in the endian of this datastruct
|
||||
|
||||
BOX3D bvol;
|
||||
int SRID;
|
||||
char future[4];
|
||||
float factor; // Usually 1.0.
|
||||
// Integer values are multiplied by this number
|
||||
// to get the actual height value
|
||||
// (for sub-meter accuracy height data).
|
||||
|
||||
int datatype; // 1 = float32,
|
||||
// 5 = 24bit integer,
|
||||
// 6 = 16bit integer (short)
|
||||
// 101 = float32 (NDR),
|
||||
// 105 = 24bit integer (NDR),
|
||||
// 106=16bit int (NDR)
|
||||
|
||||
int height;
|
||||
int width;
|
||||
int compression; // 0 = no compression, 1 = differencer
|
||||
// 0x80 = new value
|
||||
// 0x7F = nodata
|
||||
|
||||
// this is provided for convenience, it should be set to
|
||||
// sizeof(chip) bytes into the struct because the serialized form is:
|
||||
// <header><data>
|
||||
// NULL when serialized
|
||||
void *data; // data[0] = bottm left,
|
||||
// data[width] = 1st pixel, 2nd row (uncompressed)
|
||||
|
||||
} CHIP;
|
||||
|
||||
/*
|
||||
* standard definition of an ellipsoid (what wkt calls a spheroid)
|
||||
* f = (a-b)/a
|
||||
* e_sq = (a*a - b*b)/(a*a)
|
||||
* b = a - fa
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double a; //semimajor axis
|
||||
double b; //semiminor axis
|
||||
double f; //flattening
|
||||
double e; //eccentricity (first)
|
||||
double e_sq; //eccentricity (first), squared
|
||||
char name[20]; //name of ellipse
|
||||
} SPHEROID;
|
||||
|
||||
|
||||
// POINT3D already defined in postgis.h
|
||||
// ALL LWGEOM structures will use POINT3D as an abstract point.
|
||||
// This means a 2d geometry will be stored as (x,y) in its serialized
|
||||
// form, but all functions will work on (x,y,0). This keeps all the
|
||||
// analysis functions simple.
|
||||
// NOTE: for GEOS integration, we'll probably set z=NaN
|
||||
// so look out - z might be NaN for 2d geometries!
|
||||
typedef struct { double x,y,z; } POINT3D;
|
||||
|
||||
|
||||
// type for 2d points. When you convert this to 3d, the
|
||||
// z component will be either 0 or NaN.
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
} POINT2D;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double m;
|
||||
} POINT4D;
|
||||
|
||||
// Point array abstracts a lot of the complexity of points and point lists.
|
||||
// It handles miss-alignment in the serialized form, 2d/3d translation
|
||||
// (2d points converted to 3d will have z=0 or NaN)
|
||||
// DONT MIX 2D and 3D POINTS! *EVERYTHING* is either one or the other
|
||||
typedef struct
|
||||
{
|
||||
char *serialized_pointlist; // array of POINT 2D, 3D or 4D.
|
||||
// probably missaligned.
|
||||
// points to a double
|
||||
char ndims; // 2=2d, 3=3d, 4=4d
|
||||
uint32 npoints;
|
||||
} POINTARRAY;
|
||||
|
||||
// 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
|
||||
extern POINT4D getPoint4d(const POINTARRAY *pa, int n);
|
||||
|
||||
// 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'.
|
||||
extern void getPoint4d_p(const POINTARRAY *pa, int n, char *point);
|
||||
|
||||
// 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
|
||||
extern POINT3D getPoint3d(const POINTARRAY *pa, int n);
|
||||
|
||||
// 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'.
|
||||
extern void getPoint3d_p(const POINTARRAY *pa, int n, char *point);
|
||||
|
||||
|
||||
// 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
|
||||
extern POINT2D getPoint2d(const POINTARRAY *pa, int n);
|
||||
|
||||
// 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'.
|
||||
extern void getPoint2d_p(const POINTARRAY *pa, int n, char *point);
|
||||
|
||||
// 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.
|
||||
extern char *getPoint(const POINTARRAY *pa, int n);
|
||||
//--- here is a macro equivalent, for speed...
|
||||
//#define getPoint(x,n) &( (x)->serialized_pointlist[((x)->ndims*8)*(n)] )
|
||||
|
||||
|
||||
// constructs a POINTARRAY.
|
||||
// NOTE: points is *not* copied, so be careful about modification (can be aligned/missaligned)
|
||||
// NOTE: ndims is descriptive - it describes what type of data 'points'
|
||||
// points to. No data conversion is done.
|
||||
extern POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints);
|
||||
|
||||
//calculate the bounding box of a set of points
|
||||
// returns a 3d box
|
||||
// if pa is 2d, then box3d's zmin/zmax will be either 0 or NaN
|
||||
// dont call on an empty pa
|
||||
extern BOX3D *pointArray_bbox(const POINTARRAY *pa);
|
||||
|
||||
//size of point represeneted in the POINTARRAY
|
||||
// 16 for 2d, 24 for 3d, 32 for 4d
|
||||
extern int pointArray_ptsize(const POINTARRAY *pa);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* LWGEOM types are an 8-bit char in this format:
|
||||
*
|
||||
* BSDDtttt
|
||||
*
|
||||
* WHERE
|
||||
* B = 16 byte BOX2DFLOAT4 follows (probably not aligned) [before SRID]
|
||||
* S = 4 byte SRID attached (0= not attached (-1), 1= attached)
|
||||
* DD = dimentionality (0=2d, 1=3d, 2= 4d)
|
||||
* tttt = actual type (as per the WKB type):
|
||||
*
|
||||
* enum wkbGeometryType {
|
||||
* wkbPoint = 1,
|
||||
* wkbLineString = 2,
|
||||
* wkbPolygon = 3,
|
||||
* wkbMultiPoint = 4,
|
||||
* wkbMultiLineString = 5,
|
||||
* wkbMultiPolygon = 6,
|
||||
* wkbGeometryCollection = 7
|
||||
* };
|
||||
*
|
||||
*/
|
||||
#define POINTTYPE 1
|
||||
#define LINETYPE 2
|
||||
#define POLYGONTYPE 3
|
||||
#define MULTIPOINTTYPE 4
|
||||
#define MULTILINETYPE 5
|
||||
#define MULTIPOLYGONTYPE 6
|
||||
#define COLLECTIONTYPE 7
|
||||
|
||||
#define TYPE_SETTYPE(c,t) (((c)&0xF0)|t)
|
||||
#define TYPE_SETDIMS(c,d) (((c)&0xCF)|d)
|
||||
#define TYPE_SETHASBBOX(c,b) (((c)&0x7F)|b)
|
||||
#define TYPE_SETHASSRID(c,s) (((c)&0xBF)|s)
|
||||
|
||||
extern bool lwgeom_hasSRID(unsigned char type); // true iff S bit is set
|
||||
extern bool lwgeom_hasBBOX(unsigned char type); // true iff B bit set
|
||||
extern int lwgeom_ndims(unsigned char type); // returns the DD value
|
||||
extern int lwgeom_getType(unsigned char type); // returns the tttt value
|
||||
|
||||
extern unsigned char lwgeom_makeType(int ndims, char hasSRID, int type);
|
||||
extern unsigned char lwgeom_makeType_full(int ndims, char hasSRID, int type, bool hasBBOX);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is the binary representation of lwgeom compatible
|
||||
* with postgresql varlena struct
|
||||
*/
|
||||
typedef struct {
|
||||
int32 size;
|
||||
unsigned char type; // encodes ndims, type, bbox presence,
|
||||
// srid presence
|
||||
char data[1];
|
||||
} PG_LWGEOM;
|
||||
|
||||
/*
|
||||
* Construct a full LWGEOM type (including size header)
|
||||
* from a serialized form.
|
||||
* The constructed LWGEOM object will be allocated using palloc
|
||||
* and the serialized form will be copied.
|
||||
* If you specify a SRID other then -1 it will be set.
|
||||
* If you request bbox (wantbbox=1) it will be extracted or computed
|
||||
* from the serialized form.
|
||||
*/
|
||||
extern PG_LWGEOM *PG_LWGEOM_construct(char *serialized, int SRID, int wantbbox);
|
||||
|
||||
/*
|
||||
* Use this macro to extract the char * required
|
||||
* by most functions from an PG_LWGEOM struct.
|
||||
* (which is an PG_LWGEOM w/out int32 size casted to char *)
|
||||
*/
|
||||
#define SERIALIZED_FORM(x) ((char *)(x))+4
|
||||
|
||||
|
||||
/*
|
||||
* This function computes the size in bytes
|
||||
* of the serialized geometries.
|
||||
*/
|
||||
extern int lwgeom_size(const char *serialized_form);
|
||||
extern int lwgeom_size_subgeom(const char *serialized_form, int geom_number);
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// all the base types (point/line/polygon) will have a
|
||||
// basic constructor, basic de-serializer, basic serializer,
|
||||
// bounding box finder and (TODO) serialized form size finder.
|
||||
//--------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char ndims; // 2=2d, 3=3d, 4=4d, 5=undef
|
||||
int SRID; // spatial ref sys
|
||||
POINTARRAY *point; // hide 2d/3d (this will be an array of 1 point)
|
||||
} LWPOINT; // "light-weight point"
|
||||
|
||||
// construct a new point. point will NOT be copied
|
||||
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
||||
extern LWPOINT *lwpoint_construct(int ndims, int SRID, POINTARRAY *point);
|
||||
|
||||
// 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)
|
||||
// Returns NULL if serialized form is not a point.
|
||||
// See serialized form doc
|
||||
extern LWPOINT *lwpoint_deserialize(char *serialized_form);
|
||||
|
||||
// Find size this point would get when serialized (no BBOX)
|
||||
extern uint32 lwpoint_size(LWPOINT *point);
|
||||
|
||||
// convert this point into its serialize form
|
||||
// result's first char will be the 8bit type. See serialized form doc
|
||||
extern char *lwpoint_serialize(LWPOINT *point);
|
||||
|
||||
// same as above, writes to buf
|
||||
extern void lwpoint_serialize_buf(LWPOINT *point, char *buf, int *size);
|
||||
|
||||
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
||||
extern BOX3D *lwpoint_findbbox(LWPOINT *point);
|
||||
|
||||
// convenience functions to hide the POINTARRAY
|
||||
extern POINT2D lwpoint_getPoint2d(const LWPOINT *point);
|
||||
extern POINT3D lwpoint_getPoint3d(const LWPOINT *point);
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char ndims; // 2=2d, 3=3d, 4=4d, 5=undef
|
||||
int SRID; // spatial ref sys -1=none
|
||||
POINTARRAY *points; // array of POINT3D
|
||||
} LWLINE; //"light-weight line"
|
||||
|
||||
// construct a new LWLINE. points will *NOT* be copied
|
||||
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
||||
extern LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points);
|
||||
|
||||
// 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
|
||||
extern LWLINE *lwline_deserialize(char *serialized_form);
|
||||
|
||||
// find the size this line would get when serialized (no BBOX)
|
||||
extern uint32 lwline_size(LWLINE *line);
|
||||
|
||||
// convert this line into its serialize form
|
||||
// result's first char will be the 8bit type. See serialized form doc
|
||||
// copies data.
|
||||
extern char *lwline_serialize(LWLINE *line);
|
||||
|
||||
// same as above, writes to buf
|
||||
extern void lwline_serialize_buf(LWLINE *line, char *buf, int *size);
|
||||
|
||||
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
||||
extern BOX3D *lwline_findbbox(LWLINE *line);
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int nrings;
|
||||
POINTARRAY **rings; // list of rings (list of points)
|
||||
} LWPOLY; // "light-weight polygon"
|
||||
|
||||
// construct a new LWPOLY. arrays (points/points per ring) will NOT be copied
|
||||
// use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
||||
extern LWPOLY *lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points);
|
||||
|
||||
// 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
|
||||
extern LWPOLY *lwpoly_deserialize(char *serialized_form);
|
||||
|
||||
// find the size this polygon would get when serialized (no bbox!)
|
||||
extern uint32 lwpoly_size(LWPOLY *poly);
|
||||
|
||||
// create the serialized form of the polygon
|
||||
// result's first char will be the 8bit type. See serialized form doc
|
||||
// points copied
|
||||
extern char *lwpoly_serialize(LWPOLY *poly);
|
||||
|
||||
// same as above, writes to buf
|
||||
extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *size);
|
||||
|
||||
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
||||
extern BOX3D *lwpoly_findbbox(LWPOLY *poly);
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
// MULTIPOINTTYPE
|
||||
typedef struct
|
||||
{
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int npoints;
|
||||
LWPOINT **points;
|
||||
} LWMPOINT;
|
||||
|
||||
// MULTILINETYPE
|
||||
typedef struct
|
||||
{
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int nlines;
|
||||
LWLINE **lines;
|
||||
} LWMLINE;
|
||||
|
||||
// MULTIPOLYGONTYPE
|
||||
typedef struct
|
||||
{
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int npolys;
|
||||
LWPOLY **polys;
|
||||
} LWMPOLY;
|
||||
|
||||
// COLLECTIONTYPE
|
||||
typedef struct
|
||||
{
|
||||
int32 SRID;
|
||||
char ndims;
|
||||
int ngeoms;
|
||||
struct LWGEOM **geoms;
|
||||
} LWCOLLECTION;
|
||||
|
||||
// LWGEOM (any type)
|
||||
typedef struct
|
||||
{
|
||||
char type;
|
||||
union {
|
||||
LWPOINT *point;
|
||||
LWMPOINT *mpoint;
|
||||
LWLINE *line;
|
||||
LWMLINE *mline;
|
||||
LWPOLY *poly;
|
||||
LWMPOLY *mpoly;
|
||||
LWCOLLECTION *collection;
|
||||
};
|
||||
} LWGEOM;
|
||||
|
||||
LWGEOM *lwgeom_deserialize(char *serializedform);
|
||||
LWMPOINT *lwmpoint_deserialize(char *serializedform);
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------
|
||||
// Multi-geometries
|
||||
//
|
||||
// These are all handled equivelently so its easy to write iterator code.
|
||||
// NOTE NOTE: you can hand in a non-multigeometry to most of these functions
|
||||
// and get usual behavior (ie. get geometry 0 on a POINT
|
||||
// will return the point).
|
||||
// This makes coding even easier since you dont have to necessarily
|
||||
// differenciate between the multi* and non-multi geometries.
|
||||
//
|
||||
// NOTE: these usually work directly off the serialized form, so
|
||||
// they're a little more difficult to handle (and slower)
|
||||
// NOTE NOTE: the get functions maybe slow, so we may want to have an "analysed"
|
||||
// lwgeom that would just have pointer to the start of each sub-geometry.
|
||||
//------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// use this version for speed. READ-ONLY!
|
||||
typedef struct
|
||||
{
|
||||
int SRID;
|
||||
const char *serialized_form; // orginal structure
|
||||
unsigned char type; // 8-bit type for the LWGEOM
|
||||
int ngeometries; // number of sub-geometries
|
||||
char * * const sub_geoms; // list of pointers (into serialized_form) of the sub-geoms
|
||||
} LWGEOM_INSPECTED;
|
||||
|
||||
extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
||||
/*
|
||||
* This structure is intended to be used for geometry collection construction.
|
||||
* Does not allow specification of collection structure
|
||||
* (serialization chooses the simpler form)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int SRID;
|
||||
int ndims;
|
||||
uint32 npoints;
|
||||
char **points;
|
||||
uint32 nlines;
|
||||
char **lines;
|
||||
uint32 npolys;
|
||||
char **polys;
|
||||
} LWGEOM_EXPLODED;
|
||||
|
||||
void pfree_exploded(LWGEOM_EXPLODED *exploded);
|
||||
|
||||
// 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);
|
||||
|
||||
/*
|
||||
* This function recursively scan the given serialized geometry
|
||||
* and returns a list of _all_ subgeoms in it (deep-first)
|
||||
*/
|
||||
extern LWGEOM_EXPLODED *lwgeom_explode(char *serialized);
|
||||
|
||||
/*
|
||||
* Return the length of the serialized form corresponding
|
||||
* to this exploded structure.
|
||||
*/
|
||||
extern uint32 lwexploded_findlength(LWGEOM_EXPLODED *exp, int wantbbox);
|
||||
|
||||
// Serialize an LWGEOM_EXPLODED object.
|
||||
// SRID and ndims will be taken from exploded structure.
|
||||
// wantbbox will determine result bbox.
|
||||
extern char *lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox);
|
||||
|
||||
// Same as lwexploded_serialize but writing to pre-allocated space
|
||||
extern void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, char *buf, int *retsize);
|
||||
|
||||
// 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.
|
||||
extern LWGEOM_INSPECTED *lwgeom_inspect(const char *serialized_form);
|
||||
|
||||
|
||||
// 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
|
||||
extern LWPOINT *lwgeom_getpoint(char *serialized_form, int geom_number);
|
||||
extern LWPOINT *lwgeom_getpoint_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
||||
// 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
|
||||
extern LWLINE *lwgeom_getline(char *serialized_form, int geom_number);
|
||||
extern LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
||||
// 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
|
||||
extern LWPOLY *lwgeom_getpoly(char *serialized_form, int geom_number);
|
||||
extern LWPOLY *lwgeom_getpoly_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
||||
// 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.
|
||||
extern char *lwgeom_getsubgeometry(const char *serialized_form, int geom_number);
|
||||
extern char *lwgeom_getsubgeometry_inspected(LWGEOM_INSPECTED *inspected, int 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
|
||||
extern char lwgeom_getsubtype(char *serialized_form, int geom_number);
|
||||
extern char lwgeom_getsubtype_inspected(LWGEOM_INSPECTED *inspected, int geom_number);
|
||||
|
||||
|
||||
// how many sub-geometries are there?
|
||||
// for point,line,polygon will return 1.
|
||||
extern int lwgeom_getnumgeometries(char *serialized_form);
|
||||
extern int lwgeom_getnumgeometries_inspected(LWGEOM_INSPECTED *inspected);
|
||||
|
||||
|
||||
|
||||
// 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...
|
||||
extern char *lwgeom_construct(int SRID,int finalType,int ndims, int nsubgeometries, char **serialized_subs);
|
||||
|
||||
|
||||
// construct the empty geometry (GEOMETRYCOLLECTION(EMPTY))
|
||||
extern char *lwgeom_constructempty(int SRID,int ndims);
|
||||
extern void lwgeom_constructempty_buf(int SRID, int ndims, char *buf, int *size);
|
||||
int lwgeom_empty_length(int SRID);
|
||||
|
||||
// get the SRID from the LWGEOM
|
||||
// none present => -1
|
||||
extern int lwgeom_getSRID(PG_LWGEOM *lwgeom);
|
||||
extern int lwgeom_getsrid(char *serialized);
|
||||
extern PG_LWGEOM *lwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID);
|
||||
|
||||
//get bounding box of LWGEOM (automatically calls the sub-geometries bbox generators)
|
||||
extern BOX3D *lw_geom_getBB(char *serialized_form);
|
||||
extern BOX3D *lw_geom_getBB_inspected(LWGEOM_INSPECTED *inspected);
|
||||
|
||||
|
||||
//------------------------------------------------------
|
||||
// other stuff
|
||||
|
||||
// handle the double-to-float conversion. The results of this
|
||||
// will usually be a slightly bigger box because of the difference
|
||||
// between float8 and float4 representations.
|
||||
|
||||
extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box);
|
||||
extern int box3d_to_box2df_p(BOX3D *box, BOX2DFLOAT4 *res);
|
||||
extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box);
|
||||
extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d);
|
||||
|
||||
extern BOX2DFLOAT4 *box_to_box2df(BOX *box); // postgresql standard type
|
||||
extern BOX box2df_to_box(BOX2DFLOAT4 *box); // postgresql standard type
|
||||
extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type
|
||||
|
||||
extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2);
|
||||
|
||||
|
||||
// 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.
|
||||
// WARNING! the EMPTY geom will result in a random BOX2D returned
|
||||
extern BOX2DFLOAT4 getbox2d(char *serialized_form);
|
||||
|
||||
// this function writes to 'box' and returns 0 if serialized_form
|
||||
// does not have a bounding box (empty geom)
|
||||
extern int getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box);
|
||||
|
||||
// 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!
|
||||
extern const BOX2DFLOAT4 * getbox2d_internal(char *serialized_form);
|
||||
|
||||
// Expand given box of 'd' units in all directions
|
||||
void expand_box2d(BOX2DFLOAT4 *box, double d);
|
||||
void expand_box3d(BOX3D *box, double d);
|
||||
|
||||
//****************************************************************
|
||||
// memory management -- these only delete the memory associated
|
||||
// directly with the structure - NOT the stuff pointing into
|
||||
// the original de-serialized info
|
||||
|
||||
extern void pfree_inspected(LWGEOM_INSPECTED *inspected);
|
||||
extern void pfree_point (LWPOINT *pt);
|
||||
extern void pfree_line (LWLINE *line);
|
||||
extern void pfree_polygon (LWPOLY *poly);
|
||||
extern void pfree_POINTARRAY(POINTARRAY *pa);
|
||||
|
||||
|
||||
//***********************************************************
|
||||
// utility
|
||||
|
||||
extern uint32 get_uint32(const char *loc);
|
||||
extern int32 get_int32(const char *loc);
|
||||
extern void printPA(POINTARRAY *pa);
|
||||
extern void printLWPOINT(LWPOINT *point);
|
||||
extern void printLWLINE(LWLINE *line);
|
||||
extern void printLWPOLY(LWPOLY *poly);
|
||||
extern void printBYTES(unsigned char *a, int n);
|
||||
extern void printMULTI(char *serialized);
|
||||
extern void deparse_hex(unsigned char str, unsigned char *result);
|
||||
extern void printType(unsigned char str);
|
||||
|
||||
|
||||
//------------------------------------------------------------
|
||||
//------------------------------------------------------------
|
||||
// On serialized form (see top for the 8bit type implementation)
|
||||
|
||||
// NOTE: contrary to the original proposal, bounding boxes are *never*
|
||||
// included in the geometry. You must either refer to the index
|
||||
// or compute it on demand.
|
||||
|
||||
|
||||
// The serialized form is always a stream of bytes. The first four are always
|
||||
// the memory size of the LWGEOM (including the 4 byte memory size).
|
||||
|
||||
// The easiest way to describe the serialed form is with examples:
|
||||
// (more examples are available in the postgis mailing list)
|
||||
|
||||
//3D point w/o bounding box::
|
||||
//<int32> size = 29 bytes
|
||||
//<char> type: S=0,D=1, tttt= 1
|
||||
//<double> X
|
||||
//<double> Y
|
||||
//<double> Z
|
||||
|
||||
//2D line String
|
||||
//<int32> size = ...
|
||||
//<char> type: S=0,D=0, tttt= 2
|
||||
//<uint32> npoints
|
||||
//<double> X0
|
||||
//<double> Y0
|
||||
//<double> X1
|
||||
//<double> Y1
|
||||
//<double> X2
|
||||
//<double> Y2
|
||||
//...
|
||||
|
||||
//3D polygon w/o bounding box
|
||||
//<int32> size = ...
|
||||
//<char> type: S=0,D=0, tttt= 3
|
||||
//<uint32> nrings
|
||||
//<uint32> npoints in ring0
|
||||
//<double> X0
|
||||
//<double> Y0
|
||||
//<double> X1
|
||||
//<double> Y1
|
||||
//<double> X2
|
||||
//<double> Y2
|
||||
//...
|
||||
//<uint32> npoints in ring1
|
||||
//<double> X0
|
||||
//<double> Y0
|
||||
//<double> X1
|
||||
//<double> Y1
|
||||
//<double> X2
|
||||
//<double> Y2
|
||||
//...
|
||||
//...
|
||||
|
||||
|
||||
// the multi* representations are very simple
|
||||
|
||||
//<int32> size = ...
|
||||
//<char> type: ... with tttt= <multi* or geometrycollection>
|
||||
//<int32> ngeometries
|
||||
// <geometry zero, serialized form>
|
||||
// <geometry one, serialized form>
|
||||
// <geometry two, serialzied form>
|
||||
// ...
|
||||
|
||||
|
||||
|
||||
// see implementation for more exact details.
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// example function (computes total length of the lines in a LWGEOM).
|
||||
// This works for a LINESTRING, MULTILINESTRING, OR GEOMETRYCOLLECTION
|
||||
|
||||
|
||||
|
||||
// char *serialized_form = (char *) [[get from database]]
|
||||
//
|
||||
// double total_length_so_far = 0;
|
||||
// for (int t=0;t< lwgeom_getnumgeometries(serialized_form) ; t++)
|
||||
// {
|
||||
// LWLINE *line = lwgeom_getline(serialized_form, t);
|
||||
// if (line != NULL)
|
||||
// {
|
||||
// double length = findlength( POINT_ARRAY(line->points) ); //2d/3d aware
|
||||
// total_length_so_far + = length;
|
||||
// }
|
||||
// }
|
||||
// return total_length_so_far;
|
||||
|
||||
|
||||
// using the LWGEOM_INSPECTED way:
|
||||
|
||||
|
||||
// char *serialized_form = (char *) [[get from datbase]]
|
||||
// LWGEOM_INSPECTED inspected_geom = lwgeom_inspect(serialized_form);
|
||||
//
|
||||
// double total_length_so_far = 0;
|
||||
// for (int t=0;t< lwgeom_getnumgeometries(inspected_geom) ; t++)
|
||||
// {
|
||||
// LWLINE *line = lwgeom_getline(inspected_geom, t);
|
||||
// if (line != NULL)
|
||||
// {
|
||||
// double length = findlength( POINT_ARRAY(line->points) ); //2d/3d aware
|
||||
// total_length_so_far + = length;
|
||||
// }
|
||||
// }
|
||||
// return total_length_so_far;
|
||||
|
||||
|
||||
// the findlength() function could be written like based on functions like:
|
||||
//
|
||||
// POINT3D getPoint3d(POINTARRAY pa, int n); (for a 2d/3d point and 3d length)
|
||||
// POINT2D getPoint2d(POINTARRAY pa, int n); (for a 2d/3d point and 2d length)
|
||||
// NOTE: make sure your findlength() function knows what to do with z=NaN.
|
||||
|
||||
|
||||
|
||||
|
||||
// other forwards (for indirect function calls)
|
||||
|
||||
extern float LWGEOM_Minf(float a, float b);
|
||||
extern float LWGEOM_Maxf(float a, float b);
|
||||
extern double LWGEOM_Mind(double a, double b);
|
||||
extern double LWGEOM_Maxd(double a, double b);
|
||||
|
||||
|
||||
|
||||
extern BOX3D *lw_geom_getBB_simple(char *serialized_form);
|
||||
|
||||
extern float nextDown_f(double d);
|
||||
extern float nextUp_f(double d);
|
||||
extern double nextDown_d(float d);
|
||||
extern double nextUp_d(float d);
|
||||
|
||||
|
||||
|
||||
#if ! defined(__MINGW32__)
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
#endif
|
||||
#define abs(a) ((a) < (0) ? (-a) : (a))
|
||||
|
||||
|
||||
// general utilities
|
||||
extern double lwgeom_polygon_area(LWPOLY *poly);
|
||||
extern double lwgeom_polygon_perimeter(LWPOLY *poly);
|
||||
extern double lwgeom_polygon_perimeter2d(LWPOLY *poly);
|
||||
extern double lwgeom_pointarray_length2d(POINTARRAY *pts);
|
||||
extern double lwgeom_pointarray_length(POINTARRAY *pts);
|
||||
extern void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize);
|
||||
extern void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize);
|
||||
extern void lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize);
|
||||
extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
|
||||
extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
|
||||
extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
|
||||
extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
|
||||
extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
|
||||
extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
|
||||
extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
|
||||
extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
|
||||
extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
|
||||
extern double distance2d_point_line(LWPOINT *point, LWLINE *line);
|
||||
extern double distance2d_line_line(LWLINE *line1, LWLINE *line2);
|
||||
extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
|
||||
extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
|
||||
extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
|
||||
extern double lwgeom_mindistance2d_recursive(char *lw1, char *lw2);
|
||||
extern void lwgeom_translate_recursive(char *serialized, double xoff, double yoff, double zoff);
|
||||
extern void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff);
|
||||
extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
|
||||
extern POINTARRAY *segmentize2d_ptarray(POINTARRAY *ipa, double dist);
|
||||
extern int32 lwgeom_npoints(char *serialized);
|
||||
extern bool ptarray_isccw(const POINTARRAY *pa);
|
||||
extern void lwgeom_reverse(LWGEOM *lwgeom);
|
||||
extern void lwgeom_forceRHR(LWGEOM *lwgeom);
|
||||
|
|
|
@ -939,8 +939,8 @@ lwgeom_inspect(const char *serialized_form)
|
|||
//simple geometry (point/line/polygon)-- not multi!
|
||||
result->ngeometries = 1;
|
||||
sub_geoms = (char**) lwalloc(sizeof(char*));
|
||||
sub_geoms[0] = serialized_form;
|
||||
result->sub_geoms = sub_geoms;
|
||||
sub_geoms[0] = (char *)serialized_form;
|
||||
result->sub_geoms = (char **)sub_geoms;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -963,7 +963,7 @@ lwgeom_inspect(const char *serialized_form)
|
|||
|
||||
sub_geoms = (char**) lwalloc(sizeof(char*) * result->ngeometries );
|
||||
result->sub_geoms = sub_geoms;
|
||||
sub_geoms[0] = loc;
|
||||
sub_geoms[0] = (char *)loc;
|
||||
#ifdef DEBUG
|
||||
lwnotice("subgeom[0] @ %p", sub_geoms[0]);
|
||||
#endif
|
||||
|
|
|
@ -53,10 +53,8 @@ char * lwgeom_summary_recursive(char *serialized, int offset);
|
|||
char * lwgeom_summary(LWGEOM *serialized, int offset);
|
||||
int32 lwgeom_nrings_recursive(char *serialized);
|
||||
void dump_lwexploded(LWGEOM_EXPLODED *exploded);
|
||||
POINTARRAY *ptarray_reverse(const POINTARRAY *pa);
|
||||
LWLINE *lwline_reverse(const LWLINE *line);
|
||||
LWPOLY *lwpoly_reverse(const LWPOLY *poly);
|
||||
LWPOLY *lwpoly_forceRHR(const LWPOLY *poly);
|
||||
void ptarray_reverse(POINTARRAY *pa);
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
|
@ -759,88 +757,59 @@ lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad)
|
|||
|
||||
}
|
||||
|
||||
POINTARRAY *
|
||||
ptarray_reverse(const POINTARRAY *ipa)
|
||||
void
|
||||
ptarray_reverse(POINTARRAY *pa)
|
||||
{
|
||||
POINTARRAY *opa;
|
||||
uint32 i, j;
|
||||
int ptsize;
|
||||
POINT4D pbuf;
|
||||
uint32 i;
|
||||
int ptsize = pointArray_ptsize(pa);
|
||||
int last = pa->npoints-1;
|
||||
int mid = last/2;
|
||||
|
||||
opa = (POINTARRAY *)lwalloc(sizeof(POINTARRAY));
|
||||
opa->ndims = ipa->ndims;
|
||||
opa->npoints = ipa->npoints;
|
||||
ptsize = pointArray_ptsize(ipa);
|
||||
opa->serialized_pointlist = lwalloc(ipa->npoints*ptsize);
|
||||
|
||||
for (i=0, j=ipa->npoints-1; i<ipa->npoints; i++, j--)
|
||||
for (i=0; i<=mid; i++)
|
||||
{
|
||||
memcpy(getPoint(opa, j), getPoint(ipa, i), ptsize);
|
||||
char *from, *to;
|
||||
from = getPoint(pa, i);
|
||||
to = getPoint(pa, (last-i));
|
||||
memcpy((char *)&pbuf, to, ptsize);
|
||||
memcpy(to, from, ptsize);
|
||||
memcpy(from, (char *)&pbuf, ptsize);
|
||||
}
|
||||
|
||||
return opa;
|
||||
}
|
||||
|
||||
LWLINE *
|
||||
lwline_reverse(const LWLINE *iline)
|
||||
void
|
||||
lwline_reverse(LWLINE *line)
|
||||
{
|
||||
LWLINE *oline;
|
||||
POINTARRAY *rpa = ptarray_reverse(iline->points);
|
||||
|
||||
oline = lwline_construct(iline->ndims, iline->SRID, rpa);
|
||||
return oline;
|
||||
ptarray_reverse(line->points);
|
||||
}
|
||||
|
||||
LWPOLY *
|
||||
lwpoly_reverse(const LWPOLY *ipoly)
|
||||
void
|
||||
lwpoly_reverse(LWPOLY *poly)
|
||||
{
|
||||
LWPOLY *opoly;
|
||||
POINTARRAY **rpa;
|
||||
int i;
|
||||
|
||||
rpa = lwalloc(sizeof(POINTARRAY *)*ipoly->nrings);
|
||||
|
||||
for (i=0; i<ipoly->nrings; i++)
|
||||
{
|
||||
rpa[i] = ptarray_reverse(ipoly->rings[i]);
|
||||
}
|
||||
|
||||
opoly = lwpoly_construct(ipoly->ndims, ipoly->SRID,
|
||||
ipoly->nrings, rpa);
|
||||
|
||||
return opoly;
|
||||
for (i=0; i<poly->nrings; i++)
|
||||
ptarray_reverse(poly->rings[i]);
|
||||
}
|
||||
|
||||
LWPOLY *
|
||||
lwpoly_forceRHR(const LWPOLY *ipoly)
|
||||
void
|
||||
lwpoly_forceRHR(LWPOLY *poly)
|
||||
{
|
||||
LWPOLY *opoly;
|
||||
POINTARRAY **rpa;
|
||||
int i;
|
||||
POINTARRAY *opa;
|
||||
|
||||
rpa = lwalloc(sizeof(POINTARRAY *)*ipoly->nrings);
|
||||
|
||||
if ( ptarray_isccw(ipoly->rings[0]) )
|
||||
if ( ptarray_isccw(poly->rings[0]) )
|
||||
{
|
||||
opa = ipoly->rings[0];
|
||||
rpa[0] = ptarray_reverse(ipoly->rings[0]);
|
||||
ptarray_reverse(poly->rings[0]);
|
||||
}
|
||||
else rpa[0] = ipoly->rings[0];
|
||||
|
||||
for (i=1; i<ipoly->nrings; i++)
|
||||
for (i=1; i<poly->nrings; i++)
|
||||
{
|
||||
if ( ! ptarray_isccw(ipoly->rings[i]) )
|
||||
if ( ! ptarray_isccw(poly->rings[i]) )
|
||||
{
|
||||
opa = ipoly->rings[i];
|
||||
rpa[i] = ptarray_reverse(ipoly->rings[i]);
|
||||
ptarray_reverse(poly->rings[i]);
|
||||
}
|
||||
else rpa[i] = ipoly->rings[i];
|
||||
}
|
||||
|
||||
opoly = lwpoly_construct(ipoly->ndims, ipoly->SRID,
|
||||
ipoly->nrings, rpa);
|
||||
|
||||
return opoly;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
@ -917,16 +886,16 @@ lwmpoint_summary(LWMPOINT *mpoint, int offset)
|
|||
{
|
||||
char *result = lwalloc(60);
|
||||
sprintf(result, "Object %d is a MULTIPOINT() with %d points\n",
|
||||
offset, mpoint->npoints);
|
||||
offset, mpoint->ngeoms);
|
||||
return result;
|
||||
}
|
||||
|
||||
char *
|
||||
lwmline_summary(LWMLINE *mline, int offset)
|
||||
{
|
||||
char *result = lwalloc(60*(mline->nlines+1));
|
||||
char *result = lwalloc(60*(mline->ngeoms+1));
|
||||
sprintf(result, "Object %d is a MULTILINE() with %d lines\n",
|
||||
offset, mline->nlines);
|
||||
offset, mline->ngeoms);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -939,11 +908,11 @@ lwmpoly_summary(LWMPOLY *mpoly, int offset)
|
|||
int i;
|
||||
|
||||
sprintf(result, "Object %d is a MULTIPOLYGON() with %d polys\n",
|
||||
offset, mpoly->npolys);
|
||||
offset, mpoly->ngeoms);
|
||||
|
||||
for (i=0; i<mpoly->npolys; i++)
|
||||
for (i=0; i<mpoly->ngeoms; i++)
|
||||
{
|
||||
tmp = lwpoly_summary(mpoly->polys[i], i);
|
||||
tmp = lwpoly_summary(mpoly->geoms[i], i);
|
||||
size += strlen(tmp)+1;
|
||||
result = lwrealloc(result, size);
|
||||
strcat(result, tmp);
|
||||
|
@ -2977,51 +2946,14 @@ PG_FUNCTION_INFO_V1(LWGEOM_reverse);
|
|||
Datum LWGEOM_reverse(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_LWGEOM *geom;
|
||||
PG_LWGEOM *result = NULL;
|
||||
LWGEOM_EXPLODED *exp;
|
||||
int size;
|
||||
int wantbbox;
|
||||
int i;
|
||||
LWGEOM *lwgeom;
|
||||
|
||||
geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
||||
geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
|
||||
|
||||
if ( lwgeom_getType(geom->type) == COLLECTIONTYPE )
|
||||
{
|
||||
elog(ERROR, "Collection reversing is not supported");
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom));
|
||||
lwgeom_reverse(lwgeom);
|
||||
|
||||
wantbbox = lwgeom_hasBBOX(geom->type);
|
||||
exp = lwgeom_explode(SERIALIZED_FORM(geom));
|
||||
|
||||
for (i=0; i<exp->nlines; i++)
|
||||
{
|
||||
LWLINE *line = lwline_deserialize(exp->lines[i]);
|
||||
LWLINE *rline = lwline_reverse(line);
|
||||
pfree_line(line);
|
||||
exp->lines[i] = lwline_serialize(rline);
|
||||
}
|
||||
|
||||
for (i=0; i<exp->npolys; i++)
|
||||
{
|
||||
LWPOLY *poly = lwpoly_deserialize(exp->polys[i]);
|
||||
LWPOLY *rpoly = lwpoly_reverse(poly);
|
||||
pfree_polygon(poly);
|
||||
exp->polys[i] = lwpoly_serialize(rpoly);
|
||||
}
|
||||
|
||||
size = lwexploded_findlength(exp, wantbbox);
|
||||
result = lwalloc(size+4);
|
||||
result->size = (size+4);
|
||||
lwexploded_serialize_buf(exp, wantbbox, SERIALIZED_FORM(result), &size);
|
||||
|
||||
if ( result->size != (size+4) )
|
||||
{
|
||||
elog(ERROR, "lwexploded_serialize_buf wrote %d bytes, lwexploded_findlength returned %d", size, result->size-4);
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
PG_RETURN_POINTER(geom);
|
||||
}
|
||||
|
||||
// Force polygons of the collection to obey Right-Hand-Rule
|
||||
|
@ -3029,41 +2961,12 @@ PG_FUNCTION_INFO_V1(LWGEOM_forceRHR_poly);
|
|||
Datum LWGEOM_forceRHR_poly(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_LWGEOM *geom;
|
||||
PG_LWGEOM *result = NULL;
|
||||
LWGEOM_EXPLODED *exp;
|
||||
int size;
|
||||
int wantbbox;
|
||||
int i;
|
||||
LWGEOM *lwgeom;
|
||||
|
||||
geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
|
||||
geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
|
||||
|
||||
if ( lwgeom_getType(geom->type) != POLYGONTYPE &&
|
||||
lwgeom_getType(geom->type) != MULTIPOLYGONTYPE )
|
||||
{
|
||||
elog(ERROR, "Only polygon|multipolygon supported");
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom));
|
||||
lwgeom_forceRHR(lwgeom);
|
||||
|
||||
wantbbox = lwgeom_hasBBOX(geom->type);
|
||||
exp = lwgeom_explode(SERIALIZED_FORM(geom));
|
||||
|
||||
for (i=0; i<exp->npolys; i++)
|
||||
{
|
||||
LWPOLY *poly = lwpoly_deserialize(exp->polys[i]);
|
||||
LWPOLY *rpoly = lwpoly_reverse(poly);
|
||||
exp->polys[i] = lwpoly_serialize(rpoly);
|
||||
}
|
||||
|
||||
size = lwexploded_findlength(exp, wantbbox);
|
||||
result = lwalloc(size+4);
|
||||
result->size = (size+4);
|
||||
lwexploded_serialize_buf(exp, wantbbox, SERIALIZED_FORM(result), &size);
|
||||
|
||||
if ( result->size != (size+4) )
|
||||
{
|
||||
elog(ERROR, "lwexploded_serialize_buf wrote %d bytes, lwexploded_findlength returned %d", size, result->size-4);
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
PG_RETURN_POINTER(geom);
|
||||
}
|
||||
|
|
|
@ -24,16 +24,16 @@ lwmline_deserialize(char *srl)
|
|||
result->type = MULTILINETYPE;
|
||||
result->SRID = insp->SRID;
|
||||
result->ndims = lwgeom_ndims(insp->type);
|
||||
result->nlines = insp->ngeometries;
|
||||
result->lines = lwalloc(sizeof(LWLINE *)*insp->ngeometries);
|
||||
result->ngeoms = insp->ngeometries;
|
||||
result->geoms = lwalloc(sizeof(LWLINE *)*insp->ngeometries);
|
||||
|
||||
for (i=0; i<insp->ngeometries; i++)
|
||||
{
|
||||
result->lines[i] = lwline_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->lines[i]->ndims != result->ndims )
|
||||
result->geoms[i] = lwline_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->geoms[i]->ndims != result->ndims )
|
||||
{
|
||||
lwerror("Mixed dimensions (multiline:%d, line%d:%d)",
|
||||
result->ndims, i, result->lines[i]->ndims);
|
||||
result->ndims, i, result->geoms[i]->ndims);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ lwmline_serialize_size(LWMLINE *mline)
|
|||
|
||||
if ( mline->SRID != -1 ) size += 4; // SRID
|
||||
|
||||
for (i=0; i<mline->nlines; i++)
|
||||
size += lwline_serialize_size(mline->lines[i]);
|
||||
for (i=0; i<mline->ngeoms; i++)
|
||||
size += lwline_serialize_size(mline->geoms[i]);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -83,14 +83,14 @@ lwmline_serialize_buf(LWMLINE *mline, char *buf, int *retsize)
|
|||
}
|
||||
|
||||
// Write number of subgeoms
|
||||
memcpy(loc, &mline->nlines, 4);
|
||||
memcpy(loc, &mline->ngeoms, 4);
|
||||
size += 4;
|
||||
loc += 4;
|
||||
|
||||
// Serialize subgeoms
|
||||
for (i=0; i<mline->nlines; i++)
|
||||
for (i=0; i<mline->ngeoms; i++)
|
||||
{
|
||||
lwline_serialize_buf(mline->lines[i], loc, &subsize);
|
||||
lwline_serialize_buf(mline->geoms[i], loc, &subsize);
|
||||
size += subsize;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,16 +24,16 @@ lwmpoint_deserialize(char *srl)
|
|||
result->type = MULTIPOINTTYPE;
|
||||
result->SRID = insp->SRID;
|
||||
result->ndims = lwgeom_ndims(insp->type);
|
||||
result->npoints = insp->ngeometries;
|
||||
result->points = lwalloc(sizeof(LWPOINT *)*result->npoints);
|
||||
result->ngeoms = insp->ngeometries;
|
||||
result->geoms = lwalloc(sizeof(LWPOINT *)*result->ngeoms);
|
||||
|
||||
for (i=0; i<insp->ngeometries; i++)
|
||||
{
|
||||
result->points[i] = lwpoint_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->points[i]->ndims != result->ndims )
|
||||
result->geoms[i] = lwpoint_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->geoms[i]->ndims != result->ndims )
|
||||
{
|
||||
lwerror("Mixed dimensions (multipoint:%d, point%d:%d)",
|
||||
result->ndims, i, result->points[i]->ndims);
|
||||
result->ndims, i, result->geoms[i]->ndims);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ lwmpoint_serialize_size(LWMPOINT *mpoint)
|
|||
|
||||
if ( mpoint->SRID != -1 ) size += 4; // SRID
|
||||
|
||||
for (i=0; i<mpoint->npoints; i++)
|
||||
size += lwpoint_serialize_size(mpoint->points[i]);
|
||||
for (i=0; i<mpoint->ngeoms; i++)
|
||||
size += lwpoint_serialize_size(mpoint->geoms[i]);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -83,14 +83,14 @@ lwmpoint_serialize_buf(LWMPOINT *mpoint, char *buf, int *retsize)
|
|||
}
|
||||
|
||||
// Write number of subgeoms
|
||||
memcpy(loc, &mpoint->npoints, 4);
|
||||
memcpy(loc, &mpoint->ngeoms, 4);
|
||||
size += 4;
|
||||
loc += 4;
|
||||
|
||||
// Serialize subgeoms
|
||||
for (i=0; i<mpoint->npoints; i++)
|
||||
for (i=0; i<mpoint->ngeoms; i++)
|
||||
{
|
||||
lwpoint_serialize_buf(mpoint->points[i], loc, &subsize);
|
||||
lwpoint_serialize_buf(mpoint->geoms[i], loc, &subsize);
|
||||
size += subsize;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <string.h>
|
||||
#include "liblwgeom.h"
|
||||
|
||||
//#define DEBUG_CALLS 1
|
||||
|
||||
LWMPOLY *
|
||||
lwmpoly_deserialize(char *srl)
|
||||
{
|
||||
|
@ -11,6 +13,10 @@ lwmpoly_deserialize(char *srl)
|
|||
int type = lwgeom_getType(srl[0]);
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG_CALLS
|
||||
lwnotice("lwmpoly_deserialize called");
|
||||
#endif
|
||||
|
||||
if ( type != MULTIPOLYGONTYPE )
|
||||
{
|
||||
lwerror("lwmpoly_deserialize called on NON multipoly: %d",
|
||||
|
@ -21,20 +27,19 @@ lwmpoly_deserialize(char *srl)
|
|||
insp = lwgeom_inspect(srl);
|
||||
|
||||
result = lwalloc(sizeof(LWMPOLY));
|
||||
result->type = srl[0];
|
||||
result->type = MULTIPOLYGONTYPE;
|
||||
result->SRID = insp->SRID;
|
||||
result->ndims = lwgeom_ndims(insp->type);
|
||||
result->npolys = insp->ngeometries;
|
||||
result->polys = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
|
||||
result->ngeoms = insp->ngeometries;
|
||||
result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries);
|
||||
|
||||
for (i=0; i<insp->ngeometries; i++)
|
||||
{
|
||||
result->polys[i] = lwpoly_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->polys[i]->ndims != result->ndims )
|
||||
result->geoms[i] = lwpoly_deserialize(insp->sub_geoms[i]);
|
||||
if ( result->geoms[i]->ndims != result->ndims )
|
||||
{
|
||||
lwerror("Mixed dimensions (multipoly:%d, poly%d:%d)",
|
||||
result->ndims, i, result->polys[i]->ndims);
|
||||
result->ndims, i, result->geoms[i]->ndims);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +56,8 @@ lwmpoly_serialize_size(LWMPOLY *mpoly)
|
|||
|
||||
if ( mpoly->SRID != -1 ) size += 4; // SRID
|
||||
|
||||
for (i=0; i<mpoly->npolys; i++)
|
||||
size += lwpoly_serialize_size(mpoly->polys[i]);
|
||||
for (i=0; i<mpoly->ngeoms; i++)
|
||||
size += lwpoly_serialize_size(mpoly->geoms[i]);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -84,14 +89,14 @@ lwmpoly_serialize_buf(LWMPOLY *mpoly, char *buf, int *retsize)
|
|||
}
|
||||
|
||||
// Write number of subgeoms
|
||||
memcpy(loc, &mpoly->npolys, 4);
|
||||
memcpy(loc, &mpoly->ngeoms, 4);
|
||||
size += 4;
|
||||
loc += 4;
|
||||
|
||||
// Serialize subgeoms
|
||||
for (i=0; i<mpoly->npolys; i++)
|
||||
for (i=0; i<mpoly->ngeoms; i++)
|
||||
{
|
||||
lwpoly_serialize_buf(mpoly->polys[i], loc, &subsize);
|
||||
lwpoly_serialize_buf(mpoly->geoms[i], loc, &subsize);
|
||||
size += subsize;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue