2 votos

¿Proyección de punto a punto del GPS en la carretera de pgrouting más cercana (coincidencia con el mapa)?

Soy bastante nuevo en PostGIS y pgRouting.

Estoy interesado en hacer una simple coincidencia de mapas. Precisamente, encontrar el punto más cercano en una red de carreteras OSM dada.

He importado con éxito la red OSM con osm2pgrouting. Después de buscar en Google y leer mucho he podido encontrar cómo obtener el vértice de carretera más cercano desde un punto P dado (-49.239099 -16.667802) utilizando la siguiente consulta:

SELECT * FROM ways_vertices_pgr ORDER BY the_geom <->
ST_GeometryFromText('POINT(-49.239099 -16.667802)',4326) LIMIT 1

Sin embargo, lo que me interesa en el punto de proyecto de P que debe estar situado en el borde más cercano en la red de carreteras.

¿Cómo puedo hacerlo?

3voto

mathieu Puntos 53

Utilice su estructura de consulta para obtener el borde más cercano a P y proyectar un punto más cercano P' de P en el borde con ST_ClosestPoint :

SELECT edge.id,
       ST_ClosestPoint(edge.geom, <P>) AS "P'"
FROM (
    SELECT <edges_id> AS id,
           <edges_geom> AS geom
    FROM <edges_table>
    ORDER BY ST_Distance(<P>, <edges_geom>)
    LIMIT 1
) AS edge

Nota: puede haber mejores soluciones si realmente te interesa la distancia a lo largo de la línea hasta el nodo de la línea que necesitas como punto de entrada para el enrutamiento.

ACTUALIZACIÓN:
ST_Distance junto con LatLon (por ejemplo, EPSG:4326) es un asunto complicado. Si bien puede funcionar aquí, con distancias suficientemente pequeñas, al menos no lo utilice para derivar distancias métricas (esto se aplica igualmente al KNN operadores, por ejemplo <-> ). Para una solución más robusta y precisa, considere la posibilidad de fundir a geografía antes de los cálculos (por ejemplo ST_Distance(<P>::geography, <edges_geom>::geography) )

2voto

S.Lott Puntos 207588

Recientemente he trabajado en un problema similar a este.

Mi metodología fue la siguiente:

  1. Encontrar la línea más cercana al punto o puntos de entrada
  2. Obtenga una pequeña subsección de esta línea
  3. Rota la subsección 90 grados alrededor de un punto de la línea más cercana al punto de entrada (nos permite cortar y o crear punto en la intersección)

A esta metodología podemos añadir una forma de cortar obtener un punto cuando estas dos líneas se cruzan... Para ello podemos utilizar algo como este :

ST_CollectionExtract(ST_Intersection(a.geom, b.geom), 1)

Estaba trabajando con una tabla de muchos puntos de entrada, pero debería estar bien para un solo punto (necesitamos un geom y id en las tablas de redes y puntos).

Código completo aquí:

--1 Closest line to point(s)
CREATE TABLE schema.test_closestline AS
            SELECT pid ,lid, distance_m, a.geom 
            FROM
                (SELECT q.id pid, a.id lid, ROUND(ST_Distance(q.geom, a.geom)::NUMERIC, 2) as distance_m, 
            ROW_NUMBER() OVER (PARTITION BY q.id ORDER BY ST_DISTANCE(a.geom,q.geom)) as row_number,
            a.geom
                FROM schema.road_network a
                INNER JOIN schema.input_points q ON
                ST_DWITHIN(a.geom,q.geom,100) -- use a sensible distance to restrict the result set without losing records 
                ) a
            WHERE a.row_number = 1

DROP TABLE IF EXISTS schema.test_blade_rotate;

--2/3 get Small line segment at right 90 degress to line, crossing at closest point to input point
CREATE TABLE schema.test_blade_rotate AS   
SELECT
line.id, ST_Rotate(line.geom, 1.5708, ST_Centroid(line.geom)) geom --1.5708 radians = 90 degrees
FROM
   (
   SELECT paired.pid id, 
CASE 
    WHEN  ( round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2) + 1 = 1 ) THEN  ST_LineSubstring(paired.lgeom, round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2), round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2)+ 0.01)
    WHEN  ( round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2) + 1 = 2) THEN  ST_LineSubstring(paired.lgeom, round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2) - 0.01, round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2))
    ELSE ST_LineSubstring(paired.lgeom,(round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2) - 0.01), (round((ST_LineLocatePoint(paired.lgeom,paired.pgeom))::numeric,2)+0.01))
END AS geom 
   FROM 
        (SELECT line.pid, (ST_DUMP(line.geom)).geom lgeom, (ST_DUMP(point.geom)).geom pgeom
        FROM 
        schema.test_closestline as line,
        schema.input_points as point
        WHERE line.pid = point.id) as paired
   ) as line;

--4 POINT FROM INTERSECT OF TWO LINES:
CREATE TABLE schema.closest_point AS   
SELECT 
b.id, ST_CollectionExtract(ST_Intersection(a.geom, b.geom), 1) as geom        
FROM  schema.road_network a, schema.test_blade_rotate b

0voto

mattisan Puntos 21

Utiliza un Buffer para encontrar el punto de intersección de la línea más cercana. El punto de la trayectoria de la línea se identifica entonces fácilmente.

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