- #4006, ST_GeomFromGeoJSON support for json and jsonb as input
(Paul Ramsey, Regina Obe)
- #4038, ST_Subdivide now selects pivot for geometry split that reuses input
- vertices. ST_ClipByBox2D is stubbed with ST_Intersection because of
- robustness issues. (Darafei Praliaskouski)
+ vertices. (Darafei Praliaskouski)
- #4025, #4032 Fixed precision issue in ST_ClosestPointOfApproach,
ST_DistanceCPA, and ST_CPAWithin (Paul Ramsey, Darafei Praliaskouski)
- #4076, Reduce use of GEOS in topology implementation (Björn Harrtell)
<refsection>
<title>Description</title>
- <para>
-Clips a geometry by a 2D box.</para>
+ <para>
+ Clips a geometry by a 2D box in a fast but possibly dirty way.
+ The output geometry is not guaranteed to be valid (self-intersections for a polygon may be introduced).
+ Topologically invalid input geometries do not result in exceptions being thrown.
+ </para>
<para>Performed by the GEOS module.</para>
<note><para>Requires GEOS 3.5.0+</para></note>
<para>Availability: 2.2.0 - requires GEOS >= 3.5.0.</para>
- <para>Changed: 2.5.0 - wrapper around ST_Intersection to work around GEOS bugs.
- No longer supports invalid input geometry.</para>
</refsection>
lwgeom_clip_by_rect(const LWGEOM *geom1, double x1, double y1, double x2, double y2)
{
LWGEOM *result;
- LWGEOM *tmp;
+ GEOSGeometry *g1, *g3;
+ int is3d;
- /* This lwgeom_intersection should be a call to GEOSClipByRect:
- * g3 = GEOSClipByRect(g1, x1, y1, x2, y2);
- * Unfortunately as of GEOS 3.7 it chokes on practical inputs.
- * GEOS ticket: https://trac.osgeo.org/geos/ticket/865
- */
+ /* A.Intersection(Empty) == Empty */
+ if ( lwgeom_is_empty(geom1) )
+ return lwgeom_clone_deep(geom1);
- LWGEOM *envelope = (LWGEOM *)lwpoly_construct_envelope(geom1->srid, x1, y1, x2, y2);
- result = lwgeom_intersection(geom1, envelope);
- lwgeom_free(envelope);
+ is3d = FLAGS_GET_Z(geom1->flags);
- if (!result) return NULL;
+ initGEOS(lwnotice, lwgeom_geos_error);
- /* clipping should not produce lower dimension objects */
- if (
- /* input has exact dimensionality, isn't a generic collection */
- geom1->type != COLLECTIONTYPE &&
- /* output may have different things inside */
- result->type == COLLECTIONTYPE)
- {
- tmp = lwcollection_as_lwgeom(lwcollection_extract(lwgeom_as_lwcollection(result), lwgeom_dimension(geom1) + 1));
- lwfree(result);
- result = tmp;
- if (!result) return NULL;
- }
+ if (!(g1 = LWGEOM2GEOS(geom1, AUTOFIX)))
+ GEOS_FAIL();
+
+ if (!(g3 = GEOSClipByRect(g1, x1, y1, x2, y2)))
+ GEOS_FREE_AND_FAIL(g1);
+
+ GEOS_FREE(g1);
+ result = GEOS2LWGEOM(g3, is3d);
+ GEOS_FREE(g3);
+
+ if (!result)
+ GEOS_FAIL();
- /* clean up stray points on geometry boundary */
- lwgeom_simplify_in_place(result, 0.0, LW_TRUE);
+ result->srid = geom1->srid;
return result;
}
1|BOX(5 5,10 10)
2|BOX(5 5,8 8)
3|BOX(2 2,8 8)
-4|MULTIPOINT(0 0,2 2)
-ERROR: lwgeom_intersection: GEOS Error: TopologyException: Input geom 0 is invalid: Self-intersection
-6|MULTIPOLYGON(((2.5 2,5 4,5 5,10 5,10 2,2.5 2)))
+4|POINT(2 2)
+5|POLYGON((2 2,8 2,2 8,8 8,2 2))
+6|POLYGON((2.5 2,5 4,5 5,5 4,7.5 2,2.5 2))
7|POLYGON((2 2,2 5,5 5,5 2,2 2))
8|SRID=3857;POLYGON EMPTY
9|SRID=4326;POINT(0 0)
PG6|POLYGON((894 2704,600 594,2791 594,894 2704))
PG7|POLYGON((1252 1904,1253 1905,1253 1906,1251 1904,1252 1904))
PG8|MULTIPOLYGON(((5 4096,10 4091,10 4096,5 4096)),((5 4096,0 4101,0 4096,5 4096)))
-PG9|POLYGON((4096 4096,0 4096,0 0,4096 0,4096 4096))
+PG9|POLYGON((0 4096,0 0,4096 0,4096 4096,0 4096))
PG10|
PG11|POLYGON((0 10,0 0,10 0,10 10,0 10))
PG12|POLYGON((0 10,0 0,10 0,10 10,0 10))
PG41 - OFF|LINESTRING(0 10,0 4,0 2,0 0,1 0)
PG42 - ON |LINESTRING(0 10,0 0,1 0)
PG42 - OFF|LINESTRING(0 10,0 0,1 0)
-NOTICE: lwgeom_intersection: GEOS Error: TopologyException: Input geom 0 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
-PG43 - ON |MULTIPOLYGON(((0 10,5 5,10 10,0 10)),((5 5,0 0,10 0,5 5)))
+PG43 - ON |MULTIPOLYGON(((5 5,0 0,10 0,5 5)),((0 10,5 5,10 10,0 10)))
PG43 - OFF|MULTIPOLYGON(((5 5,-1 -1,11 -1,5 5)),((5 5,11 11,-1 11,5 5)))
TG1|GiEKBHRlc3QSDBICAAAYASIECTLePxoCYzEiAigBKIAgeAI=
TG2|GiMKBHRlc3QSDhICAAAYASIGETLePwIBGgJjMSICKAEogCB4Ag==