3

I have a polygon layer containing titles which are grouped by a property ID (i.e. there may be one or more title polygon per property)

I need to generate an internal buffer of those unioned titles/of the property but can't quite get it working- with the code below, the internal buffer is generated but for all titles individually (i.e. there are buffers on the internal divisions)

How can I apply a union to the 'titles' before the difference?

Alternatively, is there a better way of generating an internal buffer of unioned/merged polygons grouped by an attribute?

SELECT
  row_number() OVER () AS fid,
  g.geom::geometry(Polygon,2193) AS geom,
  g.forest_id
FROM (
  SELECT
    (ST_Dump(
       ST_Union(
         ST_Difference(
           titles.geom,
           ST_Buffer(titles.geom, - 10::double precision)
         )
       )
    )).geom AS geom,
    titles.forest_id
  FROM public.titles
  GROUP BY titles.forest_id) g;

example of problem

2
  • How about moving the ST_Union inside the call to ST_Buffer?
    – dr_jts
    Commented Dec 13, 2022 at 5:38
  • I have tried but I can't get the syntax correct :( (I find the pgadmin syntax error messages rather unhelpful as they refer to line numbers which aren't even in the query)
    – Tim
    Commented Dec 15, 2022 at 23:04

1 Answer 1

2

To create the residue area of a subtraction of unioned titles.geom and their negative buffer based on common titles.forest_id, run:

SELECT
  ROW_NUMBER() OVER() AS fid,
  u.forest_id,
  dmp.path[1] AS seq,
  dmp.geom
FROM (
  SELECT
    forest_id,
    ST_Union(geom) AS geom
  FROM
    titles
  GROUP BY
    1
) AS u,
  LATERAL ST_Dump(
    ST_Difference(
      u.geom,
      ST_Buffer(u.geom, -10)
    )
  ) AS dmp
;

Update:

If your geometric conditions are simple enough, it is more performant to create a side-specific buffer along the ST_Boundary of the unioned geometries; see the example section in the docs for ST_Buffer.

Since I'm at it, here's a possible alternative to the above; on larger datasets, this should definitely be a lot faster.

SELECT
  ROW_NUMBER() OVER() AS fid,
  u.forest_id,
  buf AS geom
FROM (
  SELECT
    forest_id,
    ST_Union(geom) AS geom
  FROM
    titles
  GROUP BY
    1
) AS u,
  LATERAL ST_Buffer(
    ST_Boundary(u.geom),
    10,
    'side=right'
  ) AS buf
;

Note that you need to make sure all your Polygons are oriented the same (i.e. via ST_ForceRHR, either on-the-fly or as an UPDATE to the table) for the side=left|right parameter working as expected.

3
  • That query (although it does get rejigged after saving in pgadmin) returns a geometry-less table?
    – Tim
    Commented Dec 15, 2022 at 23:50
  • @Tim ah yes, the arguments passed to ST_DIfference were in the wrong order - fixed that in the query above.
    – geozelot
    Commented Dec 16, 2022 at 9:04
  • Brilliant- thank you, that's exactly what I was after.
    – Tim
    Commented Dec 19, 2022 at 2:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.