2011年4月25日月曜日

16 pgRouting in Debian6 8 - 高度なルーティングクエリ

7. Advanced Routing Queries 高度なルーティングクエリ
http://workshop.pgrouting.org/chapters/advanced.html

を試しに訳してみます。
インストールしたデータでみていきます。

前の章で説明した最短経路のクエリは通常は次のようになります。

routing2=# SELECT * FROM shortest_path_shooting_star('
SELECT gid as id, source, target, length as cost,
x1, y1, x2, y2,
rule,
to_cost,
reverse_cost FROM ways',10, 1, true, true);

これは、最短経路と呼ばれ、エッジの長さがその cost という意味です。
しかし、cost が長さである必要はありません。
cost は、時間、坂、表面、道路の種類など何にもなります。
また、複数のパラメータの組み合わせにもなります。

7.1. Weighted costs

実際のネットワークでは、異なる制限や様々な道路の種類などの設定があります。言い換えれば、私たちは最短距離を取得する必要はありませんが、格安パス-最小限のコストが欲しいときもあります。コストとしてかかるものに制限はありません。

osm2pgrouting ツールを使用して OSM 形式のデータを変換すると、道路の種類と道路クラスの2つの追加テーブルを取得します:

Note
We switch now to the database we previously generated with osm2pgrouting. From within PostgreSQL shell this is possible with the \c routing command.

前回 osm2pgrouting で生成したデータベースにすぐ切り替えます。 PostgreSQL シェル内から、これは \c ルーティングコマンドで可能です。

Run: SELECT * FROM types;

id | name
-----+------------
2 | cycleway
1 | highway
4 | junction
3 | tracktype

Run: SELECT * FROM classes;

id | type_id | name | cost
-----+---------+------------------+--------
201 | 2 | lane |
204 | 2 | opposite |
203 | 2 | opposite_lane |
202 | 2 | track |
120 | 1 | bridleway |
116 | 1 | bus_guideway |
121 | 1 | byway |
118 | 1 | cicleway |
119 | 1 | footway |
111 | 1 | living_street |
101 | 1 | motorway |
103 | 1 | motorway_junction|
102 | 1 | motorway_link |
117 | 1 | path |
114 | 1 | pedestrian |
106 | 1 | primary |
107 | 1 | primary_link |
110 | 1 | residential |
100 | 1 | road |
108 | 1 | secondary |
112 | 1 | service |
115 | 1 | services |
122 | 1 | steps |
109 | 1 | tertiary |
113 | 1 | track |
104 | 1 | trunk |
105 | 1 | trunk_link |
100 | 1 | unclassified |
401 | 4 | roundabout |
301 | 3 | grade1 |
302 | 3 | grade2 |
303 | 3 | grade3 |
304 | 3 | grade4 |
305 | 3 | grade5 |
(END):q

road クラスは class_id フィールドによって ways テーブルにリンクされています。
データのインポート後の cost 属性がまだ設定されていません。
その値は、UPDATE クエリを使用して変更することができます。
この例では、クラステーブルのコスト値は、任意に割り当てられるので、実行します:
(実際につぎのように実行します。)

routing2=# UPDATE classes SET cost=1;
UPDATE 34
routing2=# UPDATE classes SET cost=2.0 WHERE name IN ('pedestrian','step','footway');
UPDATE 2
routing2=# UPDATE classes SET cost=1.5 WHERE name IN ('cicleway','living_street','path');
UPDATE 3
routing2=# UPDATE classes SET cost=0.8 WHERE name IN ('secondary','tertiary');
UPDATE 2
routing2=# UPDATE classes SET cost=0.6 WHERE name IN ('primary','primary_link');
UPDATE 2
routing2=# UPDATE classes SET cost=0.4 WHERE name IN ('trunk','trunk_link');
UPDATE 2
routing2=# UPDATE classes SET cost=0.3 WHERE name IN ('motorway','motorway_junction','motorway_link');
UPDATE 3

