11 votos

¿Cómo conectar a una red puntos (paradas de autobús) que no se encuentran en las líneas (LINESTRING)?

Necesito conectar paradas de autobús (puntos) a una capa de red (datos OSM). Estas paradas de autobús no se encuentran directamente en las líneas (véase la captura de pantalla) ni deben moverse en su ubicación. Utilizo PostGIS, pgrouting y QGIS y la red ya es enrutable con columnas de origen y destino, etc.

enter image description here

Principalmente quiero hacer dos cosas después:

  1. Obtención de las distancias entre las paradas de autobús mediante el análisis del camino más corto.
  2. Creación de isócronas con distancias a pie desde la parada de autobús utilizando la red OSM.

Para obtener valores exactos es necesario que la ruta "empiece" y "pare" lo más cerca posible de las paradas de autobús. En muchos casos, el nodo existente más cercano estará demasiado lejos para obtener valores exactos. Pero no debería haber un enrutamiento a la ubicación real del punto de la parada de autobús. En mi ejemplo en la imagen se puede ver cómo el enrutamiento entre las paradas debe ser como.

¿Existe la posibilidad de insertar automáticamente nuevos nodos en la red (LINESTRING) que estén más cerca de las paradas de autobús o es posible iniciar el enrutamiento en una especie de "punto ficticio" que se establece sólo para la consulta (similar a lo que hace el plugin de gráfico de carreteras en QGIS)?

5voto

ariefbayu Puntos 161

La primera parte de la solución es ésta:

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;

Esto encaja las paradas en las líneas de la red de carreteras, como se puede ver en la imagen, y funciona con bastante facilidad.

enter image description here

A continuación, intentaré dividir las líneas en las ubicaciones de los puntos. Después de dividir las líneas quiero usar pgr_createTopology de nuevo. Después de eso debería ser posible crear una consulta para encontrar los nodos más cercanos a las paradas, que serán mis nuevos nodos generados en los "puntos de división".

Agradecería que alguien me diera una pista sobre cómo dividir la cadena de líneas con las características de los puntos en postgis, ya que después de haber mirado preguntas similares no parece haber una solución fácil para eso por el momento.

0 votos

ST_Split(algocortado, hoja)

1 votos

añadiendo un comentario porque no he probado esto en absoluto, syntac probablemente mal ... ... select *, st_split(a.lg, a.pg) from ( select *, lines.g as lg, points.geom as pg from points join lines on ST_intersect(p.geom, l.geom) ) como a pero esa división devuelve la colección por lo que todavía tiene que obtener todas las líneas fuera de ella ...

2voto

Raj Puntos 1

Esta es mi solución completa. Implica una especie de hack para conseguir la división: Obtengo los puntos en las líneas (caminos, para usar la terminología de OSM) usando ST_ClosestPoint y luego amortiguarlas con una distancia muy pequeña para que la división funcione realmente. De lo contrario, los errores de imprecisión y redondeo impedían la división.

Esto tiene el problema de que genera dos divisiones en cada línea por punto (a causa del buffering). Para mi uso, esto estaba bien, ya que más tarde me dirigí entre los puntos de división más cercanos a los puntos originales, que estaban fuera de la línea, y podría ser cualquiera de los dos puntos de división de la intersección línea-buffer.

Empecé descargando los datos de OSM y cargándolos en 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

Dividir los caminos utilizando un buffer:

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;

Crear la topología necesaria para el enrutamiento con 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');

0 votos

Lo primero que pensé fue en el amortiguador también. Pero si puedes obtener una "distancia al más cercano", amortiguar esa cantidad, crear un punto en esa intersección... entonces podrías crear una línea con los puntos finales consistentes en tu punto original y el punto "más cercano" a él.

1voto

Easy D Puntos 9

Dado que estoy trabajando en una tarea similar, sólo quería contar el enfoque que estoy utilizando actualmente. Esto hace uso de GRASS GIS, pero por lo que mis experimentos con PostGIS fueron, es bastante complicado añadir múltiples puntos nuevos a LineStrings existentes dividiendo esos LineStrings en las respectivas ubicaciones - aunque estoy seguro de que hay una solución conveniente.

Ahora he utilizado el SIG de GRASS v.net utilizando la opción connect . Sólo tienes que elegir input vector line layer y points layer . Existe la opción de ajustar los puntos al punto más cercano de las líneas, o de crear nuevas conexiones entre el punto más cercano de las líneas y el nuevo punto.

Aquí hay una imagen del antes y el después. En la parte derecha, para cada punto de la capa de puntos se añadió un nodo en la red de carreteras: enter image description here

Después, en PostGIS, tras crear su ..._vertices_pgr tabla fuera de la red de carreteras sólo asigna sus puntos al vértice más cercano para poder utilizarlos en sus peticiones de enrutamiento. Para esta tarea puedes hacer uso del ST_ClosestPoint como ha hecho @Setraworks en su respuesta.

Las desventajas de este enfoque son:

  • la conexión de los puntos con las líneas debe hacerse en GRASS GIS
  • Las rutas que se calculan pueden constar de muchos componentes (dependiendo de la cantidad de nuevos puntos añadidos)
  • no es posible la adición dinámica de nuevos puntos

Este enfoque funciona bien si se tiene un número definido de puntos a añadir a la red de carreteras (como en el ejemplo de la pregunta con las paradas de autobús).

Si alguien puede proporcionar un ejemplo de funcionamiento utilizando PostGIS, me encantaría leerlo.

0voto

Dave Haynes Puntos 999

Hay un post que discute un problema similar, puedes ver ese post en la siguiente ubicación: http://osdir.com/ml/qgis-user-gis/2011-11/msg00220.html

0 votos

Esto es sólo una parte de una posible solución, porque después de ajustar los puntos a las líneas, los puntos se encuentran directamente en las líneas, pero todavía no son una parte de la red.

0 votos

Si espera obtener una respuesta que le proporcione todos sus requisitos, puede sentirse decepcionado. Esto puede hacer que llegue a la mitad del camino, y entonces podrá centrarse en la otra parte que le falta.

0 votos

Creo que tienes razón Ryan. Ya he conseguido ajustar los puntos a las líneas, así que el siguiente paso será averiguar cómo dividir las líneas con puntos en Postgis. ¡Gracias por tu ayuda hasta ahora!

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X