Hatlarda yer almayan noktalar (otobüs durakları) (LINESTRING) ağa bağlanıyor mu?


10

Bir ağ katmanına (OSM verileri) otobüs durakları (noktalar) bağlamanız gerekir. Bu otobüs durakları doğrudan hatların üzerinde değil (ekran görüntüsüne bakın) ve konumları taşınmamalıdır. PostGIS, pgrouting ve QGIS kullanıyorum ve ağ zaten kaynak ve hedef sütunlarla yönlendirilebilir.

resim açıklamasını buraya girin

Daha sonra iki şey yapmak istiyorum:

  1. Otobüs arasındaki mesafelerin elde edilmesi en kısa yol analizini kullanarak durur.
  2. OSM ağını kullanarak otobüs durağından yürüme mesafeleri ile izoronlar oluşturma.

Kesin değerleri elde etmek için, otobüs duraklarına en yakın şekilde 'başlar' ve 'durur'. Çoğu durumda, mevcut en yakın düğüm kesin değerleri elde etmek için çok uzakta olacaktır. Ancak otobüs durağının gerçek nokta konumuna bir yönlendirme olmamalıdır. Resimdeki örneğimde, duraklar arasındaki güzergahın nasıl görünmesi gerektiğini görebilirsiniz.

Otobüs duraklarına en yakın olan ağa otomatik olarak yeni düğümler (LINESTRING) ekleme imkanı var mıdır yoksa yalnızca sorgu için ayarlanan (yolun ne olduğuna benzer) bir tür 'kukla nokta' üzerinde yönlendirmeye başlamak mümkün müdür? QGIS grafik eklentisi yapar)?

Yanıtlar:


5

Çözümün ilk kısmı şudur:

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;

Bu, busstops'u resimde gördüğünüz gibi yol ağının hatlarına bağlar ve oldukça kolay çalışır.

resim açıklamasını buraya girin

Daha sonra çizgileri noktaların yerlerinde bölmeye çalışacağım. Çizgileri böldükten sonra tekrar pgr_createTopology kullanmak istiyorum. Bundan sonra, busstops'a en yakın düğümleri bulmak için bir sorgu oluşturmak mümkün olmalıdır, bu da 'splitpoint'lerde yeni oluşturulan düğümlerim olacaktır.

Birisi benim için postgis'teki nokta özellikleri ile linestring'i nasıl bölebileceğime dair bir ipucu olsaydı minnettar olurum, çünkü benzer sorulara baktıktan sonra şu an için kolay bir çözüm yok gibi görünüyor.


ST_Split (somethingtocut, bıçak)
simplexio

1
bunu hiç test etmediğim için yorum ekliyorum, muhtemelen yanlış sözdizimi ... ... (select *, lines.g lg, points.geom'dan pg olarak *, st_split (a.lg, a.pg) seçin ST_intersect (p.geom, l.geom)) 'da satırlara katılın, ancak bu bölünmüş dönüş koleksiyonu, böylece hala tüm satırları çıkarmanız gerekiyor ...
simplexio

2

Bu benim tam çözümüm. Ayrılmayı tamamlamak için bir tür hack içerir: Çizgilerdeki noktaları (OSM terminolojisini kullanmanın yolları) kullanarak alıyorum ST_ClosestPointve sonra ayırmanın gerçekten işe yaraması için onları çok küçük bir mesafeyle tamponluyorum. Aksi takdirde kesinsizlik / yuvarlama hataları bölünmeyi önlüyordu.

Bu, nokta başına her satırda (arabellekleme nedeniyle) iki bölme oluşturması sorununa sahiptir. Benim kullanımım için bu iyiydi, daha sonra orijinal noktalara en yakın olan ve çizginin dışında olan bölme noktaları arasına geçtim ve çizgi-tampon kavşağının iki bölme noktasından biri olabilir.

OSM verilerini indirip Postgres'e ekleyerek başladım:

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

Bir arabellek kullanarak yolları bölme:

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 ile yönlendirme için gerekli topolojiyi oluşturun:

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');

İlk düşüncem de tampon oldu. Ama eğer 'en yakın mesafeye' mesafe alabilir, bu miktarı tamponlayabilir, kesişen noktada bir nokta oluşturabilirsiniz ... o zaman orijinal noktanızdan ve ona en yakın noktadan oluşan uç noktalarla bir çizgi oluşturabilirsiniz.
Mox

1

Benzer bir görev üzerinde çalıştığım için, şu anda kullandığım yaklaşımı anlatmak istedim. Bu GRASS GIS kullanır, ancak PostGIS ile yaptığım deneyler ilerledikçe, bu LineStrings'i ilgili konumlara bölerek mevcut LineStrings'e birden fazla yeni nokta eklemek oldukça karmaşıktır - ancak uygun bir çözüm olduğundan eminim.

Şimdi v.netseçeneği kullanarak GRASS GIS işlevini kullandım connect. Sadece seçin input vector line layerve points layer. Noktaları çizgilerdeki en yakın noktaya yapıştırma veya çizgilerdeki en yakın nokta ile yeni nokta arasında yeni bağlantılar oluşturma seçeneği vardır.

İşte öncesi ve sonrası görüntüsü. Sağ tarafa, noktalar katmanının her noktası için yol ağına bir düğüm eklendi: resim açıklamasını buraya girin

Daha sonra PostGIS'te, ..._vertices_pgrtablonuzu yol ağından oluşturduktan sonra , yönlendirme isteklerinizde kullanabilmeniz için puanlarınızı en yakın köşeye atamanız yeterlidir. Bu görev için ST_ClosestPointcevabında @Setraworks tarafından yapılan işlevi kullanabilirsiniz .

Bu yaklaşımın dezavantajları şunlardır:

  • noktaların hatlarla bağlanması GRASS GIS'de yapılmalıdır.
  • hesaplanan yollar birçok bileşenden oluşabilir (yeni eklenen noktaların miktarına bağlı olarak)
  • dinamik yeni nokta eklenmesi mümkün değil

Bu yaklaşım, yol ağına tanımlanacak belirli sayıda noktanız varsa işe yarar (otobüs duraklarıyla ilgili soru örneğinde olduğu gibi).

Eğer herhangi biri PostGIS kullanarak çalışan bir örnek verebilirse, bunu okumak isterim!


0

Benzer bir sorunu tartışan bir yayın var, bu yayını aşağıdaki konumda görebilirsiniz: http://osdir.com/ml/qgis-user-gis/2011-11/msg00220.html


Bu, olası bir çözümün sadece bir parçasıdır, çünkü noktaları çizgilere tutturduktan sonra, noktalar doğrudan çizgilerin üzerinde bulunur, ancak yine de ağın bir parçası değildir.
Setraworks

Size tüm gereksinimlerinizi karşılayacak bir yanıt almayı düşünüyorsanız, hayal kırıklığına uğrayabilirsiniz. Bu sizi yarıya indirebilir, o zaman eksik olduğunuz diğer kısma odaklanabilirsiniz.
Ryan Garnett

Bence haklısın Ryan. Noktaları çizgilere tutturmayı başardım, bu yüzden bir sonraki adım postgis'teki noktalarla linestringlerin nasıl bölüneceğini bulmak olacak. Şimdilik yardımlarınız için teşekkürler!
Setraworks

Yardımcı olduğuma sevindim. Bir çizgiyi nokta ile ayıracak araçlar var, ancak PostGIS'de bir seçenek aramaya devam edeceğim. İyi şanslar
Ryan Garnett

@Setraworks, aşağıdaki PostGIS seçeneğine (ST_Split) postgis.net/docs/ST_Split.html bakmak isteyebilirsiniz . Bir noktayı bir noktaya bölebilirsiniz, işte PostGIS'ten açıklama: İşlev bir satır nokta, satır satır, çokgen satır satır bölünmeyi destekler. Döndürülen geometri her zaman bir koleksiyondur.
Ryan Garnett
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.