Datum ST_MakeValid(PG_FUNCTION_ARGS) { #if POSTGIS_GEOS_VERSION < 33 elog(ERROR, "You need GEOS-3.3.0 or up for ST_MakeValid"); PG_RETURN_NULL(); #else /* POSTGIS_GEOS_VERSION >= 33 */ GSERIALIZED *in, *out; LWGEOM *lwgeom_in, *lwgeom_out; in = PG_GETARG_GSERIALIZED_P(0); lwgeom_in = lwgeom_from_gserialized(in); switch ( lwgeom_in->type ) { case POINTTYPE: case MULTIPOINTTYPE: case LINETYPE: case POLYGONTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: break; default: lwerror("ST_MakeValid: unsupported geometry type %s", lwtype_name(lwgeom_in->type)); PG_RETURN_NULL(); break; } lwgeom_out = lwgeom_make_valid(lwgeom_in); if ( ! lwgeom_out ) { PG_FREE_IF_COPY(in, 0); PG_RETURN_NULL(); } out = geometry_serialize(lwgeom_out); PG_RETURN_POINTER(out); #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
// trying to make polygon to be valid // accept only string-polygon in wkb format static VALUE make_valid(VALUE self, VALUE geom_wkb) { VALUE result; LWGEOM *valid_lwg; int wkb_size_a; wkb_size_a = RSTRING_LEN(geom_wkb); lwg = lwgeom_from_wkb(RSTRING_PTR(geom_wkb), wkb_size_a, 0); valid_lwg = lwgeom_make_valid(lwg); //make multi valid_lwg = lwgeom_as_multi(valid_lwg); char *wkb_str = (char*)lwgeom_to_wkb(valid_lwg, WKB_HEX, NULL); return rb_str_new2(wkb_str); }
static LWGEOM* lwgeom_clean(LWGEOM* lwgeom_in) { LWGEOM* lwgeom_out; lwgeom_out = lwgeom_make_valid(lwgeom_in); if ( ! lwgeom_out ) { return NULL; } /* Check dimensionality is the same as input */ if ( lwgeom_dimensionality(lwgeom_in) != lwgeom_dimensionality(lwgeom_out) ) { lwnotice("lwgeom_clean: dimensional collapse (%d to %d)", lwgeom_dimensionality(lwgeom_in), lwgeom_dimensionality(lwgeom_out)); return NULL; } /* Check that the output is not a collection if the input wasn't */ if ( lwgeom_out->type == COLLECTIONTYPE && lwgeom_in->type != COLLECTIONTYPE ) { lwnotice("lwgeom_clean: mixed-type output (%s) " "from single-type input (%s)", lwtype_name(lwgeom_out->type), lwtype_name(lwgeom_in->type)); return NULL; } /* Force right-hand-rule (will only affect polygons) */ /* gout := ST_ForceRHR(gout); */ /* Remove repeated duplicated points ? */ /* gout = ST_RemoveRepeatedPoints(gout); */ return lwgeom_out; }
static void test_lwgeom_make_valid(void) { #if POSTGIS_GEOS_VERSION >= 33 LWGEOM *gin, *gout, *gexp; char *ewkt; /* Because i don't trust that much prior tests... ;) */ cu_error_msg_reset(); gin = lwgeom_from_wkt( "MULTIPOLYGON(((1725063 4819121, 1725104 4819067, 1725060 4819087, 1725064.14183882 4819094.70208557,1725064.13656044 4819094.70235069,1725064.14210359 4819094.70227252,1725064.14210362 4819094.70227252,1725064.13656043 4819094.70235069,1725055. 4819094, 1725055 4819094, 1725055 4819094, 1725063 4819121)))", LW_PARSER_CHECK_NONE); CU_ASSERT(gin != NULL); gout = lwgeom_make_valid(gin); /* We're really only interested in avoiding a crash in here. * See http://trac.osgeo.org/postgis/ticket/1738 * TODO: enhance the test if we find a workaround * to the excepion: * See http://trac.osgeo.org/postgis/ticket/1735 */ lwgeom_free(gout); lwgeom_free(gin); /* Test for http://trac.osgeo.org/postgis/ticket/2307 */ gin = lwgeom_from_hexwkb("0106000020E6100000010000000103000000010000000A0000004B7DA956B99844C0DB0790FE8B4D1DC010BA74A9AF9444C049AFFC5B8C4D1DC03FC6CC690D9844C0DD67E5628C4D1DC07117B56B0D9844C0C80ABA67C45E1DC0839166ABAF9444C0387D4568C45E1DC010BA74A9AF9444C049AFFC5B8C4D1DC040C3CD74169444C0362EC0608C4D1DC07C1A3B77169444C0DC3ADB40B2641DC03AAE5F68B99844C0242948DEB1641DC04B7DA956B99844C0DB0790FE8B4D1DC0", LW_PARSER_CHECK_NONE); CU_ASSERT(gin != NULL); gout = lwgeom_make_valid(gin); CU_ASSERT(gout != NULL); lwgeom_free(gin); /* We're really only interested in avoiding memory problems. * Convertion to ewkt ensures full scan of coordinates thus * triggering the error, if any */ ewkt = lwgeom_to_ewkt(gout); lwgeom_free(gout); lwfree(ewkt); /* Test collection */ gin = lwgeom_from_wkt( "GEOMETRYCOLLECTION(LINESTRING(0 0, 0 0), POLYGON((0 0, 10 10, 10 0, 0 10, 0 0)), LINESTRING(10 0, 10 10))", LW_PARSER_CHECK_NONE); CU_ASSERT(gin != NULL); gout = lwgeom_make_valid(gin); CU_ASSERT(gout != NULL); ewkt = lwgeom_to_ewkt(gout); /* printf("c = %s\n", ewkt); */ /* TODO: This doesn't work on windows returns in different order. strk figure out why. For now will replace with normalized version */ /* CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0),MULTIPOLYGON(((5 5,0 0,0 10,5 5)),((5 5,10 10,10 0,5 5))),LINESTRING(10 0,10 10))");*/ gexp = lwgeom_from_wkt( "GEOMETRYCOLLECTION(POINT(0 0),MULTIPOLYGON(((5 5,0 0,0 10,5 5)),((5 5,10 10,10 0,5 5))),LINESTRING(10 0,10 10))", LW_PARSER_CHECK_NONE); check_geom_equal(gout, gexp); lwfree(ewkt); lwgeom_free(gout); lwgeom_free(gin); lwgeom_free(gexp); /* Test multipoint */ gin = lwgeom_from_wkt( "MULTIPOINT(0 0,1 1,2 2)", LW_PARSER_CHECK_NONE); CU_ASSERT(gin != NULL); gout = lwgeom_make_valid(gin); CU_ASSERT(gout != NULL); ewkt = lwgeom_to_ewkt(gout); /* printf("c = %s\n", ewkt); */ CU_ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,1 1,2 2)"); lwfree(ewkt); lwgeom_free(gout); lwgeom_free(gin); #endif /* POSTGIS_GEOS_VERSION >= 33 */ }