Skip to main content
Added a line separator, missing Waldo in the example, Bob Ross in the bobrossed part.
Source Link
Zegarek
  • 787
  • 3
  • 11
 

enter image description hereenter image description here

It can stitch shapes broken along a tile boundary back together, but as you can see it works with arbitrarily shaped splits just as well - I just smashed my two squares into pieces, threw some away and shook everything hard to make a bit of mess*.enter image description here

enter image description here

It can stitch shapes broken along a tile boundary back together, but as you can see it works with arbitrarily shaped splits just as well - I just smashed my two squares into pieces, threw some away and shook everything hard to make mess*.

 

enter image description here

It can stitch shapes broken along a tile boundary back together, but as you can see it works with arbitrarily shaped splits just as well - I just smashed my two squares into pieces, threw some away and shook everything hard to make a bit of mess*.enter image description here

added 1973 characters in body
Source Link
Zegarek
  • 787
  • 3
  • 11

How to merge polygons that share some features

If the same "original" shape has the same cat and unid in both tables, you can just UNION the tables, then ST_Union() the shapes back together, grouping by cat and unid:

create table hrl_tst.your_shapes_back_together as
with both_tiles as (table hrl_tst.tile1 union all table hrl_tst.tile2)
select cat
      ,unid
      ,st_union(geom) as geom
from both_tiles 
group by cat,unid;

This will use the aggregate variant of ST_Union() and dissolve all shapes that share the same unid and cat from both tables at the same time.
Your example used two-variant ST_Union() in STEP 1 that kept only dissolving two shapes at a time and in STEP 2 you merged those pairs into groups sharing one common shape, which is still a few steps away from dissolving the whole group.

How to merge polygons that touch and share some features

create table hrl_tst.your_shapes_back_together as
with both_tiles as (table hrl_tst.tile1 union all table hrl_tst.tile2)
,clustered as (
    select *,ST_ClusterDBSCAN(geom,0,1)over(partition by cat) c_num
    from both_tiles)
select cat
      ,unid
      ,st_makevalid(st_union(geom)) as geom --it's healthy to `st_makevalid()`
from clustered
group by cat,unid,c_num;

Problems withAbout your initial approach

How to merge polygons that touch and share some features

Problems with your initial approach

How to merge polygons that share some features

If the same "original" shape has the same cat and unid in both tables, you can just UNION the tables, then ST_Union() the shapes back together, grouping by cat and unid:

create table hrl_tst.your_shapes_back_together as
with both_tiles as (table hrl_tst.tile1 union all table hrl_tst.tile2)
select cat
      ,unid
      ,st_union(geom) as geom
from both_tiles 
group by cat,unid;

This will use the aggregate variant of ST_Union() and dissolve all shapes that share the same unid and cat from both tables at the same time.
Your example used two-variant ST_Union() in STEP 1 that kept only dissolving two shapes at a time and in STEP 2 you merged those pairs into groups sharing one common shape, which is still a few steps away from dissolving the whole group.

How to merge polygons that touch and share some features

create table hrl_tst.your_shapes_back_together as
with both_tiles as (table hrl_tst.tile1 union all table hrl_tst.tile2)
,clustered as (
    select *,ST_ClusterDBSCAN(geom,0,1)over(partition by cat) c_num
    from both_tiles)
select cat
      ,unid
      ,st_makevalid(st_union(geom)) as geom --it's healthy to `st_makevalid()`
from clustered
group by cat,unid,c_num;

About your initial approach

added 1973 characters in body
Source Link
Zegarek
  • 787
  • 3
  • 11

If your unid field is unique but spans the sets, meaning that the same shape's split between the two tables but holds the same unid in both, and you don't want to merge shapes of differenddifferent unid, you can add unid anywhere on the group by list and swap out array_agg() for just unid.


Problems with your initial approach

  1. A join results in pairs, which you don't want if you aim to connect more than two things in each row.
  2. By joining the two tables, you not only didn't achieve your goal, you duplicated your data. Each time you had a shape on in hrl_tst.tile1 that touched N shapes in hrl_tst.tile2 with the same cat, the first shape got repeated N times on output, one time with each of those N touching shapes in tile2.
    If you only inspected your intermediate results visually, you probably didn't see them, since they'll be in the exact same spot. If you increase transparency, you'll see undissolved lines everywhere, because those shapes will each time dissolve with one neighbour at a time.
  3. You're not supposed to use the two-input variant of ST_Union() here, at all - not over a window, not directly. You want the aggregate variant, but you also need a way to apply it to entire clusters of touching shapes. Not all shapes of the same cat, not pairs of touching shapes - whole clusters or groups of touching shapes.
  4. Technically, there is a way to do that with a bunch of joins and the two-input st_union, if you used a recursive query, made pairs, them kept joining more and more shapes to those, until you ran out. It'd be a slow, ungly Goldberg machine, and run out of memory pretty fast.
  5. Your observation that you got different results by splitting STEP 2 was likely due to the duplication. One time your map viewer showed one set of merged pairs on top obfuscating the ones below, another time it sunk them down below, giving you an impression that those are different results, while you were just viewing different subsets of the same overall set.

If your unid field is unique but spans the sets, meaning that the same shape's split between the two tables but holds the same unid in both, and you don't want to merge shapes of differend unid, you can add unid anywhere on the group by list and swap out array_agg() for just unid.

If your unid field is unique but spans the sets, meaning that the same shape's split between the two tables but holds the same unid in both, and you don't want to merge shapes of different unid, you can add unid anywhere on the group by list and swap out array_agg() for just unid.


Problems with your initial approach

  1. A join results in pairs, which you don't want if you aim to connect more than two things in each row.
  2. By joining the two tables, you not only didn't achieve your goal, you duplicated your data. Each time you had a shape on in hrl_tst.tile1 that touched N shapes in hrl_tst.tile2 with the same cat, the first shape got repeated N times on output, one time with each of those N touching shapes in tile2.
    If you only inspected your intermediate results visually, you probably didn't see them, since they'll be in the exact same spot. If you increase transparency, you'll see undissolved lines everywhere, because those shapes will each time dissolve with one neighbour at a time.
  3. You're not supposed to use the two-input variant of ST_Union() here, at all - not over a window, not directly. You want the aggregate variant, but you also need a way to apply it to entire clusters of touching shapes. Not all shapes of the same cat, not pairs of touching shapes - whole clusters or groups of touching shapes.
  4. Technically, there is a way to do that with a bunch of joins and the two-input st_union, if you used a recursive query, made pairs, them kept joining more and more shapes to those, until you ran out. It'd be a slow, ungly Goldberg machine, and run out of memory pretty fast.
  5. Your observation that you got different results by splitting STEP 2 was likely due to the duplication. One time your map viewer showed one set of merged pairs on top obfuscating the ones below, another time it sunk them down below, giving you an impression that those are different results, while you were just viewing different subsets of the same overall set.
deleted 2 characters in body
Source Link
Zegarek
  • 787
  • 3
  • 11
Loading
Source Link
Zegarek
  • 787
  • 3
  • 11
Loading