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

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