From: Sandro Santilli Date: Tue, 28 Sep 2004 09:01:17 +0000 (+0000) Subject: Added forceRHR() and support functions. X-Git-Tag: pgis_1_0_0RC1~369 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=346bde8960b1a353557aee9babe79f0ca894a649;p=postgis Added forceRHR() and support functions. git-svn-id: http://svn.osgeo.org/postgis/trunk@903 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index 46a2371f8..40a706d0b 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -45,6 +45,7 @@ Datum LWGEOM_envelope(PG_FUNCTION_ARGS); Datum LWGEOM_isempty(PG_FUNCTION_ARGS); Datum LWGEOM_segmentize2d(PG_FUNCTION_ARGS); Datum LWGEOM_reverse(PG_FUNCTION_ARGS); +Datum LWGEOM_forceRHR_poly(PG_FUNCTION_ARGS); // internal char * lwgeom_summary_recursive(char *serialized, int offset); @@ -53,6 +54,7 @@ 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); /*------------------------------------------------------------------*/ @@ -806,6 +808,39 @@ lwpoly_reverse(const LWPOLY *ipoly) return opoly; } +LWPOLY * +lwpoly_forceRHR(const LWPOLY *ipoly) +{ + LWPOLY *opoly; + POINTARRAY **rpa; + int i; + POINTARRAY *opa; + + rpa = palloc(sizeof(POINTARRAY *)*ipoly->nrings); + + if ( ptarray_isccw(ipoly->rings[0]) ) + { + opa = ipoly->rings[0]; + rpa[0] = ptarray_reverse(ipoly->rings[0]); + } + else rpa[0] = ipoly->rings[0]; + + for (i=1; inrings; i++) + { + if ( ! ptarray_isccw(ipoly->rings[i]) ) + { + opa = ipoly->rings[i]; + rpa[i] = ptarray_reverse(ipoly->rings[i]); + } + else rpa[i] = ipoly->rings[i]; + } + + opoly = lwpoly_construct(ipoly->ndims, ipoly->SRID, + ipoly->nrings, rpa); + + return opoly; +} + /*------------------------------------------------------------------*/ //find the size of geometry @@ -2832,3 +2867,47 @@ Datum LWGEOM_reverse(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } + +// Force polygons of the collection to obey Right-Hand-Rule +PG_FUNCTION_INFO_V1(LWGEOM_forceRHR_poly); +Datum LWGEOM_forceRHR_poly(PG_FUNCTION_ARGS) +{ + LWGEOM *geom; + LWGEOM *result = NULL; + LWGEOM_EXPLODED *exp; + int size; + int wantbbox; + int i; + + geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + + if ( lwgeom_getType(geom->type) != POLYGONTYPE && + lwgeom_getType(geom->type) != MULTIPOLYGONTYPE ) + { + elog(ERROR, "Only polygon|multipolygon supported"); + PG_RETURN_NULL(); + } + + wantbbox = lwgeom_hasBBOX(geom->type); + exp = lwgeom_explode(SERIALIZED_FORM(geom)); + + for (i=0; inpolys; 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 = palloc(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); +} diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index bf280f33d..9057d5c1e 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1612,6 +1612,11 @@ CREATEFUNCTION reverse(geometry) AS '@MODULE_FILENAME@', 'LWGEOM_reverse' LANGUAGE 'C' WITH (iscachable,isstrict); +CREATEFUNCTION ForceRHR(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_forceRHR_poly' + LANGUAGE 'C' WITH (iscachable,isstrict); + ------------------------------------------------------------------------ --