パフォーマンスを向上させるため、特にネットワークのデータが大きい場合は、 ways テーブルの class_id フィールドと最終的に types テーブルの id フィールドにインデックスを作成することをお勧めします。

routing2=# CREATE INDEX ways_class_idx ON ways (class_id);
CREATE INDEX
routing2=# CREATE INDEX classes_idx ON classes (id);
CREATE INDEX

これら2つのテーブルの背後にある考え方は、各リンク(通常は長さ)の cost で乗算する係数を指定することです:

routing2=# SELECT * FROM shortest_path_shooting_star(
'SELECT gid as id, class_id, source, target, length*c.cost as cost,
x1, y1, x2, y2, rule, to_cost, reverse_cost*c.cost as reverse_cost
FROM ways w, classes c
WHERE class_id=c.id', 10, 1, true, true);

vertex_id | edge_id | cost
-----------+---------+--------------------
8 | 10 | 0.21436682583899
16 | 28 | 0.0616578808755829
18 | 29 | 0.0503517776608
20 | 30 | 0.0322363573642631
22 | 31 | 0.0152758932742916
24 | 383280 | 0.0193755609874666
294 | 207 | 0.14332341972053
76 | 76 | 0.0843040186165352
63 | 67 | 0.157592613117751
65 | 78 | 0.0681030174865841
56 | 62 | 0.118968821186703
57 | 591 | 0.069506289950689
964 | 12984 | 0.0607971743633479
20274 | 380597 | 0.0829580759736785
302 | 214 | 0.0948843293578448
27 | 36 | 0.190297596187546
28 | 1 | 0.680805240753506
(17 行)

~
(stdin):q

(6.3. Shooting-Star の 6.3.1. Core の結果と違うので経路が変更されたようです。reverse_cost を使用していないからかもしれませんが。)

7.2. Restricted access¶

もう一つの可能性は、特定の属性で道路リンクに非常に高いコストを設定するか、または、特定の道路リンクをまったく選択していないことにより、特定の種類の道路へのアクセスを制限することです:

UPDATE classes SET cost=100000 WHERE name LIKE 'motorway%';

サブクエリを通してあなたが好きなようにあなたのコストを"ミックス"することができます。これはすぐにルーティング要求の結果を変更します。コストの変化は、次の最短経路の検索に影響を与え、あなたのネットワークを再構築する必要はありません。

もちろん、特定の道路のクラスは同様のクエリのWHERE句で除外することができます。例えば、"living_street"クラスを除外する場合:

SELECT * FROM shortest_path_shooting_star(
'SELECT gid as id, class_id, source, target, length*c.cost as cost,
x1, y1, x2, y2, rule, to_cost, reverse_cost*c.cost as reverse_cost
FROM ways w, classes c
WHERE class_id=c.id AND class_id != 111', 10, 1, true, true);

vertex_id | edge_id | cost
-----------+---------+--------------------
8 | 10 | 0.21436682583899
16 | 28 | 0.0616578808755829
18 | 29 | 0.0503517776608
20 | 30 | 0.0322363573642631
22 | 31 | 0.0152758932742916
24 | 383280 | 0.0193755609874666
294 | 207 | 0.14332341972053
76 | 76 | 0.0843040186165352
63 | 67 | 0.157592613117751
65 | 78 | 0.0681030174865841
56 | 62 | 0.118968821186703
57 | 591 | 0.069506289950689
964 | 12984 | 0.0607971743633479
20250 | 380597 | 0.0829580759736785
302 | 214 | 0.0948843293578448
27 | 36 | 0.190297596187546
28 | 1 | 0.680805240753506
(17 行)

~
(stdin):q
(結果が変わらないのでこのルートでは living_street がないようです。)

もちろん、pgRouting は、あなたに PostgreSQL/PostGIS で可能なすべての種類のSQLを許可します。

0 件のコメント: