[postgis-devel] ST_isValidDetail
strk
strk at keybit.net
Fri Feb 5 08:26:01 PST 2010
Attached is a patch which implements ST_isValidDetail(geometry)
returns valid_detail(valid bool, reason varchar, location geometry).
The location is always a point (if anything).
The reason is blank if valid is true.
Dare to check on pgsql < 8.3 and GEOS < 3.3.0 (trunk) ?
Also, I might be missing some upgrade thingies (I just
touched postgis.sql.in.c)
Oh, let me know if I should just commit rather than ask
to ask to test to check ... :)
--strk;
() Free GIS & Flash consultant/developer
/\ http://foo.keybit.net/~strk/services.html
-------------- next part --------------
Index: postgis/lwgeom_geos.c
===================================================================
--- postgis/lwgeom_geos.c (revision 5203)
+++ postgis/lwgeom_geos.c (working copy)
@@ -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 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 @@
}
+/*
+** 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: postgis/postgis.sql.in.c
===================================================================
--- postgis/postgis.sql.in.c (revision 5203)
+++ postgis/postgis.sql.in.c (working copy)
@@ -3923,6 +3923,17 @@
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
More information about the postgis-devel
mailing list