]> granicus.if.org Git - postgis/commitdiff
Added forceRHR() and support functions.
authorSandro Santilli <strk@keybit.net>
Tue, 28 Sep 2004 09:01:17 +0000 (09:01 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 28 Sep 2004 09:01:17 +0000 (09:01 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@903 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwgeom_functions_basic.c
lwgeom/lwpostgis.sql.in

index 46a2371f822ffa3d7584e752713d07815a085512..40a706d0be091914e89c6c715abdbd243fd8eb7a 100644 (file)
@@ -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; i<ipoly->nrings; 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; 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 = 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);
+}
index bf280f33dda7b841473f033e9a0bdcd1a4e532ed..9057d5c1e546549b28c920a2dd738134cc7c779b 100644 (file)
@@ -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);
+
 ------------------------------------------------------------------------
 
 --