Skip to content

Instantly share code, notes, and snippets.

@hjanetzek
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hjanetzek/d65b13179522098527d7 to your computer and use it in GitHub Desktop.
Save hjanetzek/d65b13179522098527d7 to your computer and use it in GitHub Desktop.
CREATE OR REPLACE FUNCTION gis.split_polygon(poly geometry, expand double precision DEFAULT 0.0001, srid integer DEFAULT 3857, level integer DEFAULT 0)
RETURNS SETOF geometry AS
$BODY$
declare
num_points integer;
env geometry;
p1 geometry;
p2 geometry;
b1 geometry;
b2 geometry;
mid double precision;
diffx double precision;
diffy double precision;
tmp geometry;
begin
if geometrytype(poly) != 'POLYGON' then
raise notice 'not a polygon! %', st_geometrytype(poly);
return;
end if;
num_points := ST_NumPoints(ST_ExteriorRing(poly));
if num_points < 500 or level > 1000 then
return next poly;
return;
--raise notice 'end %', level;
else
env := ST_Envelope(poly);
diffx := st_xmax(env) - st_xmin(env);
diffy := st_ymax(env) - st_ymin(env);
if diffx < st_ymax(env) - st_ymin(env) then
if expand * 4 >= diffy then
return next poly;
return;
end if;
mid := diffy / 2.0;
b1 := ST_MakeEnvelope(st_xmin(env), st_ymin(env), st_xmax(env), st_ymin(env)+mid, srid);
b2 := ST_MakeEnvelope(st_xmin(env), st_ymin(env)+mid, st_xmax(env), st_ymax(env), srid);
else
if expand * 4 >= diffx then
return next poly;
return;
end if;
mid := diffx / 2.0;
b1 := ST_MakeEnvelope(st_xmin(env), st_ymin(env), st_xmin(env)+mid, st_ymax(env), srid);
b2 := ST_MakeEnvelope(st_xmin(env)+mid, st_ymin(env), st_xmax(env), st_ymax(env), srid);
end if;
b1 := ST_SnapToGrid(ST_Expand(b1, expand), expand/2);
b2 := ST_SnapToGrid(ST_Expand(b2, expand), expand/2);
--raise notice 'split %d', level;
begin
p1 := ST_Intersection(poly, b1);
p2 := ST_Intersection(poly, b2);
exception when others then begin
raise notice 'buffer poly' ;
tmp := st_buffer(poly,0);
p1 := ST_Intersection(tmp, b1);
p2 := ST_Intersection(tmp, b2);
exception when others then
return next poly;
return;
end; end;
return query select gis.split_polygon(p.geom, expand, srid, level + 1) from
(select (ST_Dump(p1)).geom as geom) p where st_dimension(p.geom) = 2;
return query select gis.split_polygon(p.geom, expand, srid, level + 1) from
(select (ST_Dump(p2)).geom as geom) p where st_dimension(p.geom) = 2;
end if;
end;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment