| 1 | |
| 2 | == Spatial Overlay of 2 Polygon Tables - pgunion == |
| 3 | |
| 4 | This 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 | |
| 8 | pgunion consists of 6 separate functions which have to be called all in a determined order:[[BR]] |
| 9 | 1. _pgunion_start[[BR]] |
| 10 | 2. _pgunion_intersection[[BR]] |
| 11 | 3. _pgunion_no_intersection[[BR]] |
| 12 | 4. _pgunion_difference_a[[BR]] |
| 13 | 5. _pgunion_difference_b[[BR]] |
| 14 | 6. _pgunion_merge[[BR]] |
| 15 | |
| 16 | Final 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 | |
| 21 | Preconditions 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 | {{{ |
| 34 | CREATE TABLE pgunion_bsp_a (gid serial PRIMARY KEY, a_id integer, the_geom geometry); |
| 35 | INSERT 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 | |
| 41 | CREATE TABLE pgunion_bsp_b (gid serial PRIMARY KEY, b_id integer, the_geom geometry); |
| 42 | INSERT 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 | |
| 47 | SELECT _pgunion_start('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public'); |
| 48 | SELECT _pgunion_intersection('public','pgunion_bsp_a','a_id','public','pgunion_bsp_b','b_id','public','pgunion_bsp_intsec'); |
| 49 | SELECT _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'); |
| 50 | SELECT _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'); |
| 51 | SELECT _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'); |
| 52 | SELECT _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 | /* |
| 59 | pgunion consists of 6 separate functions which have to be called all in a determined order: |
| 60 | 1. _pgunion_start |
| 61 | 2. _pgunion_intersection |
| 62 | 3. _pgunion_no_intersection |
| 63 | 4. _pgunion_difference_a |
| 64 | 5. _pgunion_difference_b |
| 65 | 6. _pgunion_merge |
| 66 | |
| 67 | Preconditions 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 | |
| 74 | 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). |
| 75 | */ |
| 76 | |
| 77 | |
| 78 | CREATE 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) |
| 86 | RETURNS void AS |
| 87 | $BODY$ |
| 88 | |
| 89 | /* |
| 90 | $Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $ |
| 91 | |
| 92 | pgunion - 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 | |
| 95 | schema_a: database schema where 1st table is located |
| 96 | table_a: name of 1st table |
| 97 | a_id: id column name in 1st table |
| 98 | schema_b: database schema where 2nd table is located |
| 99 | table_b: name of 2nd table |
| 100 | b_id: id column name in 2nd table |
| 101 | schema_z: database schema where result table shall be located |
| 102 | |
| 103 | Copyright (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) |
| 104 | Version 0.1 |
| 105 | contact: birgit dot laggner at vti dot bund dot de |
| 106 | |
| 107 | This is free software; you can redistribute and/or modify it under |
| 108 | the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk. |
| 109 | */ |
| 110 | |
| 111 | BEGIN |
| 112 | |
| 113 | EXECUTE |
| 114 | 'DROP TABLE IF EXISTS '||schema_z||'.intersection_inner_join;'; |
| 115 | |
| 116 | EXECUTE |
| 117 | 'CREATE TABLE '||schema_z||'.intersection_inner_join (gid serial PRIMARY KEY, a_id integer, a_geom geometry, b_id integer, b_geom geometry);'; |
| 118 | EXECUTE |
| 119 | 'INSERT INTO '||schema_z||'.intersection_inner_join (a_id, a_geom, b_id, b_geom) |
| 120 | SELECT |
| 121 | a.'||a_id||', |
| 122 | a.the_geom, |
| 123 | b.'||b_id||', |
| 124 | b.the_geom |
| 125 | FROM |
| 126 | '||schema_a||'.'||table_a||' a |
| 127 | INNER JOIN |
| 128 | '||schema_b||'.'||table_b||' b |
| 129 | ON a.the_geom && b.the_geom |
| 130 | WHERE |
| 131 | ST_Intersects(a.the_geom, b.the_geom);'; |
| 132 | |
| 133 | EXECUTE |
| 134 | 'CREATE INDEX intersection_inner_join_btree_a_id ON '||schema_z||'.intersection_inner_join USING btree(a_id);'; |
| 135 | EXECUTE |
| 136 | 'CREATE INDEX intersection_inner_join_btree_b_id ON '||schema_z||'.intersection_inner_join USING btree(b_id);'; |
| 137 | EXECUTE |
| 138 | 'CREATE INDEX intersection_inner_join_gist_a ON '||schema_z||'.intersection_inner_join USING gist(a_geom);'; |
| 139 | EXECUTE |
| 140 | 'CREATE INDEX intersection_inner_join_gist_b ON '||schema_z||'.intersection_inner_join USING gist(b_geom);'; |
| 141 | |
| 142 | END; |
| 143 | $BODY$ |
| 144 | LANGUAGE 'plpgsql' VOLATILE; |
| 145 | ALTER FUNCTION _pgunion_start(varchar, varchar, varchar, varchar, varchar, varchar, varchar) OWNER TO postgres; |
| 146 | |
| 147 | |
| 148 | --Intersection: |
| 149 | |
| 150 | CREATE 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) |
| 159 | RETURNS void AS |
| 160 | $BODY$ |
| 161 | |
| 162 | /* |
| 163 | $Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $ |
| 164 | |
| 165 | pgunion - 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 | |
| 168 | schema_a: database schema where 1st table is located |
| 169 | table_a: name of 1st table |
| 170 | a_id: id column name in 1st table |
| 171 | schema_b: database schema where 2nd table is located |
| 172 | table_b: name of 2nd table |
| 173 | b_id: id column name in 2nd table |
| 174 | schema_z: database schema where result table is located |
| 175 | intersection: table name for intersection table |
| 176 | |
| 177 | Copyright: 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) |
| 178 | Version 0.1 |
| 179 | contact: birgit dot laggner at vti dot bund dot de |
| 180 | |
| 181 | This is free software; you can redistribute and/or modify it under |
| 182 | the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk. |
| 183 | */ |
| 184 | |
| 185 | DECLARE |
| 186 | |
| 187 | i integer; |
| 188 | sql_1 text; |
| 189 | |
| 190 | BEGIN |
| 191 | |
| 192 | EXECUTE |
| 193 | 'DROP TABLE IF EXISTS '||schema_z||'.'||intersection||';'; |
| 194 | |
| 195 | EXECUTE |
| 196 | 'CREATE TABLE '||schema_z||'.'||intersection||' ('|| |
| 197 | 'gid serial PRIMARY KEY, '|| |
| 198 | ''||a_id||' integer, '|| |
| 199 | ''||b_id||' integer '|| |
| 200 | ');'; |
| 201 | |
| 202 | EXECUTE |
| 203 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||intersection||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);'; |
| 204 | |
| 205 | EXECUTE |
| 206 | 'ALTER TABLE '||schema_z||'.'||intersection||' DROP CONSTRAINT enforce_geotype_the_geom;'; |
| 207 | |
| 208 | |
| 209 | RAISE NOTICE 'Starting Intersection. '; |
| 210 | |
| 211 | i:=0; |
| 212 | |
| 213 | sql_1:='SELECT gid FROM '||schema_z||'.intersection_inner_join ORDER BY gid;'; |
| 214 | |
| 215 | FOR i IN EXECUTE sql_1 LOOP |
| 216 | |
| 217 | BEGIN |
| 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 | |
| 229 | EXCEPTION |
| 230 | WHEN internal_error |
| 231 | THEN |
| 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 | |
| 247 | END; |
| 248 | END LOOP; |
| 249 | |
| 250 | EXECUTE |
| 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 | |
| 260 | EXECUTE |
| 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 | |
| 272 | RAISE NOTICE 'Intersection finished. '; |
| 273 | |
| 274 | |
| 275 | END; |
| 276 | $BODY$ |
| 277 | LANGUAGE 'plpgsql' VOLATILE; |
| 278 | ALTER FUNCTION _pgunion_intersection(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar) |
| 279 | OWNER TO postgres; |
| 280 | |
| 281 | |
| 282 | --No Intersection |
| 283 | |
| 284 | CREATE 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) |
| 295 | RETURNS void AS |
| 296 | $BODY$ |
| 297 | |
| 298 | /* |
| 299 | $Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $ |
| 300 | |
| 301 | pgunion - 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 | |
| 304 | schema_a: database schema where 1st table is located |
| 305 | table_a: name of 1st table |
| 306 | a_id: id column name in 1st table |
| 307 | schema_b: database schema where 2nd table is located |
| 308 | table_b: name of 2nd table |
| 309 | b_id: id column name in 2nd table |
| 310 | schema_z: database schema where result table is located |
| 311 | intersection: table name for intersection table |
| 312 | nointersect_a: table name for no intersection of 1st table |
| 313 | nointersect_b: table name for no intersection of 2nd table |
| 314 | |
| 315 | Copyright: 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) |
| 316 | Version 0.1 |
| 317 | contact: birgit dot laggner at vti dot bund dot de |
| 318 | |
| 319 | This is free software; you can redistribute and/or modify it under |
| 320 | the 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 | |
| 327 | EXECUTE |
| 328 | 'DROP TABLE IF EXISTS '||schema_z||'.'||nointersect_a||';'; |
| 329 | EXECUTE |
| 330 | 'DROP TABLE IF EXISTS '||schema_z||'.'||nointersect_b||';'; |
| 331 | |
| 332 | EXECUTE |
| 333 | 'CREATE TABLE '||schema_z||'.'||nointersect_a||' ('|| |
| 334 | 'gid serial PRIMARY KEY, '|| |
| 335 | ''||a_id||' integer, '|| |
| 336 | ''||b_id||' integer '|| |
| 337 | ');'; |
| 338 | |
| 339 | EXECUTE |
| 340 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||nointersect_a||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);'; |
| 341 | |
| 342 | EXECUTE |
| 343 | 'ALTER TABLE '||schema_z||'.'||nointersect_a||' DROP CONSTRAINT enforce_geotype_the_geom;'; |
| 344 | |
| 345 | EXECUTE |
| 346 | 'CREATE TABLE '||schema_z||'.'||nointersect_b||' ('|| |
| 347 | 'gid serial PRIMARY KEY, '|| |
| 348 | ''||a_id||' integer, '|| |
| 349 | ''||b_id||' integer '|| |
| 350 | ');'; |
| 351 | |
| 352 | EXECUTE |
| 353 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||nointersect_b||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);'; |
| 354 | |
| 355 | EXECUTE |
| 356 | 'ALTER TABLE '||schema_z||'.'||nointersect_b||' DROP CONSTRAINT enforce_geotype_the_geom;'; |
| 357 | |
| 358 | |
| 359 | RAISE NOTICE 'Starting No Intersection for 1st table. '; |
| 360 | |
| 361 | EXECUTE |
| 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 | |
| 374 | RAISE NOTICE 'finished '; |
| 375 | |
| 376 | --No Intersection b: |
| 377 | |
| 378 | RAISE NOTICE 'Starting No Intersection for 2nd table. '; |
| 379 | |
| 380 | EXECUTE |
| 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 | |
| 393 | RAISE NOTICE 'finished '; |
| 394 | |
| 395 | END; |
| 396 | $BODY$ |
| 397 | LANGUAGE 'plpgsql' VOLATILE; |
| 398 | ALTER FUNCTION _pgunion_no_intersection(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar) |
| 399 | OWNER TO postgres; |
| 400 | |
| 401 | --Difference a |
| 402 | |
| 403 | CREATE 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) |
| 413 | RETURNS void AS |
| 414 | $BODY$ |
| 415 | |
| 416 | /* |
| 417 | $Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $ |
| 418 | |
| 419 | pgunion - 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 | |
| 422 | schema_a: database schema where 1st table is located |
| 423 | table_a: name of 1st table |
| 424 | a_id: id column name in 1st table |
| 425 | schema_b: database schema where 2nd table is located |
| 426 | table_b: name of 2nd table |
| 427 | b_id: id column name in 2nd table |
| 428 | schema_z: database schema where result table is located |
| 429 | diff_a: table name for difference of 1st table |
| 430 | diff_a_exceptions: table name for geometries causing a topology exception |
| 431 | during difference |
| 432 | |
| 433 | Copyright: 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) |
| 434 | Version 0.1 |
| 435 | contact: birgit dot laggner at vti dot bund dot de |
| 436 | |
| 437 | This is free software; you can redistribute and/or modify it under |
| 438 | the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk. |
| 439 | */ |
| 440 | |
| 441 | DECLARE |
| 442 | i integer; |
| 443 | sql_1 text; |
| 444 | |
| 445 | BEGIN |
| 446 | |
| 447 | --4. Difference a: |
| 448 | |
| 449 | EXECUTE |
| 450 | 'DROP TABLE IF EXISTS '||schema_z||'.'||diff_a||';'; |
| 451 | |
| 452 | EXECUTE |
| 453 | 'CREATE TABLE '||schema_z||'.'||diff_a||' ('|| |
| 454 | 'gid serial PRIMARY KEY, '|| |
| 455 | ''||a_id||' integer, '|| |
| 456 | ''||b_id||' integer '|| |
| 457 | ');'; |
| 458 | |
| 459 | EXECUTE |
| 460 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||diff_a||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);'; |
| 461 | |
| 462 | EXECUTE |
| 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 | |
| 469 | BEGIN |
| 470 | EXECUTE |
| 471 | 'CREATE TABLE '||schema_z||'.'||diff_a_exceptions||' (gid serial, '||a_id||' integer, a_geom geometry, bu_geom geometry);'; |
| 472 | EXCEPTION WHEN duplicate_table THEN |
| 473 | EXECUTE |
| 474 | 'DROP TABLE '||schema_z||'.'||diff_a_exceptions||';'; |
| 475 | EXECUTE |
| 476 | 'CREATE TABLE '||schema_z||'.'||diff_a_exceptions||' (gid serial, '||a_id||' integer, a_geom geometry, bu_geom geometry);'; |
| 477 | END; |
| 478 | |
| 479 | EXECUTE |
| 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 | |
| 492 | RAISE NOTICE 'diff_a: Insert in tmp1 finished. Starting Difference. '; |
| 493 | |
| 494 | i:=0; |
| 495 | sql_1:='SELECT a_id FROM '||schema_z||'.intersection_inner_join GROUP BY a_id;'; |
| 496 | FOR i IN EXECUTE sql_1 LOOP |
| 497 | |
| 498 | IF i IN (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000) |
| 499 | THEN |
| 500 | RAISE NOTICE 'diff_a: loop % ', i; |
| 501 | END 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 | |
| 537 | RAISE NOTICE 'diff_a finished. '; |
| 538 | |
| 539 | END; |
| 540 | $BODY$ |
| 541 | LANGUAGE 'plpgsql' VOLATILE; |
| 542 | ALTER FUNCTION _pgunion_difference_a(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar) |
| 543 | OWNER TO postgres; |
| 544 | |
| 545 | |
| 546 | --Difference b: |
| 547 | |
| 548 | CREATE 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) |
| 558 | RETURNS void AS |
| 559 | $BODY$ |
| 560 | |
| 561 | /* |
| 562 | $Id: pgunion_wiki.sql 2011-03-10 09:45Z Birgit Laggner $ |
| 563 | |
| 564 | pgunion - 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 | |
| 567 | schema_a: database schema where 1st table is located |
| 568 | table_a: name of 1st table |
| 569 | a_id: id column name in 1st table |
| 570 | schema_b: database schema where 2nd table is located |
| 571 | table_b: name of 2nd table |
| 572 | b_id: id column name in 2nd table |
| 573 | schema_z: database schema where result table is located |
| 574 | diff_b: table name for difference of 2nd table |
| 575 | diff_b_exceptions: table name for geometries causing a topology exception |
| 576 | during difference |
| 577 | |
| 578 | Copyright: 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) |
| 579 | Version 0.1 |
| 580 | contact: birgit dot laggner at vti dot bund dot de |
| 581 | |
| 582 | This is free software; you can redistribute and/or modify it under |
| 583 | the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk. |
| 584 | */ |
| 585 | |
| 586 | DECLARE |
| 587 | i integer; |
| 588 | sql_1 text; |
| 589 | |
| 590 | BEGIN |
| 591 | |
| 592 | --5. Difference b: |
| 593 | |
| 594 | EXECUTE |
| 595 | 'DROP TABLE IF EXISTS '||schema_z||'.'||diff_b||';'; |
| 596 | |
| 597 | EXECUTE |
| 598 | 'CREATE TABLE '||schema_z||'.'||diff_b||' ('|| |
| 599 | 'gid serial PRIMARY KEY, '|| |
| 600 | ''||a_id||' integer, '|| |
| 601 | ''||b_id||' integer '|| |
| 602 | ');'; |
| 603 | |
| 604 | EXECUTE |
| 605 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||diff_b||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_a||'.'||table_a||'),''POLYGON'',2);'; |
| 606 | |
| 607 | EXECUTE |
| 608 | 'ALTER TABLE '||schema_z||'.'||diff_b||' DROP CONSTRAINT enforce_geotype_the_geom;'; |
| 609 | |
| 610 | |
| 611 | EXECUTE |
| 612 | 'CREATE TABLE '||schema_z||'.tmp1 (gid serial, b_id integer, b_geom geometry, au_geom geometry);'; |
| 613 | |
| 614 | BEGIN |
| 615 | EXECUTE |
| 616 | 'CREATE TABLE '||schema_z||'.'||diff_b_exceptions||' (gid serial, '||b_id||' integer, b_geom geometry, au_geom geometry);'; |
| 617 | EXCEPTION WHEN duplicate_table THEN |
| 618 | EXECUTE |
| 619 | 'DROP TABLE '||schema_z||'.'||diff_b_exceptions||';'; |
| 620 | EXECUTE |
| 621 | 'CREATE TABLE '||schema_z||'.'||diff_b_exceptions||' (gid serial, '||b_id||' integer, b_geom geometry, au_geom geometry);'; |
| 622 | END; |
| 623 | |
| 624 | |
| 625 | EXECUTE |
| 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 | |
| 638 | RAISE NOTICE 'diff_b: Insert in tmp1 finished. Starting Difference. '; |
| 639 | |
| 640 | i:=0; |
| 641 | sql_1:='SELECT b_id FROM '||schema_z||'.tmp1 GROUP BY b_id ORDER BY b_id;'; |
| 642 | FOR i IN EXECUTE sql_1 LOOP |
| 643 | |
| 644 | IF i IN (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000) |
| 645 | THEN |
| 646 | RAISE NOTICE 'diff_b: loop % ', i; |
| 647 | END IF; |
| 648 | |
| 649 | BEGIN |
| 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 | |
| 683 | RAISE NOTICE 'diff_b finished. '; |
| 684 | |
| 685 | END; |
| 686 | $BODY$ |
| 687 | LANGUAGE 'plpgsql' VOLATILE; |
| 688 | ALTER FUNCTION _pgunion_difference_b(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar) |
| 689 | OWNER TO postgres; |
| 690 | |
| 691 | --Merge: |
| 692 | |
| 693 | CREATE 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 | |
| 709 | pgunion - 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 | |
| 712 | a_id: id column name in 1st table |
| 713 | b_id: id column name in 2nd table |
| 714 | schema_z: database schema where result table is located |
| 715 | intersection: table name for intersection table |
| 716 | nointersect_a: table name for no intersection of 1st table |
| 717 | nointersect_b: table name for no intersection of 2nd table |
| 718 | diff_a: table name for difference of 1st table |
| 719 | diff_b: table name for difference of 2nd table |
| 720 | result: table name for result table |
| 721 | |
| 722 | Copyright: 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) |
| 723 | Version 0.1 |
| 724 | contact: birgit dot laggner at vti dot bund dot de |
| 725 | |
| 726 | This is free software; you can redistribute and/or modify it under |
| 727 | the terms of the GNU General Public Licence. This software is without any warrenty and you use it at your own risk. |
| 728 | */ |
| 729 | |
| 730 | BEGIN |
| 731 | |
| 732 | EXECUTE |
| 733 | 'DROP TABLE IF EXISTS '||schema_z||'.'||result||';'; |
| 734 | |
| 735 | EXECUTE |
| 736 | 'CREATE TABLE '||schema_z||'.'||result||' (gid serial PRIMARY KEY, '||a_id||' integer, '||b_id||' integer);'; |
| 737 | EXECUTE |
| 738 | 'SELECT AddGeometryColumn('''||schema_z||''', '''||result||''',''the_geom'',(SELECT DISTINCT ST_SRID(the_geom) FROM '||schema_z||'.'||intersection||'),''POLYGON'',2);'; |
| 739 | EXECUTE |
| 740 | 'ALTER TABLE '||schema_z||'.'||result||' DROP CONSTRAINT enforce_geotype_the_geom;'; |
| 741 | |
| 742 | EXECUTE |
| 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 | |
| 751 | EXECUTE |
| 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 | |
| 760 | EXECUTE |
| 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 | |
| 769 | EXECUTE |
| 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 | |
| 778 | EXECUTE |
| 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 | |
| 789 | EXECUTE |
| 790 | 'SELECT DropGeometryTable('''||schema_z||''','''||intersection||''');'; |
| 791 | EXECUTE |
| 792 | 'SELECT DropGeometryTable('''||schema_z||''','''||nointersect_a||''');'; |
| 793 | EXECUTE |
| 794 | 'SELECT DropGeometryTable('''||schema_z||''','''||nointersect_b||''');'; |
| 795 | EXECUTE |
| 796 | 'SELECT DropGeometryTable('''||schema_z||''','''||diff_a||''');'; |
| 797 | EXECUTE |
| 798 | 'SELECT DropGeometryTable('''||schema_z||''','''||diff_b||''');'; |
| 799 | |
| 800 | |
| 801 | END; |
| 802 | $BODY$ |
| 803 | LANGUAGE 'plpgsql' VOLATILE; |
| 804 | ALTER FUNCTION _pgunion_merge(varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar, varchar) |
| 805 | OWNER TO postgres; |
| 806 | |
| 807 | }}} |