Changes between Version 38 and Version 39 of import layers postgis


Ignore:
Timestamp:
Aug 21, 2018 12:05:26 PM (7 years ago)
Author:
maria
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • import layers postgis

    v38 v39  
    414414== Trial with Portugal layers == 
    415415 
    416 {{{#!sql 
    417 -- In Command prompt(cmd) we need to create a new schema and import the shapefiles to Postgres 
     416In Command prompt(cmd) we need to create a new schema and import the shapefiles to Postgres 
     417 
     418{{{#!sql 
    418419-- Create a new schema for Portugal 
    419420psql -U postgres -c "create schema portugal" eda2.0 
     
    424425psql -U postgres -f AtAgua_Bacias_bacias_snirh_PC.sql eda2.0 
    425426 
    426 -- Bacias dos troços de linha de água GeoCodificadas (basinorder corresponds to idlocalid from rede hordrografica) 
    427 shp2pgsql -s 3763 -I vw_baccod_25k_ptcont.shp portugal.vw_baccod_25k_ptcont > vw_baccod_25k_ptcont.sql 
    428 psql -U postgres -f vw_baccod_25k_ptcont.sql eda2.0 
    429  
    430427-- Rede hidrografica GeoCodificada 
    431428shp2pgsql -s 3763 -W LATIN1 -I netElementL.shp portugal.netElementL > netElementL.sql 
    432429psql -U postgres -f netElementL.sql eda2.0 
    433  
    434  
    435 -- Creating a table corresponding to MINHO 
    436 set search_path to portugal ; 
    437  
    438 -- Table of basins 
    439 drop table if exists minho_cuenca; 
    440 create table minho_cuenca as select * from vw_baccod_25k_ptcont where basinorder like '181%'; 
    441  
    442 CREATE INDEX minho_cuenca_geom_idx 
    443   ON minho_cuenca 
    444   USING gist 
    445   (geom); 
    446  
    447 -- Table of rivers 
    448 drop table if exists minho_rio; 
    449 create table minho_rio as select * from netElementL where id_localid like '181%'; 
    450  
    451 CREATE INDEX minho_rio_geom_idx 
    452   ON minho_rio 
    453   USING gist 
    454   (geom); 
    455  
    456 -- Configure the table of rivers to use pgrouting: creating source and target 
    457 ALTER TABLE minho_rio DROP COLUMN source; 
    458 ALTER TABLE minho_rio DROP COLUMN target; 
    459 ALTER TABLE minho_rio ADD COLUMN source integer; 
    460 ALTER TABLE minho_rio ADD COLUMN target integer; 
    461 CREATE INDEX minho_rio_source_idx ON minho_rio (source); 
    462 CREATE INDEX minho_rio_target_idx ON minho_rio (target); 
    463  
    464 --------------------------------------------------------------------- 
    465 -- Using pgrouting: createTopology also creates vertices_pgr 
    466 ------------------------------------------------------------------ 
    467 set search_path to portugal, public; 
    468 SELECT pgr_createTopology('minho_rio', 0.0001, 'geom', 'gid'); 
    469  
    470 SELECT  * from minho_rio limit 10 
    471  
    472 }}} 
     430}}} 
     431 
     432Adding a column identifying basin flowing to the sea to rivers 
     433 
     434{{{#!sql 
     435comment ON TABLE portugal.atagua_bacias_bacias_snirh_pc IS 'River basins flowing to the sea'; 
     436}}} 
     437 
     438Trial to join river layer with basin that flows into the sea (this layer "AtAgua_Bacias_bacias_snirh_PC" has the name of basin: "nome") 
     439 
     440{{{#!sql 
     441SELECT rivers.gid, nome FROM portugal.atagua_bacias_bacias_snirh_pc bs -- bassins sea  
     442 
     443JOIN portugal.rivers ON st_intersects(bs.geom, rivers.geom); 
     444 
     445SELECT * FROM portugal.rivers LIMIT 10; -- Just a view of the rivers 
     446}}} 
     447 
     448Adding the basin name in the river table: update the table rivers to fill in the column nome using the subquery 
     449 
     450{{{#!sql 
     451ALTER TABLE portugal.rivers ADD COLUMN nome CHARACTER VARYING(50); 
     452UPDATE portugal.rivers SET nome = sub.nome 
     453        FROM( 
     454                SELECT 
     455                        rivers.gid, 
     456                        bs.nome 
     457                FROM 
     458                        portugal.atagua_bacias_bacias_snirh_pc bs -- bassins sea  
     459                JOIN portugal.rivers ON 
     460                        st_intersects( 
     461                                bs.geom, 
     462                                rivers.geom 
     463                        ) 
     464        ) sub 
     465WHERE 
     466        rivers.gid = sub.gid;-- 75386 
     467 
     468SELECT * FROM portugal.rivers WHERE nome IS NOT NULL; 
     469}}} 
     470 
     471Using pgrouting: createTopology also creates vertices_pgr (target is the nearest point to the sea) 
     472 
     473{{{#!sql 
     474SET search_path TO portugal, public; 
     475ALTER TABLE portugal.rivers DROP COLUMN IF EXISTS SOURCE; 
     476ALTER TABLE portugal.rivers DROP COLUMN IF EXISTS target; 
     477ALTER TABLE portugal.rivers ADD COLUMN SOURCE INTEGER; 
     478ALTER TABLE portugal.rivers ADD COLUMN target INTEGER; 
     479CREATE INDEX rivers_source_idx ON portugal.rivers(SOURCE); 
     480CREATE INDEX rivers_target_idx ON portugal.rivers(target); 
     481 
     482SELECT pgr_createTopology('rivers', 0.0001, 'geom', 'gid'); 
     483 
     484-- notes: fails with id_localid if character varying so must be gid 
     485}}} 
     486 
     487Create q view of coastal waters: first it is projected to the portugese projection 3763, and second we just need one big water mass for st_distance to the sea hence the UNION 
     488 
     489{{{#!sql 
     490DROP VIEW european_wise2008.coastal_waters_3763; 
     491 
     492CREATE OR replace VIEW european_wise2008.coastal_waters_3763 AS SELECT 
     493                        st_union( 
     494                                st_transform( 
     495                                        the_geom, 
     496                                        3763 
     497                                ) 
     498                        ) AS geom 
     499                FROM 
     500                        european_wise2008.costal_waters 
     501                WHERE 
     502                        cty_id = 'PT'; 
     503}}} 
     504 
     505Creating a table of downstream points 
     506 
     507{{{#!sql 
     508DROP TABLE IF EXISTS portugal.downstream_points; 
     509 
     510CREATE TABLE portugal.downstream_points  
     511        AS (SELECT target, nome, TRUE AS at_sea, v.the_geom FROM(SELECT * FROM rivers) r 
     512                JOIN portugal.rivers_vertices_pgr v ON v.id = r.target  
     513                WHERE nextdownid = 0);--466 
     514                         
     515ALTER TABLE portugal.downstream_points ADD CONSTRAINT c_pk_target PRIMARY KEY(target); 
     516 
     517ALTER TABLE portugal.downstream_points ADD COLUMN distance NUMERIC; 
     518 
     519-- ALTER TABLE portugal.downstream_points ADD INDEX  
     520-- DROP INDEX portugal.downsteam_points_thegeom_idx; 
     521 
     522CREATE INDEX downstream_points_thegeom_idx ON portugal.downstream_points USING gist(the_geom); 
     523}}} 
     524 
     525Some of the basins are endoreic (red points), not flowing to the sea 
     526 
     527[[Image(source:eda/data/Docs/trac/sudoang/downstream_points.png, 200px)]][[BR]] 
     528 
     529So, we calculate distance to the sea and only choose distance <500m as AT_SEA = TRUE 
     530 
     531{{{#!sql 
     532DROP TABLE IF EXISTS portugal.coastalwater_union; 
     533 
     534CREATE TABLE portugal.coastalwater_union AS SELECT st_union(geom) FROM european_wise2008.coastal_waters_3763; 
     535 
     536UPDATE portugal.downstream_points 
     537                        SET    distance = st_distance(cw.geom, the_geom) 
     538                        FROM   european_wise2008.coastal_waters_3763 cw; 
     539 
     540UPDATE  portugal.downstream_points SET at_sea = FALSE WHERE distance > 500; 
     541}}} 
     542 
     543We start with "Lis e Ribeiras Costeiras" as an example, where there are 26 downstream segments 
     544 
     545{{{#!sql 
     546SELECT * FROM downstream_points WHERE nome = 'Lis e Ribeiras Costeiras' --26 
     547}}} 
     548 
     549||target||nome||at_sea||the_geom||distance|| 
     550||42602||Lis e Ribeiras Costeiras||f||0101000020B30E00008007CE19EFD0E8C000A8A44E10CDBAC0||29907.6770989189|| 
     551||39176||Lis e Ribeiras Costeiras||t||0101000020B30E0000C0DCB5845C29F0C000470378AB0CE340||0|| 
     552||39812||Lis e Ribeiras Costeiras||t||0101000020B30E000000FBCBEE7D90F0C0005A643BFFC8E040||15.2036257782544|| 
     553||39365||Lis e Ribeiras Costeiras||t||0101000020B30E0000C0627FD93C3FF0C0006ADE71AC8FE240||2.44673969528912|| 
     554||39433||Lis e Ribeiras Costeiras||t||0101000020B30E00004050FC18DD4EF0C000E25817ED31E240||0|| 
     555||39649||Lis e Ribeiras Costeiras||t||0101000020B30E0000802BF6975D74F0C00063EE5AEE69E140||0|| 
     556||39815||Lis e Ribeiras Costeiras||t||0101000020B30E000040A835CD8D85F0C000D3BCE30E09E140||0|| 
     557||39601||Lis e Ribeiras Costeiras||t||0101000020B30E0000C08BDB68BD64F0C000F697DD0DB8E140||0|| 
     558||40528||Lis e Ribeiras Costeiras||t||0101000020B30E000040431CEB6EFFF0C0009ECDAA63EBDC40||9.27728846536787|| 
     559||40005||Lis e Ribeiras Costeiras||t||0101000020B30E0000803255309EACF0C00022FDF6CF3AE040||0|| 
     560||40154||Lis e Ribeiras Costeiras||t||0101000020B30E0000C0F5285CAEBAF0C00010C7BA60C0DF40||10.7529801188864|| 
     561||40328||Lis e Ribeiras Costeiras||t||0101000020B30E00008009F9A0AED3F0C000941804E2A0DE40||0|| 
     562||40371||Lis e Ribeiras Costeiras||t||0101000020B30E00000068226CEEC0F0C0004CC807A17BDF40||2.92664241883266|| 
     563||40616||Lis e Ribeiras Costeiras||t||0101000020B30E000040D8F0F41E04F1C000D2DEE043B6DC40||8.5398098285145|| 
     564||73504||Lis e Ribeiras Costeiras||t||0101000020B30E000000BF0E9CF396EEC0001F85EB7D36E840||0.715212896922981|| 
     565||73603||Lis e Ribeiras Costeiras||t||0101000020B30E00000073D71234B6EEC000A3923A6FC4E740||16.3837915282055|| 
     566||73690||Lis e Ribeiras Costeiras||t||0101000020B30E000080C2F52874BCEEC0006C787A8FAEE740||19.2806257837849|| 
     567||73814||Lis e Ribeiras Costeiras||t||0101000020B30E0000809DEFA7D4DEEEC000EFC9C3F03AE740||66.9101252528966|| 
     568||73894||Lis e Ribeiras Costeiras||t||0101000020B30E000000DFE00B15FEEEC0005F07CE31DDE640||25.1780872038218|| 
     569||74140||Lis e Ribeiras Costeiras||t||0101000020B30E000080499D807684EFC000151DC9056EE540||0|| 
     570||74397||Lis e Ribeiras Costeiras||t||0101000020B30E000000508D979687EFC0006DE7FB455BE540||16.3373603370103|| 
     571||74423||Lis e Ribeiras Costeiras||t||0101000020B30E00008087855AD7BFEFC000CCEEC927A9E440||0|| 
     572||74703||Lis e Ribeiras Costeiras||t||0101000020B30E0000C0EEC9C3FEE7F0C0003AB4C8E2D8DD40||4.00492099466328|| 
     573||74866||Lis e Ribeiras Costeiras||t||0101000020B30E0000C0D32B658F34F1C0002C6519E66DDA40||4.5315444659325|| 
     574||75021||Lis e Ribeiras Costeiras||t||0101000020B30E0000C04B3789BF45F1C00016FBCBA6B8D940||8.50403554270985|| 
     575||75270||Lis e Ribeiras Costeiras||t||0101000020B30E000000E78C289886F1C00070F085892BD740||8.23462515206324|| 
     576 
     577The target 75270 is the largest flow of this basin 
     578Be careful! The target and source attributes are calculating randomly (so this example can be a different number for you)  
     579 
     580[[Image(source:eda/data/Docs/trac/sudoang/lis_ribeiras_example.png, 300px)]][[BR]] 
     581 
     582We select everything in basin 75270 
     583The following function (recusrsive) selects everyting in the basin by a recursive query, using source and target created by the pg_routing algorythm (it is much quicker than a spatial recursive) 
     584 
     585{{{#!sql 
     586DROP function if exists portugal.upstream_segments(INTEGER); 
     587 
     588CREATE FUNCTION portugal.upstream_segments(INTEGER) 
     589 
     590RETURNS TABLE(source integer, target integer) AS 
     591$$ 
     592BEGIN 
     593RETURN QUERY 
     594        WITH RECURSIVE parcours AS( 
     595                SELECT 
     596                        r0.source, 
     597                        r0.target 
     598                FROM 
     599                        portugal.rivers r0 
     600                WHERE 
     601                        r0.target = $1 
     602               UNION SELECT 
     603                       r1.source, 
     604                       r1.target 
     605                FROM 
     606                        parcours 
     607                JOIN portugal.rivers r1 ON  parcours.source = r1.target) 
     608          SELECT * FROM parcours; 
     609END 
     610$$ 
     611  LANGUAGE plpgsql VOLATILE; 
     612 
     613-- select * from portugal.upstream_segments(75270); --1s and 733rows of source and target 
     614}}} 
     615 
     616Creating indexes to do the routing function and join the result with the river table to get the id of the river segment 
     617 
     618{{{#!sql 
     619ALTER TABLE portugal.rivers ADD COLUMN chemin ltree; 
     620CREATE INDEX chemin_gist_rivers_idx ON portugal.rivers USING GIST(chemin); 
     621CREATE INDEX chemin_rivers_idx ON portugal.rivers USING btree(chemin); 
     622 
     623DROP function if exists portugal.get_path(integer,integer); 
     624CREATE OR REPLACE FUNCTION portugal.get_path(_from integer, _to integer) 
     625RETURNS SETOF ltree AS 
     626$$ 
     627BEGIN 
     628RETURN QUERY  
     629SELECT text2ltree(string_agg(gid::text, '.')) AS gid_list   
     630FROM (SELECT gid FROM pgr_dijkstra('SELECT gid as id, source, target, st_length(geom) as cost FROM portugal.rivers', _from, _to, FALSE) pt 
     631JOIN portugal.rivers r ON pt.edge = r.gid order by seq) sub; 
     632 
     633END 
     634$$ 
     635LANGUAGE plpgsql VOLATILE; 
     636}}} 
     637 
     638Different options to calculate topology 
     639 
     640{{{#!sql 
     641select portugal.get_path(75270, source) from portugal.upstream_segments(75270); --5:09 
     642 
     643select portugal.get_path(57647, source) from portugal.rivers where nome = 'Lis e Ribeiras Costeiras'; --5:59 
     644 
     645UPDATE portugal.rivers set chemin=get_path(75270,u.source) from portugal.upstream_segments(75270) u 
     646where rivers.source = u.source; -- 5:13 
     647}}} 
     648 
     649Pass a vector and insert the values: 
     650 -- this function writes the path for every basin in an aera (set by the name of the hydrographic region, nome) [[BR]] 
     651 -- for this, we need to pass the function  get_path(target, source) where the target is the node at the estuary [[BR]] 
     652 -- and the source is all the nodes from the basin connected to that basin [[BR]] 
     653 -- To achieve the connection to all elements in the basin we used the recursive function upstream_segments [[BR]] 
     654Details : 
     655 -- this function uses a cursor, we could have used a for loop for the cursor [[BR]] 
     656 -- here following an example http://www.postgresqltutorial.com/plpgsql-cursor/ [[BR]] 
     657 -- we open the cursor, and loop throught it, and exist at the end with EXIT WHEN NOT FOUND [[BR]] 
     658 -- We have struggled because we forget to retreive the columns using the * so no column was returned [[BR]] 
     659 
     660{{{#!sql 
     661DROP function if exists portugal.write_chemin(TEXT); 
     662CREATE OR REPLACE FUNCTION portugal.write_chemin(_nome text) 
     663   RETURNS integer AS  
     664 $$ 
     665DECLARE  
     666 current_count integer default 0; 
     667 the_downstream_point   RECORD; 
     668 cur_target integer; 
     669 cur_down CURSOR(_text text)  
     670         FOR SELECT * 
     671         FROM  portugal.downstream_points  
     672         WHERE nome = _nome; 
     673BEGIN 
     674   -- Open the cursor 
     675   OPEN  cur_down(_nome); 
     676  
     677   LOOP 
     678    -- fetch row one by one into the_downstream_point 
     679      FETCH cur_down INTO the_downstream_point; 
     680    -- exit when no more row to fetch 
     681      EXIT WHEN NOT FOUND; 
     682      current_count := current_count+1; 
     683     cur_target := the_downstream_point.target; 
     684    -- raise notice for now 
     685      RAISE NOTICE 'target :%',cur_target;  
     686    -- create the chemin for this target and all upstream segments 
     687    UPDATE portugal.rivers set chemin=get_path(cur_target,u.source) from portugal.upstream_segments(cur_target) u 
     688                where rivers.source = u.source;  
     689   END LOOP; 
     690   
     691   -- Close the cursor 
     692   CLOSE cur_down; 
     693  
     694   RETURN current_count; 
     695END;  
     696$$  
     697LANGUAGE plpgsql; 
     698 
     699select portugal.write_chemin('Lis e Ribeiras Costeiras'); 
     700select * from portugal.downstream_points where nome = 'Lis e Ribeiras Costeiras'; 
     701}}}