TransWikia.com

Performing identity operation in PostGIS?

Geographic Information Systems Asked by Kaplan on June 12, 2021

I would like to perform spatial identity operation (ArcGIS example here) using PostGIS. I have two polygon tables, one of which is the input layer and the other table is the overlay layer. The output should be the original input layer but broken up to pieces where the overlay layer intersects it. This could get complex as multiple overlay polygons can intersect the input polygons. The output table need to have all the original fields of the input table plus a column from the overlay table. This extra column will have the data from the overlay table where they intersect and a fixed value like -1 or NA in non-overlapping areas.

How can this be done in PostGIS?

I am looking for an efficient solution as my input table has about 400k and my overlay table has about 20 million records.

2 Answers

Install the PostGIS Addons and look at the ST_SplitAgg() example.

Here is a query doing an overlay between two independent tables and joining the attributes of the second layer to the first layer:

WITH geomtableA AS (
  SELECT 0 id, ST_GeomFromText('POLYGON((5 5, 5 7, 7 7, 7 5, 5 5))') geom
  UNION ALL
  SELECT 1 id, ST_GeomFromText('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0), (0.2 0.5, 0.2 1.5, 0.8 1.5, 0.8 0.5, 0.2 0.5))') geom
  UNION ALL
  SELECT 2 id, ST_GeomFromText('POLYGON((2 0.5, 2 1.5, 4 1.5, 4 0.5, 2 0.5))') geom
), geomtableB AS (
  SELECT 3 id, ST_GeomFromText('POLYGON((1 0.2, 1 1, 3 1, 3 0.2, 1 0.2))') geom
  UNION ALL
  SELECT 4 id, ST_GeomFromText('POLYGON((1.5 1, 1.5 1.4, 2.5 1.4, 2.5 1, 1.5 1))') geom
), overlay AS (
  SELECT DISTINCT ON (geom) a.id, unnest(ST_SplitAgg(a.geom, b.geom, 0.00001)) geom
  FROM geomtableA a LEFT JOIN
       geomtableB b
  ON ST_Equals(a.geom, b.geom) OR
        ST_Contains(a.geom, b.geom) OR
        ST_Contains(b.geom, a.geom) OR
        ST_Overlaps(a.geom, b.geom)
  GROUP BY a.id
  ORDER BY geom, max(ST_Area(a.geom)) DESC
)
SELECT a.id aid, b.id bid, a.geom
FROM overlay a LEFT JOIN geomtableB b
ON ST_Within(ST_Centroid(a.geom), b.geom);

Correct answer by Pierre Racine on June 12, 2021

These steps should produce an output similiar to the ESRI Identity Tool.
You should create a Spatial Index on each layer, before each command.
I'm unsure if PostGIS creates a spatial index automatically.

  1. ST_Intersection Input and Overlay (this produces stacked polygons that overlap), output as intersect01.
  2. Perform a spatial join on intersect01, adding the 01 Overlay attribute to the 01 Input polygon in intersect01.
  3. Delete the Overlay polygons from intersect01, they are no longer needed.
  4. ST_Difference Input and Intersect01 (these are Input areas that do not overlap Overlay), output as difference02.
  5. Insert difference02 into intersect01, output as Final03.

Answered by klewis on June 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP