[63] | 1 | ============================================================================================================== |
---|
| 2 | Create a Network Topology |
---|
| 3 | ============================================================================================================== |
---|
| 4 | |
---|
| 5 | :doc:`osm2pgrouting <osm2pgrouting>` is a convenient tool, but it's also a *black box*. There are several cases where :doc:`osm2pgrouting <osm2pgrouting>` can't be used. Obviously if the data isn't OpenStreetMap data. Some network data already comes with a network topology that can be used with pgRouting out-of-the-box. Often network data is stored in Shape file format (``.shp``) and we can use PostGIS' ``shape2postgresql`` converter to import the data into a PostgreSQL database. But what to do then? |
---|
| 6 | |
---|
| 7 | .. image:: images/network.png |
---|
| 8 | :width: 250pt |
---|
| 9 | :align: center |
---|
| 10 | |
---|
| 11 | In this chapter you will learn how to create a network topology from scratch. For that we will start with data that contains the minimum attributes needed for routing and show how to proceed step-by-step to build routable data for pgRouting. |
---|
| 12 | |
---|
| 13 | ------------------------------------------------------------------------------------------------------------- |
---|
| 14 | Load network data |
---|
| 15 | ------------------------------------------------------------------------------------------------------------- |
---|
| 16 | |
---|
| 17 | At first we will load a database dump from the workshop ``data`` directory. This directory contains a compressed file with database dumps as well as a smaller network data of Denver downtown. If you haven't uncompressed the data yet, extract the file by |
---|
| 18 | |
---|
| 19 | .. code-block:: bash |
---|
| 20 | |
---|
| 21 | cd ~/Desktop/pgrouting-workshop/ |
---|
| 22 | tar -xvzf data.tar.gz |
---|
| 23 | |
---|
| 24 | The following command will import the database dump. It will add PostGIS and pgRouting functions to a database, in the same way as decribed in the previous chapter. It will also load the Denver sample data with a minimum number of attributes, which you will usually find in any network data: |
---|
| 25 | |
---|
| 26 | .. code-block:: bash |
---|
| 27 | |
---|
| 28 | # Optional: Drop database |
---|
| 29 | dropdb -U postgres pgrouting-workshop |
---|
| 30 | |
---|
| 31 | # Load database dump file |
---|
| 32 | psql -U postgres -f ~/Desktop/pgrouting-workshop/data/sampledata_notopo.sql |
---|
| 33 | |
---|
| 34 | Let's see wich tables have been created: |
---|
| 35 | |
---|
| 36 | .. rubric:: Run: ``psql -U postgres -d pgrouting-workshop -c "\d"`` |
---|
| 37 | |
---|
| 38 | .. code-block:: sql |
---|
| 39 | |
---|
| 40 | List of relations |
---|
| 41 | Schema | Name | Type | Owner |
---|
| 42 | --------+-------------------+-------+---------- |
---|
| 43 | public | classes | table | postgres |
---|
| 44 | public | geography_columns | view | postgres |
---|
| 45 | public | geometry_columns | table | postgres |
---|
| 46 | public | spatial_ref_sys | table | postgres |
---|
| 47 | public | types | table | postgres |
---|
| 48 | public | ways | table | postgres |
---|
| 49 | (6 rows) |
---|
| 50 | |
---|
| 51 | |
---|
| 52 | The table containing the road network data has the name ``ways``. It consists of the following attributes: |
---|
| 53 | |
---|
| 54 | .. rubric:: Run: ``psql -U postgres -d pgrouting-workshop -c "\d ways"`` |
---|
| 55 | |
---|
| 56 | .. code-block:: sql |
---|
| 57 | |
---|
| 58 | Table "public.ways" |
---|
| 59 | Column | Type | Modifiers |
---|
| 60 | ----------+------------------+----------- |
---|
| 61 | gid | integer | not null |
---|
| 62 | class_id | integer | |
---|
| 63 | length | double precision | |
---|
| 64 | name | character(200) | |
---|
| 65 | the_geom | geometry | |
---|
| 66 | Indexes: |
---|
| 67 | "ways_pkey" PRIMARY KEY, btree (gid) |
---|
| 68 | "geom_idx" gist (the_geom) |
---|
| 69 | Check constraints: |
---|
| 70 | "enforce_dims_the_geom" CHECK (ndims(the_geom) = 2) |
---|
| 71 | "enforce_geotype_the_geom" CHECK (geometrytype(the_geom) = |
---|
| 72 | 'MULTILINESTRING'::text OR the_geom IS NULL) |
---|
| 73 | "enforce_srid_the_geom" CHECK (srid(the_geom) = 4326) |
---|
| 74 | |
---|
| 75 | It is common that road network data provides at least the following information: |
---|
| 76 | |
---|
| 77 | * Road link ID (gid) |
---|
| 78 | * Road class (class_id) |
---|
| 79 | * Road link length (length) |
---|
| 80 | * Road name (name) |
---|
| 81 | * Road geometry (the_geom) |
---|
| 82 | |
---|
| 83 | This allows to display the road network as a PostGIS layer in GIS software, for example in QGIS. Though it is not sufficient for routing, because it doesn't contain network topology information. |
---|
| 84 | |
---|
| 85 | For the next steps we need to start the PostgreSQL command line tool |
---|
| 86 | |
---|
| 87 | .. code-block:: bash |
---|
| 88 | |
---|
| 89 | psql -U postgres pgrouting-workshop |
---|
| 90 | |
---|
| 91 | ... or use PgAdmin III. |
---|
| 92 | |
---|
| 93 | |
---|
| 94 | -------------------------------------------------------------------------------------------------------------- |
---|
| 95 | Calculate topology |
---|
| 96 | -------------------------------------------------------------------------------------------------------------- |
---|
| 97 | |
---|
| 98 | Having your data imported into a PostgreSQL database usually requires one more step for pgRouting. You have to make sure that your data provides a correct network topology, which consists of information about source and target ID of each road link. |
---|
| 99 | |
---|
| 100 | If your network data doesn't have such network topology information already you need to run the ``assign_vertex_id`` function. This function assigns a ``source`` and a ``target`` ID to each link and it can "snap" nearby vertices within a certain tolerance. |
---|
| 101 | |
---|
| 102 | .. code-block:: sql |
---|
| 103 | |
---|
| 104 | assign_vertex_id('<table>', float tolerance, '<geometry column', '<gid>') |
---|
| 105 | |
---|
| 106 | First we have to add source and target column, then we run the assign_vertex_id function ... and wait.: |
---|
| 107 | |
---|
| 108 | .. code-block:: sql |
---|
| 109 | |
---|
| 110 | -- Add "source" and "target" column |
---|
| 111 | ALTER TABLE ways ADD COLUMN "source" integer; |
---|
| 112 | ALTER TABLE ways ADD COLUMN "target" integer; |
---|
| 113 | |
---|
| 114 | -- Run topology function |
---|
| 115 | SELECT assign_vertex_id('ways', 0.00001, 'the_geom', 'gid'); |
---|
| 116 | |
---|
| 117 | .. note:: |
---|
| 118 | |
---|
| 119 | Execute ``psql -U postgres -d pgrouting-workshop`` in your terminal to connect to the database and start the PostgreSQL shell. Leave the shell with ``\q`` command. |
---|
| 120 | |
---|
| 121 | .. warning:: |
---|
| 122 | |
---|
| 123 | The dimension of the tolerance parameter depends on your data projection. Usually it's either "degrees" or "meters". |
---|
| 124 | |
---|
| 125 | |
---|
| 126 | ------------------------------------------------------------------------------------------------------------- |
---|
| 127 | Add indices |
---|
| 128 | ------------------------------------------------------------------------------------------------------------- |
---|
| 129 | |
---|
| 130 | Fortunately we didn't need to wait too long because the data is small. But your network data might be very large, so it's a good idea to add an index to ``source`` and ``target`` column. |
---|
| 131 | |
---|
| 132 | .. code-block:: sql |
---|
| 133 | |
---|
| 134 | CREATE INDEX source_idx ON ways("source"); |
---|
| 135 | CREATE INDEX target_idx ON ways("target"); |
---|
| 136 | |
---|
| 137 | After these steps our routing database look like this: |
---|
| 138 | |
---|
| 139 | .. rubric:: Run: ``\d`` |
---|
| 140 | |
---|
| 141 | .. code-block:: sql |
---|
| 142 | |
---|
| 143 | List of relations |
---|
| 144 | Schema | Name | Type | Owner |
---|
| 145 | --------+---------------------+----------+---------- |
---|
| 146 | public | geography_columns | view | postgres |
---|
| 147 | public | geometry_columns | table | postgres |
---|
| 148 | public | spatial_ref_sys | table | postgres |
---|
| 149 | public | vertices_tmp | table | postgres |
---|
| 150 | public | vertices_tmp_id_seq | sequence | postgres |
---|
| 151 | public | ways | table | postgres |
---|
| 152 | (6 rows) |
---|
| 153 | |
---|
| 154 | .. rubric:: Run: ``\d ways`` |
---|
| 155 | |
---|
| 156 | .. code-block:: sql |
---|
| 157 | |
---|
| 158 | Table "public.ways" |
---|
| 159 | Column | Type | Modifiers |
---|
| 160 | ----------+------------------+----------- |
---|
| 161 | gid | integer | not null |
---|
| 162 | class_id | integer | |
---|
| 163 | length | double precision | |
---|
| 164 | name | character(200) | |
---|
| 165 | the_geom | geometry | |
---|
| 166 | source | integer | |
---|
| 167 | target | integer | |
---|
| 168 | Indexes: |
---|
| 169 | "ways_pkey" PRIMARY KEY, btree (gid) |
---|
| 170 | "geom_idx" gist (the_geom) |
---|
| 171 | "source_idx" btree (source) |
---|
| 172 | "target_idx" btree (target) |
---|
| 173 | Check constraints: |
---|
| 174 | "enforce_dims_the_geom" CHECK (ndims(the_geom) = 2) |
---|
| 175 | "enforce_geotype_the_geom" CHECK (geometrytype(the_geom) = |
---|
| 176 | 'MULTILINESTRING'::text OR the_geom IS NULL) |
---|
| 177 | "enforce_srid_the_geom" CHECK (srid(the_geom) = 4326) |
---|
| 178 | |
---|
| 179 | Now we are ready for our first routing query with :doc:`Dijkstra algorithm <shortest_path>`! |
---|