2006-05-30 08:38:58 +00:00
|
|
|
/**********************************************************************
|
2009-02-04 00:28:37 +00:00
|
|
|
* $Id$
|
2006-05-30 08:38:58 +00:00
|
|
|
*
|
|
|
|
* PostGIS - Spatial Types for PostgreSQL
|
|
|
|
* http://postgis.refractions.net
|
|
|
|
* Copyright 2001-2006 Refractions Research Inc.
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute and/or modify it under
|
|
|
|
* the terms of the GNU General Public Licence. See the COPYING file.
|
2009-06-11 16:44:03 +00:00
|
|
|
*
|
2006-05-30 08:38:58 +00:00
|
|
|
**********************************************************************/
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* basic LWPOLY manipulation */
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2010-11-01 01:28:12 +00:00
|
|
|
#include "liblwgeom_internal.h"
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2004-10-03 15:52:23 +00:00
|
|
|
|
2004-10-07 10:03:23 +00:00
|
|
|
#define CHECK_POLY_RINGS_ZM 1
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* construct a new LWPOLY. arrays (points/points per ring) will NOT be copied
|
2010-12-07 21:59:54 +00:00
|
|
|
* use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
|
2005-12-30 17:40:37 +00:00
|
|
|
*/
|
2010-03-16 03:13:33 +00:00
|
|
|
LWPOLY*
|
2010-11-25 17:34:21 +00:00
|
|
|
lwpoly_construct(int srid, GBOX *bbox, uint32 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;
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 i;
|
2004-10-07 10:03:23 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring");
|
|
|
|
|
2010-11-25 18:38:20 +00:00
|
|
|
hasz = FLAGS_GET_Z(points[0]->flags);
|
|
|
|
hasm = FLAGS_GET_M(points[0]->flags);
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
#ifdef CHECK_POLY_RINGS_ZM
|
2010-11-25 18:38:20 +00:00
|
|
|
zm = FLAGS_GET_ZM(points[0]->flags);
|
2004-10-07 10:03:23 +00:00
|
|
|
for (i=1; i<nrings; i++)
|
|
|
|
{
|
2010-11-25 18:38:20 +00:00
|
|
|
if ( zm != FLAGS_GET_ZM(points[i]->flags) )
|
2004-10-07 10:03:23 +00:00
|
|
|
lwerror("lwpoly_construct: mixed dimensioned rings");
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
|
2010-11-21 19:02:23 +00:00
|
|
|
result->type = POLYGONTYPE;
|
2010-11-24 00:28:40 +00:00
|
|
|
result->flags = gflags(hasz, hasm, 0);
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_SET_BBOX(result->flags, bbox?1:0);
|
2010-11-25 17:34:21 +00:00
|
|
|
result->srid = srid;
|
2004-09-29 10:50:30 +00:00
|
|
|
result->nrings = nrings;
|
2010-10-03 18:14:35 +00:00
|
|
|
result->maxrings = nrings;
|
2004-09-29 10:50:30 +00:00
|
|
|
result->rings = points;
|
2004-10-08 13:20:55 +00:00
|
|
|
result->bbox = bbox;
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-03-16 03:13:33 +00:00
|
|
|
LWPOLY*
|
|
|
|
lwpoly_construct_empty(int srid, char hasz, char hasm)
|
|
|
|
{
|
|
|
|
LWPOLY *result = lwalloc(sizeof(LWPOLY));
|
2010-11-21 19:02:23 +00:00
|
|
|
result->type = POLYGONTYPE;
|
2010-11-24 00:28:40 +00:00
|
|
|
result->flags = gflags(hasz,hasm,0);
|
2010-11-25 17:34:21 +00:00
|
|
|
result->srid = srid;
|
2010-03-16 03:13:33 +00:00
|
|
|
result->nrings = 0;
|
2010-10-06 15:20:02 +00:00
|
|
|
result->maxrings = 1; /* Allocate room for ring, just in case. */
|
2010-10-03 18:14:35 +00:00
|
|
|
result->rings = lwalloc(result->maxrings * sizeof(POINTARRAY*));
|
2010-03-16 03:13:33 +00:00
|
|
|
result->bbox = NULL;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2004-09-29 10:50:30 +00:00
|
|
|
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;
|
2005-12-30 17:40:37 +00:00
|
|
|
uchar *loc;
|
2004-09-29 10:50:30 +00:00
|
|
|
int t;
|
|
|
|
|
|
|
|
if (serialized_form == NULL)
|
|
|
|
{
|
|
|
|
lwerror("lwpoly_deserialize called with NULL arg");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
type = serialized_form[0];
|
2004-10-05 16:28:34 +00:00
|
|
|
ndims = TYPE_NDIMS(type);
|
|
|
|
hasz = TYPE_HASZ(type);
|
|
|
|
hasm = TYPE_HASM(type);
|
2010-12-17 20:10:36 +00:00
|
|
|
|
|
|
|
result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
|
|
|
|
result->type = TYPE_GETTYPE(type);
|
|
|
|
result->flags = gflags(hasz, hasm, 0);
|
|
|
|
|
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
|
|
|
{
|
2010-03-16 03:13:33 +00:00
|
|
|
lwerror("lwpoly_deserialize: attempt to deserialize a poly which is really a %s", lwtype_name(type));
|
2004-09-29 10:50:30 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_form+1;
|
|
|
|
|
2009-06-11 16:44:03 +00:00
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
BOX2DFLOAT4 *box2df;
|
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUG(3, "lwpoly_deserialize: input has bbox");
|
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_SET_BBOX(result->flags, 1);
|
|
|
|
box2df = lwalloc(sizeof(BOX2DFLOAT4));
|
|
|
|
memcpy(box2df, loc, sizeof(BOX2DFLOAT4));
|
|
|
|
result->bbox = gbox_from_box2df(result->flags, box2df);
|
|
|
|
lwfree(box2df);
|
2004-09-29 10:50:30 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
2009-06-11 16:44:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-10-08 13:20:55 +00:00
|
|
|
result->bbox = NULL;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2010-11-25 17:34:21 +00:00
|
|
|
result->srid = lw_get_int32(loc);
|
2005-12-30 17:40:37 +00:00
|
|
|
loc +=4; /* type + SRID */
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-13 19:25:15 +00:00
|
|
|
result->srid = SRID_UNKNOWN;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2007-11-27 22:39:06 +00:00
|
|
|
nrings = lw_get_uint32(loc);
|
2004-09-29 10:50:30 +00:00
|
|
|
result->nrings = nrings;
|
2010-10-03 18:14:35 +00:00
|
|
|
result->maxrings = nrings;
|
2004-09-29 10:50:30 +00:00
|
|
|
loc +=4;
|
2010-02-01 17:35:55 +00:00
|
|
|
if ( nrings )
|
2010-01-04 17:55:14 +00:00
|
|
|
{
|
|
|
|
result->rings = (POINTARRAY**) lwalloc(nrings* sizeof(POINTARRAY*));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->rings = NULL;
|
|
|
|
}
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2010-02-01 17:35:55 +00:00
|
|
|
for (t =0; t<nrings; t++)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2005-12-30 17:40:37 +00:00
|
|
|
/* read in a single ring and make a PA */
|
2007-11-27 22:39:06 +00:00
|
|
|
npoints = lw_get_uint32(loc);
|
2004-09-29 10:50:30 +00:00
|
|
|
loc +=4;
|
2010-11-04 23:21:06 +00:00
|
|
|
result->rings[t] = ptarray_construct_reference_data(hasz, hasm, npoints, loc);
|
2004-10-05 16:28:34 +00:00
|
|
|
loc += sizeof(double)*ndims*npoints;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
2009-06-11 16:44:03 +00:00
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/*
|
|
|
|
* create the serialized form of the polygon writing it into the
|
|
|
|
* given buffer, and returning number of bytes written into
|
|
|
|
* the given int pointer.
|
|
|
|
* result's first char will be the 8bit type. See serialized form doc
|
|
|
|
* points copied
|
|
|
|
*/
|
2004-09-29 10:50:30 +00:00
|
|
|
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-12-30 17:40:37 +00:00
|
|
|
size_t size=1; /* type byte */
|
2010-11-25 17:34:21 +00:00
|
|
|
char has_srid;
|
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
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUG(2, "lwpoly_serialize_buf called");
|
2004-10-03 15:52:23 +00:00
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
ptsize = sizeof(double)*FLAGS_NDIMS(poly->flags);
|
2005-11-11 17:45:46 +00:00
|
|
|
|
2010-12-07 21:59:54 +00:00
|
|
|
has_srid = (poly->srid != SRID_UNKNOWN);
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
size += 4; /* nrings */
|
|
|
|
size += 4*poly->nrings; /* npoints/ring */
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-02-10 10:52:53 +00:00
|
|
|
buf[0] = (uchar) lwgeom_makeType_full(
|
2010-11-21 19:02:23 +00:00
|
|
|
FLAGS_GET_Z(poly->flags), FLAGS_GET_M(poly->flags),
|
2010-11-25 17:34:21 +00:00
|
|
|
has_srid, 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
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
BOX2DFLOAT4 *box2df;
|
|
|
|
|
|
|
|
box2df = box2df_from_gbox(poly->bbox);
|
|
|
|
memcpy(loc, box2df, sizeof(BOX2DFLOAT4));
|
|
|
|
lwfree(box2df);
|
2005-12-30 17:40:37 +00:00
|
|
|
size += sizeof(BOX2DFLOAT4); /* bvol */
|
2004-09-30 15:42:28 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
2010-11-25 17:34:21 +00:00
|
|
|
if (has_srid)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2010-11-25 17:34:21 +00:00
|
|
|
memcpy(loc, &poly->srid, sizeof(int32));
|
2004-09-29 10:50:30 +00:00
|
|
|
loc += 4;
|
2005-12-30 17:40:37 +00:00
|
|
|
size +=4; /* 4 byte SRID */
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
memcpy(loc, &poly->nrings, sizeof(int32)); /* nrings */
|
2004-09-29 10:50:30 +00:00
|
|
|
loc+=4;
|
|
|
|
|
2010-02-01 17:35:55 +00:00
|
|
|
for (t=0; t<poly->nrings; t++)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
POINTARRAY *pa = poly->rings[t];
|
2005-11-11 17:45:46 +00:00
|
|
|
size_t pasize;
|
|
|
|
uint32 npoints;
|
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
LWDEBUGF(4, "FLAGS_GET_ZM(poly->type) == %d", FLAGS_GET_ZM(poly->flags));
|
2010-11-25 18:38:20 +00:00
|
|
|
LWDEBUGF(4, "FLAGS_GET_ZM(pa->flags) == %d", FLAGS_GET_ZM(pa->flags));
|
2009-09-14 10:54:33 +00:00
|
|
|
|
2010-11-25 18:38:20 +00:00
|
|
|
if ( FLAGS_GET_ZM(poly->flags) != FLAGS_GET_ZM(pa->flags) )
|
2005-11-11 17:45:46 +00:00
|
|
|
lwerror("Dimensions mismatch in lwpoly");
|
|
|
|
|
|
|
|
npoints = pa->npoints;
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
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;
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* copy points */
|
2005-11-11 17:45:46 +00:00
|
|
|
memcpy(loc, getPoint_internal(pa, 0), pasize);
|
|
|
|
loc += pasize;
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (retsize) *retsize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) */
|
2004-09-29 10:50:30 +00:00
|
|
|
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
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* just need to check outer ring -- interior rings are inside */
|
2009-06-11 16:44:03 +00:00
|
|
|
POINTARRAY *pa = poly->rings[0];
|
2005-03-18 12:36:27 +00:00
|
|
|
result = ptarray_compute_box3d(pa);
|
|
|
|
|
|
|
|
return result;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2009-09-14 10:54:33 +00:00
|
|
|
|
2005-12-30 17:40:37 +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
|
|
|
{
|
2005-12-30 17:40:37 +00:00
|
|
|
uint32 result = 1; /* char type */
|
2004-09-29 10:50:30 +00:00
|
|
|
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];
|
2010-12-08 23:40:38 +00:00
|
|
|
ndims = TYPE_NDIMS(type);
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
if ( lwgeom_getType(type) != POLYGONTYPE)
|
|
|
|
return -9999;
|
|
|
|
|
|
|
|
|
|
|
|
loc = serialized_poly+1;
|
|
|
|
|
|
|
|
if (lwgeom_hasBBOX(type))
|
|
|
|
{
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUG(3, "lwgeom_size_poly: has bbox");
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
loc += sizeof(BOX2DFLOAT4);
|
|
|
|
result +=sizeof(BOX2DFLOAT4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( lwgeom_hasSRID(type))
|
|
|
|
{
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUG(3, "lwgeom_size_poly: has srid");
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
loc +=4; /* type + SRID */
|
2004-09-29 10:50:30 +00:00
|
|
|
result += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-27 22:39:06 +00:00
|
|
|
nrings = lw_get_uint32(loc);
|
2004-09-29 10:50:30 +00:00
|
|
|
loc +=4;
|
|
|
|
result +=4;
|
|
|
|
|
2009-06-11 16:44:03 +00:00
|
|
|
LWDEBUGF(3, "lwgeom_size_poly contains %d rings", nrings);
|
2008-05-31 09:56:44 +00:00
|
|
|
|
2010-02-01 17:35:55 +00:00
|
|
|
for (t =0; t<nrings; t++)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2005-12-30 17:40:37 +00:00
|
|
|
/* read in a single ring and make a PA */
|
2007-11-27 22:39:06 +00:00
|
|
|
npoints = lw_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;
|
|
|
|
}
|
|
|
|
}
|
2007-06-28 20:16:13 +00:00
|
|
|
|
2009-06-11 16:44:03 +00:00
|
|
|
LWDEBUGF(3, "lwgeom_size_poly returning %d", result);
|
2008-05-31 09:56:44 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/* 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
|
|
|
{
|
2005-12-30 17:40:37 +00:00
|
|
|
size_t size = 1; /* type */
|
2004-09-29 10:50:30 +00:00
|
|
|
uint32 i;
|
|
|
|
|
2010-12-07 21:59:54 +00:00
|
|
|
if ( poly->srid != SRID_UNKNOWN ) 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
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(2, "lwpoly_serialize_size called with poly[%p] (%d rings)",
|
2009-06-11 16:44:03 +00:00
|
|
|
poly, poly->nrings);
|
2004-10-03 15:52:23 +00:00
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
size += 4; /* nrings */
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
2005-12-30 17:40:37 +00:00
|
|
|
size += 4; /* npoints */
|
2010-11-21 19:02:23 +00:00
|
|
|
size += poly->rings[i]->npoints*FLAGS_NDIMS(poly->flags)*sizeof(double);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(3, "lwpoly_serialize_size returning %d", size);
|
2004-10-03 15:52:23 +00:00
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2010-10-03 18:14:35 +00:00
|
|
|
void lwpoly_free(LWPOLY *poly)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
int t;
|
|
|
|
|
2009-01-08 17:04:00 +00:00
|
|
|
if ( poly->bbox )
|
|
|
|
lwfree(poly->bbox);
|
|
|
|
|
2010-02-01 17:35:55 +00:00
|
|
|
for (t=0; t<poly->nrings; t++)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2009-06-11 16:44:03 +00:00
|
|
|
if ( poly->rings[t] )
|
2009-01-09 17:41:23 +00:00
|
|
|
ptarray_free(poly->rings[t]);
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
2009-06-11 16:44:03 +00:00
|
|
|
if ( poly->rings )
|
2009-01-08 17:04:00 +00:00
|
|
|
lwfree(poly->rings);
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
lwfree(poly);
|
|
|
|
}
|
|
|
|
|
|
|
|
void printLWPOLY(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int t;
|
|
|
|
lwnotice("LWPOLY {");
|
2010-11-21 19:02:23 +00:00
|
|
|
lwnotice(" ndims = %i", (int)FLAGS_NDIMS(poly->flags));
|
2010-11-25 17:34:21 +00:00
|
|
|
lwnotice(" SRID = %i", (int)poly->srid);
|
2004-09-29 10:50:30 +00:00
|
|
|
lwnotice(" nrings = %i", (int)poly->nrings);
|
2010-02-01 17:35:55 +00:00
|
|
|
for (t=0; t<poly->nrings; t++)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
lwnotice(" RING # %i :",t);
|
|
|
|
printPA(poly->rings[t]);
|
|
|
|
}
|
|
|
|
lwnotice("}");
|
|
|
|
}
|
|
|
|
|
2004-09-30 15:42:28 +00:00
|
|
|
int
|
2010-03-16 03:13:33 +00:00
|
|
|
lwpoly_compute_box2d_p(const 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
|
|
|
|
2011-07-06 14:29:26 +00:00
|
|
|
/* @brief Clone LWLINE object. Serialized point lists are not copied.
|
|
|
|
*
|
|
|
|
* @see ptarray_clone
|
|
|
|
*/
|
2004-10-01 14:49:34 +00:00
|
|
|
LWPOLY *
|
|
|
|
lwpoly_clone(const LWPOLY *g)
|
|
|
|
{
|
2011-07-06 14:29:26 +00:00
|
|
|
int i;
|
2004-10-01 14:49:34 +00:00
|
|
|
LWPOLY *ret = lwalloc(sizeof(LWPOLY));
|
|
|
|
memcpy(ret, g, sizeof(LWPOLY));
|
|
|
|
ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
|
2011-07-06 14:29:26 +00:00
|
|
|
for ( i = 0; i < g->nrings; i++ ) {
|
|
|
|
ret->rings[i] = ptarray_clone(g->rings[i]);
|
|
|
|
}
|
2010-11-21 19:02:23 +00:00
|
|
|
if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
|
2004-10-01 14:49:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-12-23 18:03:30 +00:00
|
|
|
/* Deep clone LWPOLY object. POINTARRAY are copied, as is ring array */
|
|
|
|
LWPOLY *
|
|
|
|
lwpoly_clone_deep(const LWPOLY *g)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
LWPOLY *ret = lwalloc(sizeof(LWPOLY));
|
|
|
|
memcpy(ret, g, sizeof(LWPOLY));
|
|
|
|
if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
|
|
|
|
ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
|
|
|
|
for ( i = 0; i < ret->nrings; i++ )
|
|
|
|
{
|
2011-07-06 09:40:38 +00:00
|
|
|
ret->rings[i] = ptarray_clone_deep(g->rings[i]);
|
2010-12-23 18:03:30 +00:00
|
|
|
}
|
|
|
|
FLAGS_SET_READONLY(ret->flags,0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-10-03 18:14:35 +00:00
|
|
|
/**
|
|
|
|
* Add a ring to a polygon. Point array will be referenced, not copied.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
|
|
|
|
{
|
|
|
|
if( ! poly || ! pa )
|
2010-12-07 21:08:05 +00:00
|
|
|
return LW_FAILURE;
|
2010-10-03 18:14:35 +00:00
|
|
|
|
|
|
|
/* We have used up our storage, add some more. */
|
|
|
|
if( poly->nrings >= poly->maxrings )
|
|
|
|
{
|
|
|
|
int new_maxrings = 2 * (poly->nrings + 1);
|
|
|
|
poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add the new ring entry. */
|
|
|
|
poly->rings[poly->nrings] = pa;
|
|
|
|
poly->nrings++;
|
|
|
|
|
2010-12-07 21:08:05 +00:00
|
|
|
return LW_SUCCESS;
|
2010-10-03 18:14:35 +00:00
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
void
|
2010-10-03 18:14:35 +00:00
|
|
|
lwpoly_force_clockwise(LWPOLY *poly)
|
2004-10-07 10:03:23 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2011-06-22 22:09:47 +00:00
|
|
|
/* No-op empties */
|
|
|
|
if ( lwpoly_is_empty(poly) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* External ring */
|
2004-10-07 10:03:23 +00:00
|
|
|
if ( ptarray_isccw(poly->rings[0]) )
|
|
|
|
ptarray_reverse(poly->rings[0]);
|
|
|
|
|
2011-06-22 22:09:47 +00:00
|
|
|
/* Internal rings */
|
2004-10-07 10:03:23 +00:00
|
|
|
for (i=1; i<poly->nrings; i++)
|
|
|
|
if ( ! ptarray_isccw(poly->rings[i]) )
|
|
|
|
ptarray_reverse(poly->rings[i]);
|
2011-06-22 22:09:47 +00:00
|
|
|
|
2004-10-07 10:03:23 +00:00
|
|
|
}
|
|
|
|
|
2009-01-08 17:04:00 +00:00
|
|
|
void
|
|
|
|
lwpoly_release(LWPOLY *lwpoly)
|
|
|
|
{
|
2009-06-11 16:44:03 +00:00
|
|
|
lwgeom_release(lwpoly_as_lwgeom(lwpoly));
|
2009-01-08 17:04:00 +00:00
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
lwpoly_reverse(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int i;
|
2010-12-30 23:17:20 +00:00
|
|
|
if ( lwpoly_is_empty(poly) ) return;
|
2004-10-07 10:03:23 +00:00
|
|
|
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;
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 i;
|
2009-06-11 16:44:03 +00:00
|
|
|
|
2004-10-10 20:31:23 +00:00
|
|
|
newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
|
|
|
|
}
|
2010-11-25 17:34:21 +00:00
|
|
|
return lwpoly_construct(poly->srid, NULL,
|
2009-06-11 16:44:03 +00:00
|
|
|
poly->nrings, newrings);
|
2004-10-10 20:31:23 +00:00
|
|
|
}
|
2004-10-11 07:15:20 +00:00
|
|
|
|
2005-12-30 17:40:37 +00:00
|
|
|
/*
|
2009-06-11 16:44:03 +00:00
|
|
|
* check coordinate equality
|
2005-12-30 17:40:37 +00:00
|
|
|
* ring and coordinate order is considered
|
|
|
|
*/
|
2004-10-11 07:15:20 +00:00
|
|
|
char
|
|
|
|
lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
|
|
|
|
{
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 i;
|
2004-10-11 07:15:20 +00:00
|
|
|
|
|
|
|
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,
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 nholes, const LWLINE **holes)
|
2005-01-06 13:45:01 +00:00
|
|
|
{
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 nrings;
|
2005-01-06 13:45:01 +00:00
|
|
|
POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
|
2010-11-25 17:34:21 +00:00
|
|
|
int srid = shell->srid;
|
2005-01-06 13:45:01 +00:00
|
|
|
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");
|
2011-07-06 09:40:38 +00:00
|
|
|
rings[0] = ptarray_clone_deep(shell->points);
|
2005-01-06 13:45:01 +00:00
|
|
|
|
|
|
|
for (nrings=1; nrings<=nholes; nrings++)
|
|
|
|
{
|
|
|
|
const LWLINE *hole = holes[nrings-1];
|
|
|
|
|
2010-11-25 17:34:21 +00:00
|
|
|
if ( hole->srid != srid )
|
2005-01-06 13:45:01 +00:00
|
|
|
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");
|
|
|
|
|
2011-07-06 09:40:38 +00:00
|
|
|
rings[nrings] = ptarray_clone_deep(hole->points);
|
2005-01-06 13:45:01 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 17:34:21 +00:00
|
|
|
ret = lwpoly_construct(srid, NULL, nrings, rings);
|
2005-01-06 13:45:01 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2010-02-21 12:22:08 +00:00
|
|
|
|
|
|
|
LWGEOM*
|
|
|
|
lwpoly_remove_repeated_points(LWPOLY *poly)
|
|
|
|
{
|
2010-03-16 03:13:33 +00:00
|
|
|
uint32 i;
|
2010-02-21 12:22:08 +00:00
|
|
|
POINTARRAY **newrings;
|
|
|
|
|
|
|
|
newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
newrings[i] = ptarray_remove_repeated_points(poly->rings[i]);
|
|
|
|
}
|
|
|
|
|
2010-11-25 17:34:21 +00:00
|
|
|
return (LWGEOM*)lwpoly_construct(poly->srid,
|
2010-11-21 19:02:23 +00:00
|
|
|
poly->bbox ? gbox_copy(poly->bbox) : NULL,
|
2010-02-21 12:22:08 +00:00
|
|
|
poly->nrings, newrings);
|
|
|
|
|
|
|
|
}
|
2010-11-18 05:28:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
LWPOLY*
|
|
|
|
lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
|
|
|
|
{
|
|
|
|
LWPOLY *polyout;
|
|
|
|
|
|
|
|
/* Return 2D empty */
|
|
|
|
if( lwpoly_is_empty(poly) )
|
|
|
|
{
|
2010-11-25 17:34:21 +00:00
|
|
|
polyout = lwpoly_construct_empty(poly->srid, hasz, hasm);
|
2010-11-18 05:28:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
POINTARRAY **rings = NULL;
|
|
|
|
int i;
|
|
|
|
rings = lwalloc(sizeof(POINTARRAY*) * poly->nrings);
|
|
|
|
for( i = 0; i < poly->nrings; i++ )
|
|
|
|
{
|
|
|
|
rings[i] = ptarray_force_dims(poly->rings[i], hasz, hasm);
|
|
|
|
}
|
2010-11-25 17:34:21 +00:00
|
|
|
polyout = lwpoly_construct(poly->srid, NULL, poly->nrings, rings);
|
2010-11-18 05:28:19 +00:00
|
|
|
}
|
2010-11-21 19:02:23 +00:00
|
|
|
polyout->type = poly->type;
|
2010-11-18 05:28:19 +00:00
|
|
|
return polyout;
|
|
|
|
}
|
|
|
|
|
|
|
|
int lwpoly_is_empty(const LWPOLY *poly)
|
|
|
|
{
|
2010-12-21 23:56:23 +00:00
|
|
|
if ( (poly->nrings == 0) || (!poly->rings) )
|
2010-11-18 05:28:19 +00:00
|
|
|
return LW_TRUE;
|
|
|
|
return LW_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int lwpoly_count_vertices(LWPOLY *poly)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int v = 0; /* vertices */
|
|
|
|
assert(poly);
|
|
|
|
for ( i = 0; i < poly->nrings; i ++ )
|
|
|
|
{
|
|
|
|
v += poly->rings[i]->npoints;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist)
|
|
|
|
{
|
|
|
|
int i;
|
2010-11-25 17:34:21 +00:00
|
|
|
LWPOLY *opoly = lwpoly_construct_empty(ipoly->srid, FLAGS_GET_Z(ipoly->flags), FLAGS_GET_M(ipoly->flags));
|
2010-11-18 05:28:19 +00:00
|
|
|
|
|
|
|
LWDEBUGF(2, "simplify_polygon3d: simplifying polygon with %d rings", ipoly->nrings);
|
|
|
|
|
|
|
|
if( lwpoly_is_empty(ipoly) )
|
|
|
|
return opoly;
|
|
|
|
|
|
|
|
for (i = 0; i < ipoly->nrings; i++)
|
|
|
|
{
|
|
|
|
POINTARRAY *opts = ptarray_simplify(ipoly->rings[i], dist);
|
|
|
|
|
|
|
|
/* One point implies an error in the ptarray_simplify */
|
|
|
|
if ( opts->npoints < 2 )
|
|
|
|
{
|
|
|
|
lwnotice("ptarray_simplify returned a <2 pts array");
|
|
|
|
ptarray_free(opts);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Less points than are needed to form a closed ring, we can't use this */
|
|
|
|
if ( opts->npoints < 4 )
|
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
LWDEBUGF(3, "ring%d skipped (<4 pts)", i);
|
2010-11-18 05:28:19 +00:00
|
|
|
ptarray_free(opts);
|
|
|
|
if ( i ) continue;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
|
2010-11-18 05:28:19 +00:00
|
|
|
|
|
|
|
/* Add ring to simplified polygon */
|
2010-12-07 21:08:05 +00:00
|
|
|
if( lwpoly_add_ring(opoly, opts) == LW_FAILURE )
|
2010-11-18 05:28:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-11-21 19:02:23 +00:00
|
|
|
LWDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings);
|
|
|
|
opoly->type = ipoly->type;
|
2010-11-18 05:28:19 +00:00
|
|
|
return opoly;
|
2010-11-21 19:02:23 +00:00
|
|
|
}
|
2010-11-30 21:54:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the area of the outer ring - sum (area of inner rings).
|
|
|
|
* Could use a more numerically stable calculator...
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
lwpoly_area(const LWPOLY *poly)
|
|
|
|
{
|
|
|
|
double poly_area=0.0;
|
|
|
|
int i;
|
|
|
|
POINT2D p1;
|
|
|
|
POINT2D p2;
|
|
|
|
|
|
|
|
LWDEBUGF(2, "in lwpoly_area (%d rings)", poly->nrings);
|
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
POINTARRAY *ring = poly->rings[i];
|
|
|
|
double ringarea = 0.0;
|
|
|
|
|
|
|
|
LWDEBUGF(4, " rings %d has %d points", i, ring->npoints);
|
|
|
|
|
|
|
|
if ( ! ring->npoints ) continue; /* empty ring */
|
|
|
|
for (j=0; j<ring->npoints-1; j++)
|
|
|
|
{
|
|
|
|
getPoint2d_p(ring, j, &p1);
|
|
|
|
getPoint2d_p(ring, j+1, &p2);
|
|
|
|
ringarea += ( p1.x * p2.y ) - ( p1.y * p2.x );
|
|
|
|
}
|
|
|
|
|
|
|
|
ringarea /= 2.0;
|
|
|
|
|
|
|
|
LWDEBUGF(4, " ring 1 has area %lf",ringarea);
|
|
|
|
|
|
|
|
ringarea = fabs(ringarea);
|
|
|
|
if (i != 0) /*outer */
|
|
|
|
ringarea = -1.0*ringarea ; /* its a hole */
|
|
|
|
|
|
|
|
poly_area += ringarea;
|
|
|
|
}
|
|
|
|
|
|
|
|
return poly_area;
|
2010-12-01 20:28:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the sum of polygon rings length.
|
|
|
|
* Could use a more numerically stable calculator...
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
lwpoly_perimeter(const LWPOLY *poly)
|
|
|
|
{
|
|
|
|
double result=0.0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
|
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
result += ptarray_length(poly->rings[i]);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the sum of polygon rings length (forcing 2d computation).
|
|
|
|
* Could use a more numerically stable calculator...
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
lwpoly_perimeter_2d(const LWPOLY *poly)
|
|
|
|
{
|
|
|
|
double result=0.0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
|
|
|
|
|
|
|
|
for (i=0; i<poly->nrings; i++)
|
|
|
|
result += ptarray_length_2d(poly->rings[i]);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|