ライン(LINESTRING)にないポイント(バス停)をネットワークに接続していますか?


9

バスストップ(ポイント)をネットワークレイヤー(OSMデータ)に接続する必要があります。これらのバス停は路線上にありません(スクリーンショットを参照)。また、場所を移動する必要もありません。私はPostGIS、pgrouting、QGISを使用しており、ネットワークはすでにソース列やターゲット列などでルーティング可能です。

ここに画像の説明を入力してください

その後、主に2つのことを行います。

  1. 最短経路分析を使用してバス停間の距離を取得する。
  2. OSMネットワークを使用して、バス停から徒歩圏内にアイソクロンを作成します。

正確な値を取得するには、ルーティングがバス停に最も近い「スタート」と「ストップ」であることが必要です。多くの場合、最も近い既存のノードは遠すぎて正確な値を取得できません。ただし、バス停の実際のポイント位置へのルーティングはありません。写真の私の例では、ストップ間のルーティングがどのように見えるかを確認できます。

バス停に最も近い新しいノードをネットワーク(LINESTRING)に自動的に挿入する可能性はありますか、またはクエリのためだけに設定された一種の「ダミーポイント」でルーティングを開始することは可能ですか(道路と同様) QGISのグラフプラグインはありますか?)

回答:


5

ソリューションの最初の部分はこれです:

SELECT a.id, ST_Closestpoint(ST_Collect(b.geom_way), a.geom) AS geom 
FROM point_table a, line_table b
GROUP BY a.id, a.geom;

写真でわかるように、これはバスストップを道路網の線にスナップし、非常に簡単に機能します。

ここに画像の説明を入力してください

次に、ポイントの位置でラインを分割してみます。行を分割した後、もう一度pgr_createTopologyを使用します。その後、バスストップに最も近いノードを見つけるクエリを作成できるはずです。これは、「スプリットポイント」で新しく生成されたノードになります。

同様の質問を見てみたところ、現時点では簡単な解決策はないようです。


ST_Split(somethingtocut、blade)
simplexio 2014年

1
私はこれをまったくテストしなかったのでコメントを追加します、syntacはおそらく間違っています... ... select *、st_split(a.lg、a.pg)from(select *、lines.g as lg、points.geom as pg from points ST_intersect(p.geom、l.geom))の行をaとして結合しますが、戻りのコレクションを分割するため、すべての行をそこから取り出す必要があります...
simplexio

2

これは私の完全な解決策です。これは、分割を実行するための一種のハックを伴います。私はを使用してライン上のポイント(OSM用語を使用するため)をST_ClosestPoint取得し、非常に短い距離でそれらをバッファリングして、分割を実際に機能させます。それ以外の場合は、不正確/丸めエラーが分割を妨げていました。

これには、ポイントごとに各行に2つの分割が生成されるという問題があります(バッファリングのため)。後で私は線の外側にある元の点に最も近い分割点の間をルーティングしたので、これは問題ありませんでした。これは、ラインバッファーの交点の2つの分割点のいずれかである可能性があります。

まず、OSMデータをダウンロードしてPostgresに埋め込みます。

CITY="MY_CITY"
BBOX="-46.6003,-23.7362,-46.4806,-23.5965"
wget --progress=dot:mega -O "$CITY.osm" "http://www.overpass-api.de/api/xapi?*[bbox=${BBOX}][@meta]"

# create database
createdb my_database
# add extensions
psql -d my_database -c "CREATE EXTENSION postgis;"
psql -d my_database -c "CREATE EXTENSION pgrouting;"

# import osm data to postgres database
osm2pgrouting \
    -f MY_CITY.osm \
    -d my_database \
    -U user

# load points into db
shp2pgsql -I -s 4326 points_to_split_ways.shp public.points_to_split_ways | psql -d my_database

バッファを使用してウェイを分割する:

WITH pts_ways AS (
  -- get nearest way for each point we want to split the ways by
  SELECT s.gid AS pt_id, ws.gid AS way_gid, s.geom AS pt_geom, ws.the_geom AS way_geom FROM points_to_split_ways s
  CROSS JOIN LATERAL
  (
    SELECT w.gid, w.the_geom
    FROM ways w
    ORDER BY s.geom <-> w.the_geom LIMIT 1
  ) AS ws
), pts_on_ways AS (
  -- "move" these points to be on top of the ways
  SELECT pt_id, way_gid, ST_ClosestPoint(way_geom, pt_geom) as geom
  FROM pts_ways
), ways_without_pts AS (
  -- get the ways that don't have any points on them
  SELECT the_geom as the_geom, gid as way_gid FROM ways
  WHERE gid NOT IN (SELECT way_gid FROM pts_ways)
)
SELECT
  way_gid as old_id,
  -- we need to build a new unique ID, because split ways will share the old ID
  row_number() over(order by way_gid) as gid,
  -- this is the split way geometry
  the_geom
FROM (
  SELECT 
    way_gid,
    -- split the ways and dump into indiviudal segments
    (ST_Dump(ST_Split(line_geom, pt_geom))).geom AS the_geom
  FROM (
    (SELECT the_geom as line_geom, gid FROM ways) AS lines
    LEFT JOIN
    -- HACK: use a buffer to fix imprecisions / rounding errors
    -- this will generate one extra splitting per point (each buffer will intersect each way twice)
    -- but it's ok for our purposes
    -- also, collect them grouped by the way to handle cases where there are multiple points on the same way
    (SELECT ST_Collect(ST_Buffer(geom, 0.000001)) as pt_geom, way_gid FROM pts_on_ways GROUP BY way_gid) AS pts
    ON lines.gid = pts.way_gid
  ) AS tmp1
  -- union the ways without points, otherwise you'd get only the ones that were split
  UNION ALL
  SELECT way_gid, the_geom FROM ways_without_pts
) AS tmp2;

pgroutingを使用したルーティングに必要なトポロジを作成します。

SELECT UpdateGeometrySRID('ways_split','the_geom', 4326);
SELECT find_srid('public','ways_split','the_geom');
ALTER TABLE ways_split ADD COLUMN "source" integer;
ALTER TABLE ways_split ADD COLUMN "target" integer;
ALTER TABLE ways_split ADD PRIMARY KEY (gid);
ALTER TABLE ways_split ADD CONSTRAINT ways_source_fkey FOREIGN KEY (source) REFERENCES ways_split_vertices_pgr (id) MATCH FULL;
ALTER TABLE ways_split ADD CONSTRAINT ways_target_fkey FOREIGN KEY (target) REFERENCES ways_split_vertices_pgr (id) MATCH FULL;
SELECT pgr_createTopology('ways_split', 0.00001, 'the_geom', 'gid', clean := TRUE);
SELECT pgr_analyzeGraph('ways_split', 0.000001, the_geom := 'the_geom', id := 'gid');

私の最初の考えも同様にバッファでした。しかし、「最も近い距離」を取得できる場合は、その量をバッファリングし、その交点にポイントを作成します。次に、元のポイントとそれへの「最も近い」ポイントで構成される端点を持つ線を作成できます。
Mox

1

私は同様のタスクに取り組んでいるので、私が現在使用しているアプローチについてお話したかっただけです。これはGRASS GISを利用しますが、PostGISでの私の実験が行った限り、既存のLineStringをそれぞれの場所で分割することによって複数の新しいポイントを既存のLineStringに追加することは非常に複雑です-便利な解決策があると確信していますが。

v.netオプションを使用してGRASS GIS 関数を利用しましたconnect。ただ、選択input vector line layerpoints layer。ポイントをライン上の最も近いポイントにスナップするか、ライン上の最も近いポイントと新しいポイントの間に新しい接続を作成するオプションがあります。

これは変更前と変更後の画像です。右側に、ポイントレイヤーの各ポイントについて、道路網上のノードが追加されました。 ここに画像の説明を入力してください

その後PostGIS ..._vertices_pgrで、道路ネットワークからテーブルを作成した後、ポイントを最も近い頂点に割り当てて、ルーティングリクエストでそれらを使用できるようにします。このタスクでは、ST_ClosestPoint@ Setraworksが回答で行ったように関数を使用できます。

このアプローチの欠点は次のとおりです。

  • ポイントとラインの接続はGRASS GISで行う必要があります
  • 計算されたルートは、多くのコンポーネントで構成される場合があります(新しく追加されたポイントの数によって異なります)
  • 新しいポイントの動的な追加は不可能

この方法は、(バス停の質問の例のように)道路網に追加するポイントの数が定義されている場合にうまく機能します。

誰かがPostGISを使用して実用的な例を提供できる場合、それについて読んでみたいと思います!


0

同様の問題について説明する投稿があります。その投稿は次の場所にあります。http//osdir.com/ml/qgis-user-gis/2011-11/msg00220.html


これは可能なソリューションの一部にすぎません。ポイントをラインにスナップした後、ポイントはライン上に直接配置されますが、それらはまだネットワークの一部ではありません。
Setraworks、2014年

あなたがあなたのすべての要件を提供する答えを得ることを期待しているなら、あなたは失望するかもしれません。これは途中であなたを得るかもしれません、そしてあなたはあなたが欠けている他の部分に集中することができます。
Ryan Garnett 2014年

私はあなたが正しいライアンだと思います。ポイントをラインにスナップすることができたので、次のステップは、ラインストリングをポイントでラインストリングを分割する方法を見つけることです。これまでのご協力に感謝します!
Setraworks、2014年

お役に立てて嬉しいです。ラインをポイントで分割するツールはありますが、PostGISでオプションを探し続けます。幸運
ライアンガーネット、2014年

@Setraworksでは、次のPostGISオプション(ST_Split)postgis.net/docs/ST_Split.htmlを確認できます。ポイントでラインを分割することができます。PostGISからの説明は次のとおりです。この関数は、ポイントごと、ラインごと、ポリゴンごとの分割をサポートしています。返されるジオメトリは常にコレクションです。
Ryan Garnett 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.