Changes between Initial Version and Version 1 of UsersWikiExamplesOverlayTables2


Ignore:
Timestamp:
Mar 10, 2011, 5:26:43 AM (13 years ago)
Author:
blaggner
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • UsersWikiExamplesOverlayTables2

    v1 v1  
     1
     2== Spatial Overlay of 2 Polygon Tables - pgunion ==
     3
     4This user example describes a set of functions named pgunion. The functions of pgunion implement a spatial overlay of 2 polygon tables, which means that borders and areas of all geometries will be transferred to the result table forming new geometries. Every output geometry gets the IDs of the origin input geometries so that assignment of the attributes is possible.
     5
     6[[Image(pgunion_input.png)]] [[Image(pgunion_output.png)]]
     7
     8pgunion consists of 6 separate functions which have to be called all in a determined order:[[BR]]
     91. _pgunion_start[[BR]]
     102. _pgunion_intersection[[BR]]
     113. _pgunion_no_intersection[[BR]]
     124. _pgunion_difference_a[[BR]]
     135. _pgunion_difference_b[[BR]]
     146. _pgunion_merge[[BR]]
     15
     16Final result of pgunion consists of 3 tables:[[BR]]
     17- merged result table of the spatial overlay[[BR]]
     18- 2 tables with input geometries causing Topology Exceptions during _pgunion_difference_a and _pgunion_difference_b
     19
     20
     21Preconditions for the tables to be pgunioned:[[BR]]
     22- gid column of data type integer or serial, unique, with btree index!! [[BR]]
     23- the_geom column of data type geometry and geometry type POLYGON, with gist index!! [[BR]]
     24- column of data type integer (name is variable) for subsequent joining of attributes with btree index!! [[BR]]
     25- geometries should be valid (otherwise number of exceptions rises)[[BR]]
     26- geometries of each table should not overlap (otherwise result contains duplicate or overlapping geometries with different id-combinations)
     27
     28
     29'''Caution:''' Do not call the functions twice at a time!! - Intermediate tables have fixed names and are locked during function processing (otherwise their content would be overwritten).
     30
     31'''Example:'''
     32
     33{{{
     34CREATE TABLE pgunion_bsp_a (gid serial PRIMARY KEY, a_id integer, the_geom geometry);
     35INSERT INTO pgunion_bsp_a (a_id, the_geom) VALUES
     36(1,ST_GeomFromText('POLYGON((3565961 5361731,3570432 5359825,3574390 5362977,3577469 5360631,3582526 5360192,3591616 5351909,3592715 5343113,3591835 5337395,3586265 5339448,3579008 5336882,3572045 5340254,3567500 5338788,3564421 5342013,3562296 5353301,3566327 5356527,3565961 5361731))',31467)),
     37(2,ST_GeomFromText('POLYGON((3587846 5359101,3587353 5362736,3592036 5366371,3598813 5365755,3601708 5361997,3592528 5358855,3587846 5359101))',31467)),
     38(3,ST_GeomFromText('POLYGON((3600429 5353669,3606823 5355001,3612240 5361751,3622453 5355801,3637461 5355179,3635951 5340171,3617036 5337240,3605225 5340260,3600429 5353669))',31467)),
     39(4,ST_GeomFromText('POLYGON((3580359 5328360,3588529 5330935,3597943 5323120,3606024 5322587,3612951 5315217,3608155 5306691,3603804 5305093,3596166 5306159,3591105 5310244,3584799 5310688,3576540 5317437,3580359 5328360))',31467));
     40
     41CREATE TABLE pgunion_bsp_b (gid serial PRIMARY KEY, b_id integer, the_geom geometry);
     42INSERT INTO pgunion_bsp_b (b_id, the_geom) VALUES
     43(1,ST_GeomFromText('POLYGON((3568123 5343184,3577776 5350721,3586922 5344624,3584890 5336664,3593104 5330312,3586499 5322014,3572187 5325232,3568123 5343184))',31467)),
     44(2,ST_GeomFromText('POLYGON((3594628 5349620,3601741 5358935,3617153 5357580,3621387 5348519,3617153 5339712,3610040 5334293,3616137 5322945,3607923 5311598,3600302 5314392,3596068 5319727,3600725 5329974,3596406 5339882,3594628 5349620))',31467)),
     45(3,ST_GeomFromText('POLYGON((3622319 5325401,3625029 5327433,3630194 5329466,3635191 5326502,3638747 5317610,3631719 5311598,3622150 5316594,3622319 5325401))',31467));
     46
     47SELECT _pgunion_start('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public');
     48SELECT _pgunion_intersection('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public','pgunion_bsp_intsec');
     49SELECT _pgunion_no_intersection('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public','pgunion_bsp_intsec','pgunion_bsp_nointsec_a','pgunion_bsp_nointsec_b');
     50SELECT _pgunion_difference_a('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public','pgunion_bsp_diff_a','pgunion_bsp_diff_a_exceptions');
     51SELECT _pgunion_difference_b('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public','pgunion_bsp_diff_b','pgunion_bsp_diff_b_exceptions');
     52SELECT _pgunion_merge('a_id','b_id','public','pgunion_bsp_intsec','pgunion_bsp_nointsec_a','pgunion_bsp_nointsec_b','pgunion_bsp_diff_a','pgunion_bsp_diff_b','pgunion_bsp_result');
     53}}}
     54
     55
     56'''Functions:'''
     57{{{
     58/*
     59pgunion consists of 6 separate functions which have to be called all in a determined order:
     601. _pgunion_start
     612. _pgunion_intersection
     623. _pgunion_no_intersection
     634. _pgunion_difference_a
     645. _pgunion_difference_b
     656. _pgunion_merge
     66
     67Preconditions for the tables to be pgunioned:
     68- gid column of data type integer or serial, unique, with btree index!!
     69- the_geom column of data type geometry and geometry type POLYGON, with gist index!!
     70- column of data type integer (name is variable) for subsequent joining of attributes with btree index!!
     71- geometries should be valid (otherwise number of exceptions rises)
     72- geometries of each table should not overlap (otherwise result contains duplicate or overlapping geometries with different id-combinations)
     73
     74Caution: Do not call the functions twice at a time!! - Intermediate tables have fixed names and are locked during function processing (otherwise their content would be overwritten).
     75*/
     76
     77
     78CREATE OR REPLACE FUNCTION _pgunion_start(
     79 schema_a varchar,
     80 table_a varchar,
     81 a_id varchar,
     82 schema_b varchar,
     83 table_b varchar,
     84 b_id varchar,
     85 schema_z varchar)
     86RETURNS void AS
     87$BODY$
     88
     89/*
     90$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     91
     92pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     93_pgunion_start: 1st part of pgunion, establishes spatial relation between intersecting geometries of input tables
     94
     95schema_a:      database schema where 1st table is located
     96table_a:       name of 1st table
     97a_id:          id column name in 1st table
     98schema_b:      database schema where 2nd table is located
     99table_b:       name of 2nd table
     100b_id:          id column name in 2nd table
     101schema_z:      database schema where result table shall be located
     102
     103Copyright (C) 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     104Version 0.1
     105contact: birgit dot laggner at vti dot bund dot de
     106
     107This is free software; you can redistribute and/or modify it under
     108the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     109*/
     110
     111BEGIN
     112
     113EXECUTE
     114'DROP TABLE IF EXISTS '||schema_z||'.intersection_inner_join;';
     115
     116EXECUTE
     117'CREATE TABLE '||schema_z||'.intersection_inner_join (gid serial PRIMARY KEY, a_id integer, a_geom geometry, b_id integer, b_geom geometry);';
     118EXECUTE
     119'INSERT INTO '||schema_z||'.intersection_inner_join (a_id, a_geom, b_id, b_geom)
     120SELECT
     121a.'||a_id||',
     122a.the_geom,
     123b.'||b_id||',
     124b.the_geom
     125FROM
     126'||schema_a||'.'||table_a||' a
     127INNER JOIN
     128'||schema_b||'.'||table_b||' b
     129ON a.the_geom && b.the_geom
     130WHERE
     131ST_Intersects(a.the_geom, b.the_geom);';
     132
     133EXECUTE
     134'CREATE INDEX intersection_inner_join_btree_a_id ON '||schema_z||'.intersection_inner_join USING btree(a_id);';
     135EXECUTE
     136'CREATE INDEX intersection_inner_join_btree_b_id ON '||schema_z||'.intersection_inner_join USING btree(b_id);';
     137EXECUTE
     138'CREATE INDEX intersection_inner_join_gist_a ON '||schema_z||'.intersection_inner_join USING gist(a_geom);';
     139EXECUTE
     140'CREATE INDEX intersection_inner_join_gist_b ON '||schema_z||'.intersection_inner_join USING gist(b_geom);';
     141
     142 END;
     143$BODY$
     144LANGUAGE 'plpgsql' VOLATILE;
     145ALTER FUNCTION _pgunion_start(varchar, varchar, varchar, varchar, varchar, varchar, varchar) OWNER TO postgres;
     146
     147
     148--Intersection:
     149
     150CREATE OR REPLACE FUNCTION _pgunion_intersection(
     151  schema_a varchar,
     152  table_a varchar,
     153  a_id varchar,
     154  schema_b varchar,
     155  table_b varchar,
     156  b_id varchar,
     157  schema_z varchar,
     158  intersection varchar)
     159RETURNS void AS
     160$BODY$
     161
     162/*
     163$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     164
     165pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     166_pgunion_intersection: 2nd part of pgunion, creates table with intersection polygons
     167
     168schema_a:      database schema where 1st table is located
     169table_a:       name of 1st table
     170a_id:          id column name in 1st table
     171schema_b:      database schema where 2nd table is located
     172table_b:       name of 2nd table
     173b_id:          id column name in 2nd table
     174schema_z:      database schema where result table is located
     175intersection:  table name for intersection table
     176
     177Copyright: 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     178Version 0.1
     179contact: birgit dot laggner at vti dot bund dot de
     180
     181This is free software; you can redistribute and/or modify it under
     182the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     183*/
     184
     185DECLARE
     186
     187i integer;
     188sql_1 text;
     189
     190BEGIN
     191
     192EXECUTE
     193'DROP TABLE IF EXISTS '||schema_z||'.'||intersection||';';
     194
     195EXECUTE
     196'CREATE TABLE '||schema_z||'.'||intersection||' ('||
     197 'gid serial PRIMARY KEY, '||
     198 ''||a_id||' integer, '||
     199 ''||b_id||' integer '||
     200 ');';
     201
     202EXECUTE
     203'SELECT AddGeometryColumn('''||schema_z||''', '''||intersection||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);';
     204
     205EXECUTE
     206'ALTER TABLE '||schema_z||'.'||intersection||' DROP CONSTRAINT enforce_geotype_the_geom;';
     207
     208
     209RAISE NOTICE 'Starting Intersection. ';
     210
     211i:=0;
     212
     213sql_1:='SELECT gid FROM '||schema_z||'.intersection_inner_join ORDER BY gid;';
     214
     215FOR i IN EXECUTE sql_1 LOOP
     216
     217BEGIN
     218  EXECUTE
     219    'INSERT INTO
     220     '||schema_z||'.'||intersection||'
     221      ('||a_id||', '||b_id||', the_geom)
     222      SELECT
     223      a_id,
     224      b_id,
     225      (ST_Dump(ST_Intersection(a_geom, b_geom))).geom
     226      FROM '||schema_z||'.intersection_inner_join
     227      WHERE gid='||i||'';
     228
     229EXCEPTION
     230WHEN internal_error
     231THEN
     232  EXECUTE
     233    'INSERT INTO
     234     '||schema_z||'.'||intersection||'
     235      ('||a_id||', '||b_id||', the_geom)
     236      SELECT
     237      a_id,
     238      b_id,
     239      (ST_Dump
     240       (ST_Intersection
     241        (ST_SnapToGrid(ST_Buffer(a_geom,0.001),0.001),
     242         ST_SnapToGrid(ST_Buffer(b_geom,0.001),0.001))
     243       )).geom
     244      FROM '||schema_z||'.intersection_inner_join
     245      WHERE gid='||i||'';
     246
     247END;   
     248END LOOP;
     249
     250EXECUTE
     251'DELETE FROM '||schema_z||'.'||intersection||' WHERE
     252 ST_GeometryType(the_geom) IN (
     253 ''ST_Point'',
     254 ''ST_MultiPoint'',
     255 ''ST_Linestring'',
     256 ''ST_MultiLinestring'',
     257 ''ST_Line'') OR
     258 ST_IsEmpty(the_geom)=''t'';';
     259
     260EXECUTE
     261'DELETE FROM '||schema_z||'.intersection_inner_join WHERE
     262 gid IN (
     263  SELECT a.gid
     264  FROM
     265  '||schema_z||'.intersection_inner_join a
     266  LEFT JOIN
     267  '||schema_z||'.'||intersection||' b
     268  ON a.a_id=b.'||a_id||' AND a.b_id=b.'||b_id||'
     269  WHERE b.'||a_id||' IS NULL AND b.'||b_id||' IS NULL);';
     270
     271
     272RAISE NOTICE 'Intersection finished. ';
     273
     274
     275END;
     276$BODY$
     277LANGUAGE 'plpgsql' VOLATILE;
     278ALTER FUNCTION _pgunion_intersection(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar)
     279 OWNER TO postgres;
     280
     281
     282--No Intersection
     283
     284CREATE OR REPLACE FUNCTION _pgunion_no_intersection(
     285 schema_a varchar,
     286 table_a varchar,
     287 a_id varchar,
     288 schema_b varchar,
     289 table_b varchar,
     290 b_id varchar,
     291 schema_z varchar,
     292 intersection varchar,
     293 nointersect_a varchar,
     294 nointersect_b varchar)
     295RETURNS void AS
     296$BODY$
     297
     298/*
     299$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     300
     301pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     302_pgunion_no_intersection: 3rd part of pgunion, selects not intersecting polygons of both input tables
     303
     304schema_a:      database schema where 1st table is located
     305table_a:       name of 1st table
     306a_id:          id column name in 1st table
     307schema_b:      database schema where 2nd table is located
     308table_b:       name of 2nd table
     309b_id:          id column name in 2nd table
     310schema_z:      database schema where result table is located
     311intersection:  table name for intersection table
     312nointersect_a: table name for no intersection of 1st table
     313nointersect_b: table name for no intersection of 2nd table
     314
     315Copyright: 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     316Version 0.1
     317contact: birgit dot laggner at vti dot bund dot de
     318
     319This is free software; you can redistribute and/or modify it under
     320the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     321*/
     322
     323 BEGIN
     324 
     325--No Intersection a:
     326
     327EXECUTE
     328'DROP TABLE IF EXISTS '||schema_z||'.'||nointersect_a||';';
     329EXECUTE
     330'DROP TABLE IF EXISTS '||schema_z||'.'||nointersect_b||';';
     331
     332EXECUTE
     333'CREATE TABLE '||schema_z||'.'||nointersect_a||' ('||
     334 'gid serial PRIMARY KEY, '||
     335 ''||a_id||' integer, '||
     336 ''||b_id||' integer '||
     337 ');';
     338
     339EXECUTE
     340'SELECT AddGeometryColumn('''||schema_z||''', '''||nointersect_a||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);';
     341
     342EXECUTE
     343'ALTER TABLE '||schema_z||'.'||nointersect_a||' DROP CONSTRAINT enforce_geotype_the_geom;';
     344
     345EXECUTE
     346'CREATE TABLE '||schema_z||'.'||nointersect_b||' ('||
     347 'gid serial PRIMARY KEY, '||
     348 ''||a_id||' integer, '||
     349 ''||b_id||' integer '||
     350 ');';
     351
     352EXECUTE
     353'SELECT AddGeometryColumn('''||schema_z||''', '''||nointersect_b||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);';
     354 
     355EXECUTE
     356'ALTER TABLE '||schema_z||'.'||nointersect_b||' DROP CONSTRAINT enforce_geotype_the_geom;';
     357
     358
     359RAISE NOTICE 'Starting No Intersection for 1st table. ';
     360
     361EXECUTE
     362 'INSERT INTO
     363 '||schema_z||'.'||nointersect_a||'
     364  ('||a_id||', '||b_id||', the_geom)
     365  SELECT
     366   a.'||a_id||',
     367   NULL AS '||b_id||',           
     368   a.the_geom
     369  FROM '||schema_a||'.'||table_a||' a LEFT JOIN
     370       '||schema_z||'.'||intersection||' b ON
     371       a.'||a_id||'=b.'||a_id||'
     372 WHERE b.'||a_id||' is NULL';
     373
     374RAISE NOTICE 'finished ';
     375
     376--No Intersection b:
     377
     378RAISE NOTICE 'Starting No Intersection for 2nd table. ';
     379
     380EXECUTE
     381 'INSERT INTO
     382  '||schema_z||'.'||nointersect_b||'
     383  ('||a_id||', '||b_id||', the_geom)
     384 SELECT
     385  NULL AS '||a_id||',
     386  a.'||b_id||',           
     387  a.the_geom
     388 FROM '||schema_b||'.'||table_b||' a LEFT JOIN
     389      '||schema_z||'.'||intersection||' b ON
     390       a.'||b_id||'=b.'||b_id||'
     391 WHERE b.'||b_id||' is NULL';
     392
     393RAISE NOTICE 'finished ';
     394
     395 END;
     396$BODY$
     397LANGUAGE 'plpgsql' VOLATILE;
     398ALTER FUNCTION _pgunion_no_intersection(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar)
     399OWNER TO postgres;
     400
     401--Difference a
     402
     403CREATE OR REPLACE FUNCTION _pgunion_difference_a(
     404 schema_a varchar,
     405 table_a varchar,
     406 a_id varchar,
     407 schema_b varchar,
     408 table_b varchar,
     409 b_id varchar,
     410 schema_z varchar,
     411 diff_a varchar,
     412 diff_a_exceptions varchar)
     413RETURNS void AS
     414$BODY$
     415
     416/*
     417$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     418
     419pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     420_pgunion_difference_a: 4th part of pgunion, generates difference part of intersecting geometries of 1st input table, inserts geometries causing a topology exception into a separate table for later treatment
     421
     422schema_a:          database schema where 1st table is located
     423table_a:           name of 1st table
     424a_id:              id column name in 1st table
     425schema_b:          database schema where 2nd table is located
     426table_b:           name of 2nd table
     427b_id:              id column name in 2nd table
     428schema_z:          database schema where result table is located
     429diff_a:            table name for difference of 1st table
     430diff_a_exceptions: table name for geometries causing a topology exception
     431                   during difference
     432
     433Copyright: 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     434Version 0.1
     435contact: birgit dot laggner at vti dot bund dot de
     436
     437This is free software; you can redistribute and/or modify it under
     438the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     439*/
     440
     441DECLARE
     442i     integer;
     443sql_1 text;
     444
     445BEGIN
     446       
     447--4. Difference a:
     448
     449EXECUTE
     450'DROP TABLE IF EXISTS '||schema_z||'.'||diff_a||';';
     451
     452EXECUTE
     453'CREATE TABLE '||schema_z||'.'||diff_a||' ('||
     454 'gid serial PRIMARY KEY, '||
     455 ''||a_id||' integer, '||
     456 ''||b_id||' integer '||
     457 ');';
     458
     459EXECUTE
     460'SELECT AddGeometryColumn('''||schema_z||''', '''||diff_a||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);';
     461
     462EXECUTE
     463'ALTER TABLE '||schema_z||'.'||diff_a||' DROP CONSTRAINT enforce_geotype_the_geom;';
     464
     465
     466 EXECUTE
     467 'CREATE TABLE '||schema_z||'.tmp1 (gid serial, a_id integer, a_geom geometry, bu_geom geometry);';
     468
     469BEGIN
     470EXECUTE
     471'CREATE TABLE '||schema_z||'.'||diff_a_exceptions||' (gid serial, '||a_id||' integer, a_geom geometry, bu_geom geometry);';
     472EXCEPTION WHEN duplicate_table THEN
     473EXECUTE
     474'DROP TABLE '||schema_z||'.'||diff_a_exceptions||';';
     475EXECUTE
     476'CREATE TABLE '||schema_z||'.'||diff_a_exceptions||' (gid serial, '||a_id||' integer, a_geom geometry, bu_geom geometry);';
     477END;
     478
     479EXECUTE
     480'INSERT INTO '||schema_z||'.tmp1
     481  (a_id, a_geom, bu_geom)
     482 SELECT
     483  a_id,
     484  a_geom,
     485  CASE WHEN ST_Union(b_geom) IS NULL
     486    THEN ST_Collect(b_geom)
     487    ELSE ST_Union(b_geom)
     488    END
     489  FROM '||schema_z||'.intersection_inner_join
     490  GROUP BY a_id, a_geom;';
     491
     492RAISE NOTICE 'diff_a: Insert in tmp1 finished. Starting Difference. ';
     493
     494i:=0;
     495sql_1:='SELECT a_id FROM '||schema_z||'.intersection_inner_join GROUP BY a_id;';
     496FOR i IN EXECUTE sql_1 LOOP
     497
     498IF i IN (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000)
     499THEN
     500RAISE NOTICE 'diff_a: loop % ', i;
     501END IF;
     502       
     503 BEGIN
     504
     505  EXECUTE
     506  'INSERT INTO '||schema_z||'.'||diff_a||'
     507   ('||a_id||',
     508       the_geom)
     509   SELECT
     510    a_id,
     511    ST_Difference(a_geom, bu_geom)
     512   FROM '||schema_z||'.tmp1
     513   WHERE
     514   a_id='||i||' AND
     515   ST_IsEmpty(ST_Difference(a_geom, bu_geom))=''f'';';
     516
     517  EXCEPTION
     518   WHEN  internal_error
     519   THEN --insert geometries causing errors into separate table
     520  EXECUTE
     521  'INSERT INTO '||schema_z||'.'||diff_a_exceptions||'
     522   ('||a_id||', a_geom, bu_geom)
     523  SELECT
     524   a_id,
     525   a_geom,
     526   bu_geom
     527   FROM '||schema_z||'.tmp1
     528   WHERE a_id='||i||';';
     529
     530  END;
     531
     532  END LOOP;
     533
     534  EXECUTE
     535 'DROP TABLE '||schema_z||'.tmp1;';
     536
     537RAISE NOTICE 'diff_a finished. ';
     538
     539 END;
     540$BODY$
     541LANGUAGE 'plpgsql' VOLATILE;
     542ALTER FUNCTION _pgunion_difference_a(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar)
     543OWNER TO postgres;
     544
     545
     546--Difference b:
     547
     548CREATE OR REPLACE FUNCTION _pgunion_difference_b(
     549 schema_a varchar,
     550 table_a varchar,
     551 a_id varchar,
     552 schema_b varchar,
     553 table_b varchar,
     554 b_id varchar,
     555 schema_z varchar,
     556 diff_b varchar,
     557 diff_b_exceptions varchar)
     558RETURNS void AS
     559$BODY$
     560
     561/*
     562$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     563
     564pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     565_pgunion_difference_b: 5th part of pgunion, generates difference part of intersecting geometries of 2nd input table, inserts geometries causing a topology exception into a separate table for later treatment
     566
     567schema_a:          database schema where 1st table is located
     568table_a:           name of 1st table
     569a_id:              id column name in 1st table
     570schema_b:          database schema where 2nd table is located
     571table_b:           name of 2nd table
     572b_id:              id column name in 2nd table
     573schema_z:          database schema where result table is located
     574diff_b:            table name for difference of 2nd table
     575diff_b_exceptions: table name for geometries causing a topology exception
     576                   during difference
     577
     578Copyright: 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     579Version 0.1
     580contact: birgit dot laggner at vti dot bund dot de
     581
     582This is free software; you can redistribute and/or modify it under
     583the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     584*/
     585
     586DECLARE
     587i     integer;
     588sql_1 text;
     589
     590BEGIN
     591       
     592--5. Difference b:
     593
     594EXECUTE
     595'DROP TABLE IF EXISTS '||schema_z||'.'||diff_b||';';
     596
     597EXECUTE
     598'CREATE TABLE '||schema_z||'.'||diff_b||' ('||
     599 'gid serial PRIMARY KEY, '||
     600 ''||a_id||' integer, '||
     601 ''||b_id||' integer '||
     602 ');';
     603
     604EXECUTE
     605'SELECT AddGeometryColumn('''||schema_z||''', '''||diff_b||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);';
     606
     607EXECUTE
     608'ALTER TABLE '||schema_z||'.'||diff_b||' DROP CONSTRAINT enforce_geotype_the_geom;';
     609
     610
     611EXECUTE
     612 'CREATE TABLE '||schema_z||'.tmp1 (gid serial, b_id integer, b_geom geometry, au_geom geometry);';
     613
     614BEGIN
     615EXECUTE
     616'CREATE TABLE '||schema_z||'.'||diff_b_exceptions||' (gid serial, '||b_id||' integer, b_geom geometry, au_geom geometry);';
     617EXCEPTION WHEN duplicate_table THEN
     618EXECUTE
     619'DROP TABLE '||schema_z||'.'||diff_b_exceptions||';';
     620EXECUTE
     621'CREATE TABLE '||schema_z||'.'||diff_b_exceptions||' (gid serial, '||b_id||' integer, b_geom geometry, au_geom geometry);';
     622END;
     623
     624
     625EXECUTE
     626 'INSERT INTO '||schema_z||'.tmp1
     627  (b_id, b_geom, au_geom)
     628 SELECT
     629  b_id,
     630  b_geom,
     631  CASE WHEN ST_Union(a_geom) IS NULL
     632    THEN ST_Collect(a_geom)
     633    ELSE ST_Union(a_geom)
     634    END
     635 FROM '||schema_z||'.intersection_inner_join
     636 GROUP BY b_id, b_geom;';
     637
     638RAISE NOTICE 'diff_b: Insert in tmp1 finished. Starting Difference. ';
     639
     640i:=0;
     641sql_1:='SELECT b_id FROM '||schema_z||'.tmp1 GROUP BY b_id ORDER BY b_id;';
     642FOR i IN EXECUTE sql_1 LOOP
     643
     644IF i IN (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000)
     645THEN
     646RAISE NOTICE 'diff_b: loop % ', i;
     647END IF;
     648
     649BEGIN
     650
     651  EXECUTE
     652  'INSERT INTO '||schema_z||'.'||diff_b||'
     653   ('||b_id||',
     654       the_geom)
     655   SELECT
     656    b_id,
     657    ST_Difference(b_geom, au_geom)
     658   FROM '||schema_z||'.tmp1
     659   WHERE
     660   b_id='||i||' AND
     661   ST_IsEmpty(ST_Difference(b_geom, au_geom))=''f'';';
     662
     663  EXCEPTION
     664   WHEN  internal_error
     665   THEN --insert geometries causing errors into separate table
     666  EXECUTE
     667  'INSERT INTO '||schema_z||'.'||diff_b_exceptions||'
     668   ('||b_id||', b_geom, au_geom)
     669  SELECT
     670   b_id,
     671   b_geom,
     672   au_geom
     673   FROM '||schema_z||'.tmp1
     674   WHERE b_id='||i||';';
     675
     676  END;
     677
     678  END LOOP;
     679 
     680  EXECUTE
     681 'DROP TABLE '||schema_z||'.tmp1;';
     682
     683RAISE NOTICE 'diff_b finished. ';
     684
     685 END;
     686$BODY$
     687LANGUAGE 'plpgsql' VOLATILE;
     688ALTER FUNCTION _pgunion_difference_b(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar)
     689OWNER TO postgres;
     690
     691--Merge:
     692
     693CREATE OR REPLACE FUNCTION _pgunion_merge(
     694 a_id varchar,
     695 b_id varchar,
     696 schema_z varchar,
     697 intersection varchar,
     698 nointersect_a varchar,
     699 nointersect_b varchar,
     700 diff_a varchar,
     701 diff_b varchar,
     702 result varchar)
     703 RETURNS void AS
     704$BODY$
     705
     706/*
     707$Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $
     708
     709pgunion - spatial overlay of 2 tables, returns table with new geometries and assignments to original ids, as well as 2 tables with input geometries causing Topology Exceptions during difference function
     710_pgunion_merge: 6th part of pgunion, merges the results of each step into one table
     711
     712a_id:          id column name in 1st table
     713b_id:          id column name in 2nd table
     714schema_z:      database schema where result table is located
     715intersection:  table name for intersection table
     716nointersect_a: table name for no intersection of 1st table
     717nointersect_b: table name for no intersection of 2nd table
     718diff_a:        table name for difference of 1st table
     719diff_b:        table name for difference of 2nd table
     720result:        table name for result table
     721
     722Copyright: 2011 Johann Heinrich von Thünen-Institute (vTI) - Federal Research Institute for Rural Areas, Forestry and Fisheries, Institute of Rural Studies, Braunschweig, Germany (http://www.vti.bund.de)
     723Version 0.1
     724contact: birgit dot laggner at vti dot bund dot de
     725
     726This is free software; you can redistribute and/or modify it under
     727the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk.
     728*/
     729
     730BEGIN
     731
     732EXECUTE
     733'DROP TABLE IF EXISTS '||schema_z||'.'||result||';';
     734
     735EXECUTE
     736'CREATE TABLE '||schema_z||'.'||result||' (gid serial PRIMARY KEY, '||a_id||' integer, '||b_id||' integer);';
     737EXECUTE
     738'SELECT AddGeometryColumn('''||schema_z||''', '''||result||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_z||'.'||intersection||'),''POLYGON'',2);';
     739EXECUTE
     740'ALTER TABLE '||schema_z||'.'||result||' DROP CONSTRAINT enforce_geotype_the_geom;';
     741
     742EXECUTE
     743'INSERT INTO '||schema_z||'.'||result||'
     744 ('||a_id||','||b_id||', the_geom)
     745 SELECT
     746   a.'||a_id||',
     747   a.'||b_id||',
     748   (ST_Dump(a.the_geom)).geom
     749  FROM '||schema_z||'.'||intersection||' a;';
     750
     751EXECUTE
     752'INSERT INTO '||schema_z||'.'||result||'
     753 ('||a_id||','||b_id||', the_geom)
     754 SELECT
     755   b.'||a_id||',
     756   b.'||b_id||',
     757   (ST_Dump(b.the_geom)).geom
     758  FROM '||schema_z||'.'||nointersect_a||' b;';
     759
     760EXECUTE
     761'INSERT INTO '||schema_z||'.'||result||'
     762 ('||a_id||','||b_id||', the_geom)
     763 SELECT
     764   c.'||a_id||',
     765   c.'||b_id||',
     766   (ST_Dump(c.the_geom)).geom
     767  FROM '||schema_z||'.'||nointersect_b||' c;';
     768
     769EXECUTE
     770'INSERT INTO '||schema_z||'.'||result||'
     771 ('||a_id||','||b_id||', the_geom)
     772 SELECT
     773   d.'||a_id||',
     774   d.'||b_id||',
     775   (ST_Dump(d.the_geom)).geom
     776  FROM '||schema_z||'.'||diff_a||' d;';
     777
     778EXECUTE
     779'INSERT INTO '||schema_z||'.'||result||'
     780 ('||a_id||','||b_id||', the_geom)
     781 SELECT
     782   e.'||a_id||',
     783   e.'||b_id||',
     784   (ST_Dump(e.the_geom)).geom
     785  FROM '||schema_z||'.'||diff_b||' e;';
     786
     787--Remove intermediate tables:
     788
     789EXECUTE
     790'SELECT DropGeometryTable('''||schema_z||''','''||intersection||''');';
     791EXECUTE
     792'SELECT DropGeometryTable('''||schema_z||''','''||nointersect_a||''');';
     793EXECUTE
     794'SELECT DropGeometryTable('''||schema_z||''','''||nointersect_b||''');';
     795EXECUTE
     796'SELECT DropGeometryTable('''||schema_z||''','''||diff_a||''');';
     797EXECUTE
     798'SELECT DropGeometryTable('''||schema_z||''','''||diff_b||''');';
     799
     800
     801 END;
     802$BODY$
     803LANGUAGE 'plpgsql' VOLATILE;
     804ALTER FUNCTION _pgunion_merge(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar)
     805OWNER TO postgres;
     806
     807}}}