diff --git a/pg/sql/0.0.1/05_cdb_union_adjacent.sql b/pg/sql/0.0.1/05_cdb_union_adjacent.sql new file mode 100644 index 0000000..2450dde --- /dev/null +++ b/pg/sql/0.0.1/05_cdb_union_adjacent.sql @@ -0,0 +1,43 @@ +CREATE OR REPLACE FUNCTION _cdb_final_union_adjacent( joined_geoms geometry[] ) +RETURNS geometry[] AS $$ +BEGIN + RETURN joined_geoms; +END +$$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION _cdb_state_update_union_adjacent(clusters geometry[], new_geom geometry) +RETURNS geometry[] AS $$ +DECLARE + joins geometry[] :='{}'; + unjoined geometry[] :='{}'; + i integer; + combined geometry; +BEGIN + joins := (select array_agg(g) + from unnest(clusters) a(g) + where ST_TOUCHES(g, new_geom)); + + unjoined := (select array_agg(g) + from unnest(clusters) a(g) + where ST_TOUCHES(g, new_geom) = false); + + IF array_length(joins, 1) > 0 THEN + joins := array_append(joins, new_geom); + combined := ST_UNION(joins); + ELSE + combined := new_geom; + END IF; + + unjoined := array_append(unjoined, combined); + RETURN unjoined; +END +$$ +LANGUAGE plpgsql; + +CREATE AGGREGATE cdb_union_adjacent(geometry)( + SFUNC=_cdb_state_update_union_adjacent, + STYPE=geometry[], + FINALFUNC=_cdb_final_union_adjacent, + INITCOND='{}' +); diff --git a/pg/test/0.0.1/expected/05_cdb_union_adjacent_test.out b/pg/test/0.0.1/expected/05_cdb_union_adjacent_test.out new file mode 100644 index 0000000..21f7ffd --- /dev/null +++ b/pg/test/0.0.1/expected/05_cdb_union_adjacent_test.out @@ -0,0 +1,5 @@ +st_astext +------------------------------------------------ +POLYGON((1 0,0 0,0 1,0 2,1 2,1 1,2 1,2 0,1 0)) +POLYGON((4 1,4 0,3 0,3 1,3 2,4 2,4 1)) +(2 rows) diff --git a/pg/test/0.0.1/sql/05_cdb_union_adjacent_test.sql b/pg/test/0.0.1/sql/05_cdb_union_adjacent_test.sql new file mode 100644 index 0000000..e1adec4 --- /dev/null +++ b/pg/test/0.0.1/sql/05_cdb_union_adjacent_test.sql @@ -0,0 +1,9 @@ +\i test/fixtures/touching_polygons.sql + +WITH joined_polygons AS ( + SELECT cdb_union_adjacent(the_geom) the_geom FROM touching_polygons +), +unnested_polygons as ( + select unnest(joined_polygons.the_geom) the_geom from joined_polygons +) +select ST_ASTEXT(unnested_polygons.the_geom) from unnested_polygons; diff --git a/pg/test/fixtures/touching_polygons.sql b/pg/test/fixtures/touching_polygons.sql new file mode 100644 index 0000000..82c715b --- /dev/null +++ b/pg/test/fixtures/touching_polygons.sql @@ -0,0 +1,8 @@ +-- test table (polygons, some of which touch and some which dont) +CREATE TABLE touching_polygons(cartodb_id integer, the_geom geometry); +INSERT INTO touching_polygons VALUES +(1, ST_GeomFromText('POLYGON ((0 0, 1 0,1 1, 0 1, 0 0 ))')), +(2, ST_GeomFromText('POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))')), +(1, ST_GeomFromText('POLYGON ((0 1, 1 1,1 2, 0 2, 0 1 ))')), +(4, ST_GeomFromText('POLYGON ((3 0, 4 0, 4 1, 3 1, 3 0))')), +(5, ST_GeomFromText('POLYGON ((3 1, 4 1, 4 2, 3 2, 3 1))'));