- #4084: Fixed wrong code-comment regarding front/back of BOX3D (Matthias Bay)
- #4060, #4094, PostgreSQL JIT support (Raúl Marín, Laurenz Albe)
- #3960, ST_Centroid now uses lwgeom_centroid (Darafei Praliaskouski)
+ - #4103, ST_PointOnSurface can handle invalid (Darafei Praliaskouski)
PostGIS 2.4.4
2018/04/08
LWGEOM *lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2);
+LWGEOM *lwgeom_pointonsurface(const LWGEOM* geom);
LWGEOM *lwgeom_centroid(const LWGEOM* geom);
LWGEOM *lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_linemerge(const LWGEOM *geom1);
return LW_TRUE;
}
-/* Output encoder and sanity checker for GEOS wrappers */
+/* Clean up and return NULL */
inline static LWGEOM*
geos_clean_and_fail(GEOSGeometry* g1, GEOSGeometry* g2, GEOSGeometry* g3, const char* funcname)
{
return NULL;
}
-/* Output encoder and sanity checker for GEOS wrappers */
+/* Clean up */
inline static void
geos_clean(GEOSGeometry* g1, GEOSGeometry* g2, GEOSGeometry* g3)
{
return result;
}
+LWGEOM *
+lwgeom_pointonsurface(const LWGEOM *geom)
+{
+ LWGEOM *result;
+ int32_t srid = get_result_srid(geom, NULL, __func__);
+ uint8_t is3d = FLAGS_GET_Z(geom->flags);
+ GEOSGeometry *g1, *g3;
+
+ if (srid == SRID_INVALID) return NULL;
+
+ if (lwgeom_is_empty(geom))
+ {
+ LWPOINT *lwp = lwpoint_construct_empty(srid, is3d, lwgeom_has_m(geom));
+ return lwpoint_as_lwgeom(lwp);
+ }
+
+ initGEOS(lwnotice, lwgeom_geos_error);
+
+ if (!input_lwgeom_to_geos(&g1, geom, __func__)) return NULL;
+
+ g3 = GEOSPointOnSurface(g1);
+
+ if (!g3)
+ {
+ GEOSGeometry *g1v;
+ lwnotice("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg);
+
+ if (!GEOSisValid(g1))
+ {
+ lwnotice(
+ "Your geometry dataset is not valid per OGC Specification. "
+ "Please fix it with manual review of entries that are not ST_IsValid(geom). "
+ "Retrying GEOS operation with ST_MakeValid of your input.");
+ g1v = LWGEOM_GEOS_makeValid(g1);
+ g3 = GEOSPointOnSurface(g1v);
+ geos_clean(g1v, NULL, NULL);
+ }
+ }
+
+ if (!g3) return geos_clean_and_fail(g1, NULL, NULL, __func__);
+
+ if (!output_geos_as_lwgeom(&g3, &result, srid, is3d, __func__))
+ return geos_clean_and_fail(g1, NULL, g3, __func__);
+
+ geos_clean(g1, NULL, g3);
+
+ return result;
+}
+
LWGEOM*
lwgeom_union(const LWGEOM* geom1, const LWGEOM* geom2)
{
PG_FUNCTION_INFO_V1(pointonsurface);
Datum pointonsurface(PG_FUNCTION_ARGS)
{
- GSERIALIZED *geom;
- GEOSGeometry *g1, *g3;
- GSERIALIZED *result;
+ GSERIALIZED *geom, *result;
+ LWGEOM *lwgeom, *lwresult;
geom = PG_GETARG_GSERIALIZED_P(0);
- /* Empty.PointOnSurface == Point Empty */
- if ( gserialized_is_empty(geom) )
- {
- LWPOINT *lwp = lwpoint_construct_empty(
- gserialized_get_srid(geom),
- gserialized_has_z(geom),
- gserialized_has_m(geom));
- result = geometry_serialize(lwpoint_as_lwgeom(lwp));
- lwpoint_free(lwp);
- PG_RETURN_POINTER(result);
- }
-
- initGEOS(lwpgnotice, lwgeom_geos_error);
-
- g1 = POSTGIS2GEOS(geom);
-
- if (!g1) HANDLE_GEOS_ERROR(__func__);
-
- g3 = GEOSPointOnSurface(g1);
-
- if (!g3)
- {
- GEOSGeom_destroy(g1);
- HANDLE_GEOS_ERROR("GEOSPointOnSurface");
- }
-
- GEOSSetSRID(g3, gserialized_get_srid(geom));
-
- result = GEOS2POSTGIS(g3, gserialized_has_z(geom));
-
- if (!result)
- {
- GEOSGeom_destroy(g1);
- GEOSGeom_destroy(g3);
- elog(ERROR,"GEOS pointonsurface() threw an error (result postgis geometry formation)!");
- PG_RETURN_NULL(); /* never get here */
- }
-
- GEOSGeom_destroy(g1);
- GEOSGeom_destroy(g3);
-
+ lwgeom = lwgeom_from_gserialized(geom);
+ lwresult = lwgeom_pointonsurface(lwgeom);
+ lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 0);
+ if (!lwresult) PG_RETURN_NULL();
+
+ result = geometry_serialize(lwresult);
+ lwgeom_free(lwresult);
PG_RETURN_POINTER(result);
}
--#4089
select '#4089', st_astext(st_geomfromtwkb(st_AsTWKB(st_GeometryFromText('LINESTRING Z(1 1 1, 3 3 1)'), 1, 0, 0, false, true)));
+select '#4103', ST_Intersects(ST_PointOnSurface(geom), geom)
+from (select '0103000020110F0000010000000A000000000000C41E644741000000EEA2A75A41000000F420644741000000629EA75A410000007A2D644741000000E49FA75A41000000C02E644741000000409DA75A41000000286A64474100000064A4A75A410000007867644741000000FAA9A75A41000000E82B644741000000D2A2A75A41000000222D64474100000046A0A75A41000000242B6447410000006CA4A75A41000000C41E644741000000EEA2A75A41'::geometry geom) z;
+
-- Clean up
DELETE FROM spatial_ref_sys;
#4055a|4326
#4055b|4326
#4089|LINESTRING Z (1 1 1,3 3 1)
+NOTICE: lwgeom_pointonsurface: GEOS Error: TopologyException: Input geom 1 is invalid: Self-intersection
+NOTICE: Self-intersection
+NOTICE: Your geometry dataset is not valid per OGC Specification. Please fix it with manual review of entries that are not ST_IsValid(geom). Retrying GEOS operation with ST_MakeValid of your input.
+NOTICE: Self-intersection
+#4103|t