Підключення до мережі (автобусні зупинки), які не лежать на лініях (LINESTRING), до мережі?


9

Мені потрібно підключити автобусні зупинки (точки) до мережевого рівня (дані OSM). Ці автобусні зупинки не лежать безпосередньо на лініях (див. Знімок екрана), а також не слід переміщувати їх місцезнаходження. Я використовую PostGIS, pgrouting та QGIS, і мережа вже маршрутизована з джерелами та цільовими стовпцями тощо.

введіть тут опис зображення

В основному я хочу зробити дві речі згодом:

  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)
симплексіо

1
додаючи коментар, тому що я взагалі не перевіряв це, синтаксис, ймовірно, помиляється ... ... виберіть *, st_split (a.lg, a.pg) з (виберіть *, лінії.g як lg, points.geom як pg від пунктів об'єднати рядки на ST_intersect (p.geom, l.geom)) як колекція розбитого повернення, тому вам потрібно все-таки витягнути з нього всі рядки ...
simplexio

2

Це моє повне рішення. Він передбачає своєрідний злом, щоб зробити розщеплення: я отримую точки на лініях (способи використання термінології OSM) за допомогою ST_ClosestPoint, а потім буфер їх дуже невеликою відстані, щоб розщеплення фактично працювало. В іншому випадку неточність / помилки округлення запобігали розщепленню.

У цьому проблема полягає в тому, що він генерує два розщеплення на кожному рядку за точкою (через буферизацію). Для мого використання це було чудово, оскільки пізніше я пролягав між точками розщеплення, найближчими до вихідних точок, які знаходилися поза лінією, і це могло бути будь-якою з двох точок розщеплення лінії перетину буфера.

Я почав із завантаження 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;

Створіть топологію, необхідну для маршрутизації з прошиванням:

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

Моя перша думка також була буферною. Але якщо ви можете отримати "відстань до найближчого", буфер цієї суми, створити крапку на цьому перетині ... тоді ви можете створити лінію з кінцевими точками, що складається з початкової точки і "найближчої" точки до неї.
Мокс

1

Оскільки я працюю над подібним завданням, я просто хотів розповісти про підхід, яким я зараз користуюся. Це використовує GRASS GIS, але, наскільки я міг експериментувати з PostGIS, досить складно додати кілька нових точок до існуючих LineStrings, розділивши ці LineStrings у відповідних місцях - хоча я впевнений, що є зручне рішення.

Зараз я скористався v.netфункцією ГРІС ГРІС за допомогою опції connect. Просто виберіть input vector line layerі points layer. Існує можливість або прив’язати точки до найближчої точки на лініях, або створити нові зв’язки між найближчою точкою на лініях та новою точкою.

Ось зображення до і після. Праворуч для кожної точки шару точок додано вузол дорожньої мережі: введіть тут опис зображення

Після цього в PostGIS після створення ..._vertices_pgrтаблиці з дорожньої мережі просто призначте свої очки найближчій вершині, щоб ви могли використовувати їх у своїх запитах на маршрутизацію. Для цього завдання ви можете скористатися ST_ClosestPointфункцією, яку зробив @Setraworks у своїй відповіді.

Недоліками такого підходу є:

  • з'єднання точок з лініями повинно здійснюватися в ГРІС ГІС
  • маршрути, які обчислюються, можуть складатися з багатьох компонентів (залежно від кількості щойно доданих балів)
  • динамічне додавання нових балів неможливо

Цей підхід чудово працює, якщо у вас є певна кількість балів, які потрібно додати до дорожньої мережі (як у прикладі запитання з зупинками автобусів).

Якщо хтось може надати робочий приклад за допомогою PostGIS, я хотів би прочитати про це!


0

Існує публікація, в якій обговорюється подібна проблема, ви можете побачити цю публікацію в наступному місці: http://osdir.com/ml/qgis-user-gis/2011-11/msg00220.html


Це лише частина можливого рішення, оскільки після прив’язування точок до ліній точки лежать прямо на лініях, але вони все ще не є частиною мережі.
Встановлення

Якщо ви очікуєте отримання відповіді, яка забезпечує всі ваші вимоги, ви можете розчаруватися. Це може отримати вас на півдорозі, тоді ви можете зосередитись на іншій частині, якої вам не вистачає.
Райан Гарнетт

Я думаю, ти прав, Райан. Я вже встиг прив’язати точки до рядків, тож наступним кроком стане з'ясування того, як розділити рядки рядків на точки в postgis. Дякуємо за допомогу поки що!
Настанови

Радий, що можу допомогти. Є інструменти, які розділять лінію з точкою, але я продовжуватиму шукати варіант у PostGIS. Удачі
Райан Гарнетт

@Setraworks ви можете подивитися наступний варіант PostGIS (ST_Split) postgis.net/docs/ST_Split.html . Ви можете розділити рядок на крапку, ось пояснення від PostGIS: Функція підтримує розділення рядка за точкою, рядка за рядком, багатокутника за рядком. Повернута геометрія - це завжди колекція.
Райан Гарнетт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.