Skip to content

Instantly share code, notes, and snippets.

@bjornharrtell
Last active August 29, 2015 14:24
Show Gist options
  • Save bjornharrtell/3b62a4704899eec90a2c to your computer and use it in GitHub Desktop.
Save bjornharrtell/3b62a4704899eec90a2c to your computer and use it in GitHub Desktop.
split_polygon
CREATE OR REPLACE FUNCTION osm.split_polygon(polygon geometry, level integer)
RETURNS SETOF geometry AS
$BODY$
DECLARE
num_points int;
mid double precision;
envelope geometry;
b1 geometry;
b2 geometry;
geom1 geometry;
geom2 geometry;
BEGIN
num_points = ST_NumPoints(ST_ExteriorRing(polygon));
IF num_points < 1000 THEN
RETURN NEXT polygon;
RETURN;
END IF;
envelope = ST_Envelope(polygon);
IF ST_XMax(envelope) - ST_XMin(envelope) < ST_YMax(envelope) - ST_YMin(envelope) THEN
mid = (ST_YMax(envelope) + ST_YMin(envelope)) / 2;
b1 = ST_MakeEnvelope(ST_XMin(envelope), ST_YMin(envelope), ST_XMax(envelope), mid);
b2 = ST_MakeEnvelope(ST_XMin(envelope), mid, ST_XMax(envelope), ST_YMax(envelope));
ELSE
mid = (ST_XMax(envelope) + ST_XMin(envelope)) / 2;
b1 = ST_MakeEnvelope(ST_XMin(envelope), ST_YMin(envelope), mid, ST_YMax(envelope));
b2 = ST_MakeEnvelope(mid, ST_YMin(envelope), ST_XMax(envelope), ST_YMax(envelope));
END IF;
geom1 = ST_ClipByBox2D(polygon, b1);
geom2 = ST_ClipByBox2D(polygon, b2);
IF (GeometryType(geom1) = 'POLYGON' OR GeometryType(geom1) = 'MULTIPOLYGON') AND
(GeometryType(geom2) = 'POLYGON') OR (GeometryType(geom2) = 'MULTIPOLYGON') THEN
FOR i IN 1..ST_NumGeometries(geom1) LOOP
RETURN QUERY SELECT osm.split_polygon(ST_GeometryN(geom1,i), level+1);
END LOOP;
FOR i IN 1..ST_NumGeometries(geom2) LOOP
RETURN QUERY SELECT osm.split_polygon(ST_GeometryN(geom2,i), level+1);
END LOOP;
RETURN;
END IF;
RETURN NEXT polygon;
END;
$BODY$
@bjornharrtell
Copy link
Author

The above PL/pgSQL is ported from osmcoastline C++. No support for expand to overlap and destination should be a parameter but perhaps this might be useful for some since it works directly in postgis. Also some hardcoded SRS 3006 here and there...

@bjornharrtell
Copy link
Author

Replacing ST_Intersects with ST_ClipByBox2D still give good output for me :) Was 5x faster than ST_Subdivide before this and now it's something like 50x faster. :)

@bjornharrtell
Copy link
Author

Refactored to return SETOF geometry and removed hardcoded SRS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment