D 2014-08-27T13:00:34.949 L liblwgeom-4.0 P 974b02eb4d86705ac227f81a0d0274309fb3df95 U sandro W 14346
SELECT Count(*) FROM com2011 WHERE ST_IsValid(geometry) = 0; 19 |
UPDATE com2011 SET geometry = ST_MakeValid(geometry) WHERE ST_IsValid(geometry) = 0; |
SELECT Count(*) FROM com2011 WHERE ST_IsValid(geometry) = 0; 0 |
Why the Bronte Local Council boundary was malformed ? a quick analysis | |
---|---|
malformed / invalid | valid |
![]() |
![]() |
As you can easily notice, the invalid polygon was simply represent by the exterior ring: but there is a huge internal hole in this Polygon.
This odd condition is reputed perfectly valid by some mainstream proprietary software; anyway, is actually invalid accordingly to standard rules. So the correct representation for this Polygon requires an exterior ring and a separate interior ring; ST_MakeValid() does the magic, thus recovering a full valid Polygon. |
SELECT g, ST_MakeValid(g), ST_MakeValidDiscarded(g) FROM ( SELECT ST_GeomFromText('POLYGON((0 0, 0 10, 11 10, 10 10, 10 1, 5 1, 5 9, 5 1, 0 1, 0 0))') AS g ); |
This figure represents the invalid Polygon returned by ST_GeomFromText(). There are three spikes in the exterior ring, and this one surely is a severe invalidity cause. |
![]() |
This figure represents the valid Polygon returned by ST_MakeValid(). Now we have a nice regular rectangle, all spikes have been removed. |
![]() |
Anyway the removed spikes aren't simply vanished into nothing.
You could eventually retrieve (and may be, saving somewhere for further processing / editing) all offending elements being discarded during the validation process. You simply have to invoke ST_MakeValidDiscarded() Please note: this is strongly different from the PostGIS own implementation. |
![]() |
SELECT ST_Split(input.g, blade.g), ST_SplitLeft(input.g, blade.g), ST_SplitRight(input.g, blade.g) FROM (SELECT GeomFromText('LINESTRING(0 10, 2 0, 4 4, 6 0, 10 10)') AS g) AS input, (SELECT GeomFromText('POINT(3 2)') AS g) AS blade; |
The ST_Split() SQL function will simply return a collection aggregating all fragments deriving from the cut.
This isn't really useful on many cases. Please note: collections in SpatiaLite behave quite differently from PostGis. |
![]() |
The ST_SplitLeft() SQL function will return instead a collection aggregating all fragments laying on the left side of the cut. For Linestrings you cannot intend left in the very literal sense; this really means the side where the start-point lay. Please note: if the blade doesn't intercepts the target at all, than no cut would be obviously possible. In this special case the original target Geometry will be always returned (absolutely unchanged) on the left side collection. |
![]() |
The ST_SplitRight() SQL function will return a collection aggregating all fragments laying on the right side of the cut. For Linestrings you cannot intend right in the very literal sense; this really means the side where the end-point lay. Please note: if the blade doesn't intercepts the target at all, than no cut would be obviously possible. In this special case the right side collection will be NULL. |
![]() |
SELECT ST_Split(input.g, blade.g), ST_SplitLeft(input.g, blade.g), ST_SplitRight(input.g, blade.g) FROM (SELECT GeomFromText('POLYGON((0 1, 10 1, 10 9, 0 9, 0 1), (2 2, 7 2, 7 6, 2 6, 2 2))') AS g) AS input, (SELECT GeomFromText('LINESTRING(2 0, 6 10)') AS g) AS blade; |
The ST_Split() SQL function will simply return a collection aggregating all fragments deriving from the cut. Exactly as we have already previously seen on the Linestring case. |
![]() |
The ST_SplitLeft() SQL function will return instead a collection aggregating all fragments laying on the left side of the cut. For Polygons left really means left side (at least, this is true when the blade is almost vertically oriented). Please note: if the blade doesn't intercepts the target at all, than no cut would be obviously possible. In this special case the original target Geometry will be always returned (absolutely unchanged) on the left side collection. |
![]() |
The ST_SplitRight() SQL function will return a collection aggregating all fragments laying on the right side of the cut. Please note: if the blade doesn't intercepts the target at all, than no cut would be obviously possible. In this special case the right side collection will be NULL. |
![]() |
SELECT geometry, ST_Segmentize(geometry, 10.0) FROM com2011 WHERE nome_com = 'Bronte'; |
original | segmentized |
---|---|
![]() |
![]() |
As you can easily notice, there are many more vertices in the segmentized Geometry. We imposed the constraint that no segment could be longer than 10m, thus causing many more vertices to be interpolated. The overall shape is absolutely unchanged. |
SELECT Degrees(ST_Azimuth(MakePoint(0, 0), MakePoint(0, 1)));
0.0 |
SELECT Degrees(ST_Azimuth(MakePoint(0, 0), MakePoint(1, 1)));
45.0 |
SELECT Degrees(ST_Azimuth(MakePoint(0, 0), MakePoint(1, 0)));
90.0 |
SELECT Degrees(ST_Azimuth(MakePoint(0, 0), MakePoint(0, -1)));
180.0 |
SELECT ST_SnapToGrid(geometry, 250.0) FROM com2011 WHERE nome_com = 'Bronte'; |
Yet again another time the Bronte Local Council boundary. By invoking ST_SnapToGrid() this time the Geometry has been strongly simplified (please notice; many vertices have been suppressed). The imposed grid size (250m) is absolutely unrealistic and exaggerated for any practical purpose. Anyway a such strong factor is useful in order to clearly show what really happens:
|
![]() |
Credits |
---|
This work (exposing liblwgeom APIs as SpatiaLite own SQL functions) has been entirely funded by: Tuscany Region - Territorial and Environmental Information System Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale. |