Blog

Blog

PostGIS 2.0 New Features: ST_MakeValid

The bane of PostGIS users since time immemorial has been the “invalid feature”. An invalid feature is one that disobeys the structural rules of its type. The more complicated the type, the more ways an object can be invalid.

  • Points are never invalid. How can you screw up a point?
  • Linestrings are almost never invalid. Only a two-point line where the start and end are the same is invalid.
  • Polygons have lots of ways to be invalid. Rings have to close. Rings can’t self-intersect. Rings can only touch other rings once, at a point. Inner rings have to be inside outer rings.
  • Polyhedralsurfaces… I don’t have enough space. Imagine a face defined as a 3D polygon and you get the picture. All the rules of polygons, plus rules like requiring all points on all rings to be co-planar.

My favorite invalid polygon (doesn’t everyone have a favorite invalid polygon?) is the figure-eight, because it’s so obviously wrong, and because it demonstrates the importance of validity rules so elegantly.

POLYGON((-1 -1, -1 0, 1 0, 1 1, 0 1, 0 -1, -1 -1))

Want to see why validity is important? Run ST_Area() on this polygon. The answer? Zero. The area algorithm expects that rings bound areas using a consistent orientation of edges to the bounded area. But you can see in the figure-eight diagram above, one lobe is bounded by clockwise edges and the other lobe by anti-clockwise edges. So the calculation looks like this:

The way to represent this area validly is with a MultiPolygon consisting of two one-unit squares, so, run ST_MakeValid() and see what comes out!

SELECT ST_AsText(ST_MakeValid('POLYGON((-1 -1, -1 0, 1 0, 1 1, 0 1, 0 -1, -1 -1))'))
MULTIPOLYGON (((-1 -1,-1 0,0 0,0 -1,-1 -1)),((0 0,0 1,1 1,1 0,0 0)))

ST_MakeValid() will try to create a valid output without dropping vertices, so for some invalidities, the result is not exactly what one might like. For example, many hand digitized polygons have very small versions of the figure-eight case embedded in their edges. Users probably just want those little “polygon warts” to go away, but ST_MakeValid() will retain them, as tiny elements of a multipolygon. ST_MakeClean(), to remove small errors using a tolerance, awaits funding from some enterprising organization!

Tags: , , ,