]> granicus.if.org Git - postgis/commitdiff
Add ST_isValidDetail(geom) returns valid_detail (new type!)
authorSandro Santilli <strk@keybit.net>
Fri, 5 Feb 2010 17:26:23 +0000 (17:26 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 5 Feb 2010 17:26:23 +0000 (17:26 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@5204 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_geos.c
postgis/postgis.sql.in.c

index a5c90df864272bf347388c4f3374f28e31a89f5f..51d2fae463afc59ae305cb74e4b1cba4c1355f63 100644 (file)
@@ -16,6 +16,7 @@
 #include "lwgeom_geos.h"
 #include "lwgeom_rtree.h"
 #include "lwgeom_geos_prepared.h"
+#include "funcapi.h"
 
 #include <string.h>
 
@@ -42,6 +43,7 @@ Datum covers(PG_FUNCTION_ARGS);
 Datum overlaps(PG_FUNCTION_ARGS);
 Datum isvalid(PG_FUNCTION_ARGS);
 Datum isvalidreason(PG_FUNCTION_ARGS);
+Datum isvaliddetail(PG_FUNCTION_ARGS);
 Datum buffer(PG_FUNCTION_ARGS);
 Datum intersection(PG_FUNCTION_ARGS);
 Datum convexhull(PG_FUNCTION_ARGS);
@@ -1449,6 +1451,99 @@ Datum isvalidreason(PG_FUNCTION_ARGS)
 
 }
 
+/*
+** IsValidDetail is only available in the GEOS
+** C API >= version 3.3
+*/
+PG_FUNCTION_INFO_V1(isvaliddetail);
+Datum isvaliddetail(PG_FUNCTION_ARGS)
+{
+#if POSTGIS_GEOS_VERSION < 33
+       lwerror("The GEOS version this postgis binary "
+               "was compiled against (%d) doesn't support "
+               "'isValidDetail' function (3.3.0+ required)",
+               POSTGIS_GEOS_VERSION);
+       PG_RETURN_NULL();
+#else /* POSTGIS_GEOS_VERSION >= 33 */
+
+       PG_LWGEOM *geom = NULL;
+       const GEOSGeometry *g1 = NULL;
+       char *values[3]; /* valid bool, reason text, location geometry */
+       char *geos_reason = NULL;
+       char *reason = NULL;
+       const GEOSGeometry *geos_location = NULL;
+       LWGEOM *location = NULL;
+       char valid;
+       Datum result;
+       TupleDesc tupdesc;
+       HeapTuple tuple;
+       AttInMetadata *attinmeta;
+
+       /*
+        * Build a tuple description for a
+        * valid_detail tuple
+        */
+       tupdesc = RelationNameGetTupleDesc("valid_detail");
+       if ( ! tupdesc )
+       {
+               lwerror("TYPE valid_detail not found");
+               PG_RETURN_NULL();
+       }
+
+       /*
+        * generate attribute metadata needed later to produce
+        * tuples from raw C strings
+        */
+       attinmeta = TupleDescGetAttInMetadata(tupdesc);
+
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       initGEOS(lwnotice, lwnotice);
+
+       g1 = (GEOSGeometry *)POSTGIS2GEOS(geom);
+       if ( ! g1 )
+       {       /* TODO: take as invalid */
+               PG_RETURN_NULL();
+       }
+
+       valid = GEOSisValidDetail(g1, &geos_reason, &geos_location);
+       GEOSGeom_destroy((GEOSGeometry *)g1);
+       if ( geos_reason )
+       {
+               reason = pstrdup(geos_reason);
+               GEOSFree(geos_reason);
+       }
+       if ( geos_location )
+       {
+               location = GEOS2LWGEOM(geos_location, GEOSHasZ(geos_location));
+               GEOSGeom_destroy((GEOSGeometry *)geos_location);
+       }
+
+       if (valid == 2)
+       {
+               /* NOTE: should only happen on OOM or similar */
+               lwerror("GEOS isvaliddetail() threw an exception!");
+               PG_RETURN_NULL(); /* never gets here */
+       }
+
+       /* the boolean validity */
+       values[0] =  valid ? "t" : "f";
+
+       /* the reason */
+       values[1] =  reason;
+
+       /* the location */
+       values[2] =  location ?
+                    lwgeom_to_hexwkb(location, PARSER_CHECK_NONE, -1) : 0;
+
+       tuple = BuildTupleFromCStrings(attinmeta, values);
+       result = HeapTupleGetDatum(tuple);
+
+       PG_RETURN_HEAPTUPLEHEADER(result);
+
+#endif /* POSTGIS_GEOS_VERSION >= 33 */
+}
+
 /**
  * overlaps(PG_LWGEOM g1,PG_LWGEOM g2)
  * @param g1
index 9bcfcbdcee3cddddf01123d836a35efec91004b8..432f33f1b02d0b66a79ee71d6b2c272228f569c9 100644 (file)
@@ -3923,6 +3923,17 @@ CREATE OR REPLACE FUNCTION ST_IsValidReason(geometry)
        LANGUAGE 'C' IMMUTABLE STRICT
        COST 100;
 
+-- Availability: 2.0.0
+CREATE TYPE valid_detail AS (valid bool, reason varchar, location geometry);
+
+-- Requires GEOS >= 3.3.0
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_IsValidDetail(geometry)
+       RETURNS valid_detail
+       AS 'MODULE_PATHNAME', 'isvaliddetail'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
 #if POSTGIS_GEOS_VERSION >= 32
 -- Requires GEOS >= 3.2.0
 -- Availability: 1.5.0