| 1 | |
| 2 | This is a shell script showing how Postgis topologies can be used to convert linestring geometries into topologically valid polygons. |
| 3 | |
| 4 | It uses geometry points within polygons to associate the created polygons with attribute data, and checks that all points have a matching polygon and the no points share a polygon. |
| 5 | |
| 6 | |
| 7 | ---- |
| 8 | |
| 9 | #! /bin/bash |
| 10 | |
| 11 | # Working example of Postgis topology use |
| 12 | # |
| 13 | # Brent Wood 9 April 2012 |
| 14 | # email: pcreso(at)pcreso.com |
| 15 | # With thanks to strk!! |
| 16 | |
| 17 | # Creates clean database & tests basic topology construction |
| 18 | # |
| 19 | # SUMMARY: |
| 20 | # Uses geometry linestrings |
| 21 | # Adds these to topology to create nodes/polygons |
| 22 | # Uses table of geometry points & attributes |
| 23 | # Extracts topo polygons to match points & attributes |
| 24 | # Checks for points with no polygons & for points sharing a polygon |
| 25 | |
| 26 | # create new empty database |
| 27 | dropdb topo |
| 28 | createdb topo |
| 29 | |
| 30 | # install full postgis with topolgy support |
| 31 | # modify paths as appropriate for other setups |
| 32 | psql -d topo -qf /usr/share/postgresql/contrib/postgis-2.0/postgis.sql |
| 33 | psql -d topo -qf /usr/share/postgresql/contrib/postgis-2.0/spatial_ref_sys.sql |
| 34 | psql -d topo -qf /usr/share/postgresql/contrib/postgis-2.0/legacy.sql |
| 35 | psql -d topo -qf /usr/share/postgresql/contrib/postgis-2.0/topology.sql |
| 36 | psql -d topo -qf /home/baw/Downloads/postgis-2.0.0rc2/doc/postgis_comments.sql |
| 37 | |
| 38 | # create table with overlapping linestring geometries |
| 39 | psql -d topo -qc "create table lines |
| 40 | ( id serial primary key, |
| 41 | name varchar(6), |
| 42 | geom geometry(LINESTRING,4326));" |
| 43 | |
| 44 | # add a set of linestrings to the table, like this |
| 45 | # |
| 46 | # | | | |
| 47 | # ------------------- |
| 48 | # | | | |
| 49 | # ------------------- |
| 50 | # | | | |
| 51 | |
| 52 | psql -d topo -c "insert into lines values |
| 53 | (default, |
| 54 | 'top', |
| 55 | ST_Setsrid(ST_Makeline(ST_Makepoint(175,-44),ST_Makepoint(179,-44)),4326) |
| 56 | );" |
| 57 | |
| 58 | psql -d topo -c "insert into lines values |
| 59 | (default, |
| 60 | 'bottom', |
| 61 | ST_Setsrid(ST_Makeline(ST_Makepoint(175,-45),ST_Makepoint(179,-45)),4326) |
| 62 | );" |
| 63 | |
| 64 | psql -d topo -c "insert into lines values |
| 65 | (default, |
| 66 | 'left', |
| 67 | ST_Setsrid(ST_Makeline(ST_Makepoint(176,-43),ST_Makepoint(176,-46)),4326) |
| 68 | );" |
| 69 | |
| 70 | psql -d topo -c "insert into lines values |
| 71 | (default, |
| 72 | 'middle', |
| 73 | ST_Setsrid(ST_Makeline(ST_Makepoint(177,-43),ST_Makepoint(177,-46)),4326) |
| 74 | );" |
| 75 | |
| 76 | psql -d topo -c "insert into lines values |
| 77 | (default, |
| 78 | 'right', |
| 79 | ST_Setsrid(ST_Makeline(ST_Makepoint(178,-43),ST_Makepoint(178,-46)),4326) |
| 80 | );" |
| 81 | |
| 82 | |
| 83 | # create new empty topology structure |
| 84 | psql -d topo -qc "select CreateTopology('topo1',4326,0);" |
| 85 | |
| 86 | # add all linestrings to topology in one operation as a collection |
| 87 | psql -d topo -c "select ST_CreateTopoGeo('topo1',ST_Collect(geom)) |
| 88 | from lines;" |
| 89 | |
| 90 | # creates topology like this (X = polygons - faces, + = nodes) |
| 91 | # + + + |
| 92 | # | | | |
| 93 | # +-+---+---+--+ |
| 94 | # | X | X | |
| 95 | # +-+---+---+--+ |
| 96 | # | | | |
| 97 | # + + + |
| 98 | |
| 99 | # validate topology - identify errors |
| 100 | psql -d topo -c "select * FROM ValidateTopology('topo1');" |
| 101 | |
| 102 | # list topology contents |
| 103 | psql -d topo -c "select TopologySummary('topo1');" |
| 104 | |
| 105 | # list polygons in ExtWKT format |
| 106 | psql -d topo -c "select ST_AsEWKT(ST_GetFaceGeometry('topo1', 1));" |
| 107 | psql -d topo -c "select ST_AsEWKT(ST_GetFaceGeometry('topo1', 2));" |
| 108 | |
| 109 | # create stratum polygon table for geometries as polygons |
| 110 | psql -d topo -c "create table poly |
| 111 | ( id serial primary key, |
| 112 | topo_id integer, |
| 113 | name varchar(10), |
| 114 | point geometry(point,4326), |
| 115 | geom geometry(polygon,4326));" |
| 116 | |
| 117 | # populate polygon table with non-polygon data - |
| 118 | # use points to geolocate the created strata, & associate the faces as geometries |
| 119 | psql -d topo -c "insert into poly (id, name, point) values |
| 120 | (default, |
| 121 | 'stra1', |
| 122 | ST_Setsrid(ST_Makepoint(176.5,-44.5),4326));" |
| 123 | psql -d topo -c "insert into poly (id, name, point) values |
| 124 | (default, |
| 125 | 'stra2', |
| 126 | ST_Setsrid(ST_Makepoint(177.5,-44.5),4326));" |
| 127 | |
| 128 | # insert a record with a point outside of any generated polygon to test error case |
| 129 | psql -d topo -c "insert into poly (id, name, point) values |
| 130 | (default, |
| 131 | 'stra3', |
| 132 | ST_Setsrid(ST_Makepoint(177,-43.9),4326));" |
| 133 | |
| 134 | # insert a record with a point inside the same stratum polygon to test error case |
| 135 | psql -d topo -c "insert into poly (id, name, point) values |
| 136 | (default, |
| 137 | 'stra4', |
| 138 | ST_Setsrid(ST_Makepoint(177.5,-44.4),4326));" |
| 139 | |
| 140 | # check for any points without generated polygons |
| 141 | psql -d topo -c "select 'ERROR: no enclosing polygon for point' as error, |
| 142 | name, |
| 143 | id, |
| 144 | ST_Astext(point) as point |
| 145 | from poly |
| 146 | where GetFaceByPoint('topo1',point,0) = 0;" |
| 147 | |
| 148 | # add polygons from topology matching the points |
| 149 | psql -d topo -c "update poly |
| 150 | set |
| 151 | geom=topology.ST_GetFaceGeometry('topo1',GetFaceByPoint('topo1',point,0)) |
| 152 | where GetFaceByPoint('topo1',point,0) != 0;" |
| 153 | |
| 154 | # check for any points with the same polygon |
| 155 | psql -d topo -c "select 'ERROR: points in same polygon' as error, |
| 156 | name, |
| 157 | id, |
| 158 | ST_Astext(point) as point |
| 159 | from poly where geom in |
| 160 | ( select geom from poly |
| 161 | group by geom |
| 162 | having count(geom) >1 );" |
| 163 | |
| 164 | |