2004-09-29 10:50:30 +00:00
|
|
|
// basic LWPOLY manipulation
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "liblwgeom.h"
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
//#define PGIS_DEBUG_CALLS 1
|
2004-10-03 15:52:23 +00:00
|
|
|
|
2004-10-07 10:03:23 +00:00
|
|
|
#define CHECK_POLY_RINGS_ZM 1
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
// 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)
|
|
|
|
LWPOLY *
|
2004-10-08 13:20:55 +00:00
|
|
|
lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox, unsigned int nrings, POINTARRAY **points)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
LWPOLY *result;
|
2004-10-07 10:03:23 +00:00
|
|
|
int hasz, hasm;
|
|
|
|
#ifdef CHECK_POLY_RINGS_ZM
|
|
|
|
char zm;
|
|
|
|
unsigned int i;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring");
|
|
|
|
|
|
|
|
hasz = TYPE_HASZ(points[0]->dims);
|
|
|
|
hasm = TYPE_HASM(points[0]->dims);
|
|
|
|
|
|
|
|
#ifdef CHECK_POLY_RINGS_ZM
|
|
|
|
zm = TYPE_GETZM(points[0]->dims);
|
|
|
|
for (i=1; i<nrings; i++)
|
|
|
|
{
|
|
|
|
if ( zm != TYPE_GETZM(points[i]->dims) )
|
|
|
|
lwerror("lwpoly_construct: mixed dimensioned rings");
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
|
2004-10-05 16:28:34 +00:00
|
|
|
result->type = lwgeom_makeType_full(hasz, hasm, (SRID!=-1), POLYGONTYPE,
|
2004-10-08 13:20:55 +00:00
|
|
|
0);
|
2004-09-29 10:50:30 +00:00
|
|
|
result->SRID = SRID;
|
|
|
|
result->nrings = nrings;
|
|
|
|
result->rings = points;
|
2004-10-08 13:20:55 +00:00
|
|
|
result->bbox = bbox;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// given the LWPOLY serialized form (or a pointer into a muli* one)
|
|
|
|
// construct a proper LWPOLY.
|
|
|
|
// serialized_form should point to the 8bit type format (with type = 3)
|
|
|
|
// See serialized form doc
|
|
|
|
LWPOLY *
|
2005-02-10 10:52:53 +00:00
|
|
|
lwpoly_deserialize(uchar *serialized_form)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
LWPOLY *result;
|
|
|
|
uint32 nrings;
|
2004-10-05 16:28:34 +00:00
|
|
|
int ndims, hasz, hasm;
|
2004-09-29 10:50:30 +00:00
|
|
|
uint32 npoints;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type;
|
2004-09-29 10:50:30 +00:00
|
|
|
char *loc;
|
|
|
|
int t;
|
|
|
|
|
|
|
|
if (serialized_form == NULL)
|
|
|
|
{
|
|
|
|
lwerror("lwpoly_deserialize called with NULL arg");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
|
|
|
|
|
|
|
|
type = (unsigned char) serialized_form[0];
|
2004-10-04 13:53:42 +00:00
|
|
|
result->type = type;
|
2004-09-29 15:25:21 +00:00
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
ndims = TYPE_NDIMS(type);
|
|
|
|
hasz = TYPE_HASZ(type);
|
|
|
|
hasm = TYPE_HASM(type);
|
2004-09-29 10:50:30 +00:00
|
|
|
loc = serialized_form;
|
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
if ( TYPE_GETTYPE(type) != POLYGONTYPE)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
lwerror("lwpoly_deserialize called with arg of type %d",
|
|
|
|
lwgeom_getType(type));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
2004-10-08 13:20:55 +00:00
|
|
|
if (lwgeom_hasBBOX(type)) {
|
2005-11-14 09:01:15 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
|
|
|
lwnotice("lwpoly_deserialize: input has bbox");
|
|
|
|
#endif
|
|
|
|
result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
|
|
|
|
memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
|
2004-09-29 10:50:30 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
2004-10-08 13:20:55 +00:00
|
|
|
} else {
|
|
|
|
result->bbox = NULL;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
|
|
|
result->SRID = get_int32(loc);
|
|
|
|
loc +=4; // type + SRID
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->SRID = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nrings = get_uint32(loc);
|
|
|
|
result->nrings = nrings;
|
|
|
|
loc +=4;
|
|
|
|
result->rings = (POINTARRAY**) lwalloc(nrings* sizeof(POINTARRAY*));
|
|
|
|
|
|
|
|
for (t =0;t<nrings;t++)
|
|
|
|
{
|
|
|
|
//read in a single ring and make a PA
|
|
|
|
npoints = get_uint32(loc);
|
|
|
|
loc +=4;
|
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
result->rings[t] = pointArray_construct(loc, hasz, hasm, npoints);
|
|
|
|
loc += sizeof(double)*ndims*npoints;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the serialized form of the polygon
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
// points copied
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *
|
2004-09-29 10:50:30 +00:00
|
|
|
lwpoly_serialize(LWPOLY *poly)
|
|
|
|
{
|
2004-09-30 15:42:28 +00:00
|
|
|
size_t size, retsize;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *result;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
size = lwpoly_serialize_size(poly);
|
2004-09-29 10:50:30 +00:00
|
|
|
result = lwalloc(size);
|
2004-09-30 15:42:28 +00:00
|
|
|
lwpoly_serialize_buf(poly, result, &retsize);
|
|
|
|
|
|
|
|
if ( retsize != size )
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2004-09-30 15:42:28 +00:00
|
|
|
lwerror("lwpoly_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the serialized form of the polygon writing it into the
|
|
|
|
// given buffer, and returning number of bytes written into
|
|
|
|
// the given int pointer.
|
|
|
|
// result's first char will be the 8bit type. See serialized form doc
|
|
|
|
// points copied
|
|
|
|
void
|
2005-02-10 10:52:53 +00:00
|
|
|
lwpoly_serialize_buf(LWPOLY *poly, uchar *buf, size_t *retsize)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2005-11-11 17:45:46 +00:00
|
|
|
size_t size=1; // type byte
|
2004-09-29 10:50:30 +00:00
|
|
|
char hasSRID;
|
2005-11-11 17:45:46 +00:00
|
|
|
int t;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar *loc;
|
2005-11-11 17:45:46 +00:00
|
|
|
int ptsize;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG_CALLS
|
2004-10-03 15:52:23 +00:00
|
|
|
lwnotice("lwpoly_serialize_buf called");
|
|
|
|
#endif
|
|
|
|
|
2005-11-11 17:45:46 +00:00
|
|
|
ptsize = sizeof(double)*TYPE_NDIMS(poly->type);
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
hasSRID = (poly->SRID != -1);
|
|
|
|
|
|
|
|
size += 4; // nrings
|
|
|
|
size += 4*poly->nrings; //npoints/ring
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
buf[0] = (uchar) lwgeom_makeType_full(
|
2004-10-05 16:28:34 +00:00
|
|
|
TYPE_HASZ(poly->type), TYPE_HASM(poly->type),
|
2004-10-08 13:20:55 +00:00
|
|
|
hasSRID, POLYGONTYPE, poly->bbox ? 1 : 0);
|
2004-09-29 10:50:30 +00:00
|
|
|
loc = buf+1;
|
|
|
|
|
2004-10-08 13:20:55 +00:00
|
|
|
if (poly->bbox)
|
2004-09-30 15:42:28 +00:00
|
|
|
{
|
2004-10-08 13:20:55 +00:00
|
|
|
memcpy(loc, poly->bbox, sizeof(BOX2DFLOAT4));
|
2004-09-30 15:42:28 +00:00
|
|
|
size += sizeof(BOX2DFLOAT4); // bvol
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
if (hasSRID)
|
|
|
|
{
|
|
|
|
memcpy(loc, &poly->SRID, sizeof(int32));
|
|
|
|
loc += 4;
|
2004-09-30 15:42:28 +00:00
|
|
|
size +=4; //4 byte SRID
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(loc, &poly->nrings, sizeof(int32)); // nrings
|
|
|
|
loc+=4;
|
|
|
|
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
POINTARRAY *pa = poly->rings[t];
|
2005-11-11 17:45:46 +00:00
|
|
|
size_t pasize;
|
|
|
|
uint32 npoints;
|
|
|
|
|
|
|
|
if ( TYPE_GETZM(poly->type) != TYPE_GETZM(pa->dims) )
|
|
|
|
lwerror("Dimensions mismatch in lwpoly");
|
|
|
|
|
|
|
|
npoints = pa->npoints;
|
|
|
|
|
|
|
|
memcpy(loc, &npoints, sizeof(uint32)); //npoints this ring
|
2004-09-29 10:50:30 +00:00
|
|
|
loc+=4;
|
2005-11-11 17:45:46 +00:00
|
|
|
|
|
|
|
pasize = npoints*ptsize;
|
|
|
|
size += pasize;
|
|
|
|
|
|
|
|
// copy points
|
|
|
|
memcpy(loc, getPoint_internal(pa, 0), pasize);
|
|
|
|
loc += pasize;
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (retsize) *retsize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN)
|
|
|
|
BOX3D *
|
2005-03-18 12:36:27 +00:00
|
|
|
lwpoly_compute_box3d(LWPOLY *poly)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
BOX3D *result;
|
2005-03-18 12:36:27 +00:00
|
|
|
|
|
|
|
// just need to check outer ring -- interior rings are inside
|
|
|
|
POINTARRAY *pa = poly->rings[0];
|
|
|
|
result = ptarray_compute_box3d(pa);
|
|
|
|
|
|
|
|
return result;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//find length of this serialized polygon
|
2004-10-05 17:15:42 +00:00
|
|
|
size_t
|
2005-02-10 10:52:53 +00:00
|
|
|
lwgeom_size_poly(const uchar *serialized_poly)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
uint32 result = 1; // char type
|
|
|
|
uint32 nrings;
|
2005-02-10 10:52:53 +00:00
|
|
|
int ndims;
|
2004-09-29 10:50:30 +00:00
|
|
|
int t;
|
2005-02-10 10:52:53 +00:00
|
|
|
uchar type;
|
2004-09-29 10:50:30 +00:00
|
|
|
uint32 npoints;
|
2005-02-10 10:52:53 +00:00
|
|
|
const uchar *loc;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
if (serialized_poly == NULL)
|
|
|
|
return -9999;
|
|
|
|
|
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
type = (uchar) serialized_poly[0];
|
2004-09-29 10:50:30 +00:00
|
|
|
ndims = lwgeom_ndims(type);
|
|
|
|
|
|
|
|
if ( lwgeom_getType(type) != POLYGONTYPE)
|
|
|
|
return -9999;
|
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_poly+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size_poly: has bbox");
|
|
|
|
#endif
|
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice("lwgeom_size_poly: has srid");
|
|
|
|
#endif
|
|
|
|
loc +=4; // type + SRID
|
|
|
|
result += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nrings = get_uint32(loc);
|
|
|
|
loc +=4;
|
|
|
|
result +=4;
|
|
|
|
|
|
|
|
|
|
|
|
for (t =0;t<nrings;t++)
|
|
|
|
{
|
|
|
|
//read in a single ring and make a PA
|
|
|
|
npoints = get_uint32(loc);
|
2004-10-05 17:15:42 +00:00
|
|
|
loc += 4;
|
|
|
|
result += 4;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
if (ndims == 3)
|
|
|
|
{
|
|
|
|
loc += 24*npoints;
|
|
|
|
result += 24*npoints;
|
|
|
|
}
|
|
|
|
else if (ndims == 2)
|
|
|
|
{
|
|
|
|
loc += 16*npoints;
|
|
|
|
result += 16*npoints;
|
|
|
|
}
|
|
|
|
else if (ndims == 4)
|
|
|
|
{
|
|
|
|
loc += 32*npoints;
|
|
|
|
result += 32*npoints;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// find length of this deserialized polygon
|
2004-09-29 15:25:21 +00:00
|
|
|
size_t
|
|
|
|
lwpoly_serialize_size(LWPOLY *poly)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2004-09-29 15:25:21 +00:00
|
|
|
size_t size = 1; // type
|
2004-09-29 10:50:30 +00:00
|
|
|
uint32 i;
|
|
|
|
|
|
|
|
if ( poly->SRID != -1 ) size += 4; // SRID
|
2004-10-08 13:20:55 +00:00
|
|
|
if ( poly->bbox ) size += sizeof(BOX2DFLOAT4);
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG_CALLS
|
2004-10-03 15:52:23 +00:00
|
|
|
lwnotice("lwpoly_serialize_size called with poly[%p] (%d rings)",
|
|
|
|
poly, poly->nrings);
|
|
|
|
#endif
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
size += 4; // nrings
|
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
size += 4; // npoints
|
2004-10-04 13:53:42 +00:00
|
|
|
size += poly->rings[i]->npoints*TYPE_NDIMS(poly->type)*sizeof(double);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2005-02-07 13:21:10 +00:00
|
|
|
#ifdef PGIS_DEBUG_CALLS
|
2004-10-03 15:52:23 +00:00
|
|
|
lwnotice("lwpoly_serialize_size returning %d", size);
|
|
|
|
#endif
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pfree_polygon (LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
pfree_POINTARRAY(poly->rings[t]);
|
|
|
|
}
|
|
|
|
|
|
|
|
lwfree(poly);
|
|
|
|
}
|
|
|
|
|
|
|
|
void printLWPOLY(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
lwnotice("LWPOLY {");
|
2004-10-04 13:53:42 +00:00
|
|
|
lwnotice(" ndims = %i", (int)TYPE_NDIMS(poly->type));
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" SRID = %i", (int)poly->SRID);
|
|
|
|
lwnotice(" nrings = %i", (int)poly->nrings);
|
|
|
|
for (t=0;t<poly->nrings;t++)
|
|
|
|
{
|
|
|
|
lwnotice(" RING # %i :",t);
|
|
|
|
printPA(poly->rings[t]);
|
|
|
|
}
|
|
|
|
lwnotice("}");
|
|
|
|
}
|
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
int
|
2005-03-18 12:36:27 +00:00
|
|
|
lwpoly_compute_box2d_p(LWPOLY *poly, BOX2DFLOAT4 *box)
|
2004-09-30 15:42:28 +00:00
|
|
|
{
|
|
|
|
BOX2DFLOAT4 boxbuf;
|
|
|
|
uint32 i;
|
|
|
|
|
|
|
|
if ( ! poly->nrings ) return 0;
|
2005-03-18 12:36:27 +00:00
|
|
|
if ( ! ptarray_compute_box2d_p(poly->rings[0], box) ) return 0;
|
2004-09-30 15:42:28 +00:00
|
|
|
for (i=1; i<poly->nrings; i++)
|
|
|
|
{
|
2005-03-18 12:36:27 +00:00
|
|
|
if ( ! ptarray_compute_box2d_p(poly->rings[0], &boxbuf) )
|
2004-09-30 15:42:28 +00:00
|
|
|
return 0;
|
|
|
|
if ( ! box2d_union_p(box, &boxbuf, box) )
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-01 14:49:34 +00:00
|
|
|
|
|
|
|
// Clone LWLINE object. POINTARRAY are not copied, it's ring array is.
|
|
|
|
LWPOLY *
|
|
|
|
lwpoly_clone(const LWPOLY *g)
|
|
|
|
{
|
|
|
|
LWPOLY *ret = lwalloc(sizeof(LWPOLY));
|
|
|
|
memcpy(ret, g, sizeof(LWPOLY));
|
|
|
|
ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
|
|
|
|
memcpy(ret->rings, g->rings, sizeof(POINTARRAY *)*g->nrings);
|
2005-11-14 09:01:15 +00:00
|
|
|
if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
|
2004-10-01 14:49:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add 'what' to this poly at position 'where'.
|
|
|
|
// where=0 == prepend
|
|
|
|
// where=-1 == append
|
|
|
|
// Returns a MULTIPOLYGON or a GEOMETRYCOLLECTION
|
|
|
|
LWGEOM *
|
|
|
|
lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what)
|
|
|
|
{
|
|
|
|
LWCOLLECTION *col;
|
|
|
|
LWGEOM **geoms;
|
|
|
|
int newtype;
|
|
|
|
|
|
|
|
if ( where != -1 && where != 0 )
|
|
|
|
{
|
|
|
|
lwerror("lwpoly_add only supports 0 or -1 as second argument, got %d", where);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dimensions compatibility are checked by caller
|
|
|
|
|
|
|
|
// Construct geoms array
|
|
|
|
geoms = lwalloc(sizeof(LWGEOM *)*2);
|
|
|
|
if ( where == -1 ) // append
|
|
|
|
{
|
|
|
|
geoms[0] = lwgeom_clone((LWGEOM *)to);
|
|
|
|
geoms[1] = lwgeom_clone(what);
|
|
|
|
}
|
|
|
|
else // prepend
|
|
|
|
{
|
|
|
|
geoms[0] = lwgeom_clone(what);
|
|
|
|
geoms[1] = lwgeom_clone((LWGEOM *)to);
|
|
|
|
}
|
|
|
|
// reset SRID and wantbbox flag from component types
|
|
|
|
geoms[0]->SRID = geoms[1]->SRID = -1;
|
2004-10-04 13:53:42 +00:00
|
|
|
TYPE_SETHASSRID(geoms[0]->type, 0);
|
|
|
|
TYPE_SETHASSRID(geoms[1]->type, 0);
|
|
|
|
TYPE_SETHASBBOX(geoms[0]->type, 0);
|
|
|
|
TYPE_SETHASBBOX(geoms[1]->type, 0);
|
2004-10-01 14:49:34 +00:00
|
|
|
|
|
|
|
// Find appropriate geom type
|
2004-10-04 13:53:42 +00:00
|
|
|
if ( TYPE_GETTYPE(what->type) == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
|
2004-10-01 14:49:34 +00:00
|
|
|
else newtype = COLLECTIONTYPE;
|
|
|
|
|
2004-10-05 16:28:34 +00:00
|
|
|
col = lwcollection_construct(newtype,
|
2004-10-08 13:20:55 +00:00
|
|
|
to->SRID, NULL,
|
2004-10-04 13:53:42 +00:00
|
|
|
2, geoms);
|
2004-10-01 14:49:34 +00:00
|
|
|
|
|
|
|
return (LWGEOM *)col;
|
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
lwpoly_forceRHR(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ( ptarray_isccw(poly->rings[0]) )
|
|
|
|
{
|
|
|
|
ptarray_reverse(poly->rings[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=1; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
if ( ! ptarray_isccw(poly->rings[i]) )
|
|
|
|
{
|
|
|
|
ptarray_reverse(poly->rings[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
lwpoly_reverse(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
ptarray_reverse(poly->rings[i]);
|
|
|
|
}
|
2004-10-10 20:31:23 +00:00
|
|
|
|
|
|
|
LWPOLY *
|
|
|
|
lwpoly_segmentize2d(LWPOLY *poly, double dist)
|
|
|
|
{
|
|
|
|
POINTARRAY **newrings;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
|
|
|
|
}
|
2005-11-28 11:20:20 +00:00
|
|
|
return lwpoly_construct(poly->SRID, NULL,
|
2004-10-10 20:31:23 +00:00
|
|
|
poly->nrings, newrings);
|
|
|
|
}
|
2004-10-11 07:15:20 +00:00
|
|
|
|
|
|
|
// check coordinate equality
|
|
|
|
// ring and coordinate order is considered
|
|
|
|
char
|
|
|
|
lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if ( p1->nrings != p2->nrings ) return 0;
|
|
|
|
for (i=0; i<p1->nrings; i++)
|
|
|
|
{
|
|
|
|
if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2005-01-06 13:45:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Construct a polygon from a LWLINE being
|
|
|
|
* the shell and an array of LWLINE (possibly NULL) being holes.
|
|
|
|
* Pointarrays from intput geoms are cloned.
|
|
|
|
* SRID must be the same for each input line.
|
|
|
|
* Input lines must have at least 4 points, and be closed.
|
|
|
|
*/
|
|
|
|
LWPOLY *
|
|
|
|
lwpoly_from_lwlines(const LWLINE *shell,
|
|
|
|
unsigned int nholes, const LWLINE **holes)
|
|
|
|
{
|
|
|
|
unsigned int nrings;
|
|
|
|
POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
|
|
|
|
int SRID = shell->SRID;
|
|
|
|
LWPOLY *ret;
|
|
|
|
|
|
|
|
if ( shell->points->npoints < 4 )
|
|
|
|
lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
|
|
|
|
if ( ! ptarray_isclosed2d(shell->points) )
|
|
|
|
lwerror("lwpoly_from_lwlines: shell must be closed");
|
|
|
|
rings[0] = ptarray_clone(shell->points);
|
|
|
|
|
|
|
|
for (nrings=1; nrings<=nholes; nrings++)
|
|
|
|
{
|
|
|
|
const LWLINE *hole = holes[nrings-1];
|
|
|
|
|
|
|
|
if ( hole->SRID != SRID )
|
|
|
|
lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
|
|
|
|
|
|
|
|
if ( hole->points->npoints < 4 )
|
|
|
|
lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
|
|
|
|
if ( ! ptarray_isclosed2d(hole->points) )
|
|
|
|
lwerror("lwpoly_from_lwlines: holes must be closed");
|
|
|
|
|
|
|
|
rings[nrings] = ptarray_clone(hole->points);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = lwpoly_construct(SRID, NULL, nrings, rings);
|
|
|
|
return ret;
|
|
|
|
}
|