5 votos

¿Cómo se puede enrutar sobre bordes (parciales) en pgrouting?

He hecho un sistema de planificación de rutas (basado en el camino más corto usando A*) como el servicio de direcciones de Google usando pgrouting y google maps. Incluye hacer clic en el mapa para generar puntos de ruta, arrastrar los puntos de ruta o las polilíneas para cambiar la ruta deseada. También muestra un panel de direcciones con instrucciones para llegar de A a B.

Sin embargo, en la geocodificación inversa que utilizo para saber dónde hace clic el usuario en el mapa, devuelvo el nodo más cercano en la topología. Todo esto funciona bastante bien excepto en algunos casos del mundo real en los que una ruta directa de A a B es más larga que una ruta indirecta a través de D

enter image description here

Los azules A,D,B son los nodos y los rojos C-A, C-B son los clics de mi ratón que corresponden a esos nodos. El rojo C-C es el lugar del borde que quiero que visite mi ruta.

Si un usuario quiere ir de A a B a través de la arista larga directa no es posible en este momento porque no es la ruta más rápida.

Estoy buscando una manera de hacer rutas sobre aristas o aristas parciales. Uno puede imaginar que un usuario no quiere empezar en un nodo, sino en algún lugar a mitad de camino en un borde (este es otro caso de uso, pero creo que se resolverá también con la respuesta que busco).

La forma más limpia que se me ocurre es generar nodos temporales en una arista cuando el usuario hace clic en ella (véase el clic C-C en la imagen) dividiendo efectivamente una arista en 2 aristas y colocando un nuevo nodo (temporal) en el punto de división. De esta manera, el pgrouting puede hacer una ruta sobre este nuevo nodo y así forzar la ruta para seguir las aristas que rodean ese nuevo nodo.

Sin embargo, esto generará muchos nodos temporales al arrastrar una polilínea por el mapa. Todos esos nodos generados durante_arrastrar_deben ser eliminados, excepto el creado al arrastrar_final, ya que ese pasa a formar parte de la ruta final.

Así que me pregunto si hay maneras más fáciles de resolver esto?

5voto

Felipe Olmos Puntos 246

Resolví este problema añadiendo efectivamente un nodo temporal en la arista pulsada y añadiendo 2 aristas temporales a este nodo temporal. Al unir manualmente estos nodos y aristas temporales antes de llamar a shortest_path_astar se son que se utilizan para calcular la ruta correcta, pero no abarrotar su base de datos con registros adicionales que sólo son interesantes para un usuario en particular (en un momento determinado).

Aquí la consulta SQL que he utilizado (en Python):

"SELECT 
    row_number() over (range unbounded preceding) as rownumber, 
    astar.vertex_id, 
    astar.edge_id,
    astar.cost
FROM 
    shortest_path_astar('SELECT 
                            gid as id, 
                            source::integer as source, 
                            target::integer as target,
                            length::double precision as cost, 
                            ST_X(ST_Startpoint(the_geom)) as x1, 
                            ST_Y(ST_Startpoint(the_geom)) as y1, 
                            ST_X(ST_Endpoint(the_geom)) as x2, 
                            ST_Y(ST_Endpoint(the_geom)) as y2 
                        FROM ways 
                        %s', 
                        %s, 
                        %s, 
                        false, 
                        false) astar" % (extra_edges, route_origin, route_destination)

donde route_origin o route_destination puede ser el nuevo id temporal (negativo) del nodo virtual y extra_edges tiene el aspecto siguiente

" UNION SELECT %d, %s, %d, ww.length * %f, ST_X(ST_Startpoint(ww.the_geom)), ST_Y(ST_Startpoint(ww.the_geom)), ST_X(ST_Line_Interpolate_Point(ww.the_geom, %f)), ST_Y(ST_Line_Interpolate_Point(ww.the_geom, %f)) FROM ways ww WHERE ww.source = %s AND ww.target = %s" % (edgeid, edge_fromnode, nodeid, perc, perc, perc, edge_fromnode, edge_tonode)
+ " UNION SELECT %d, %d, %s, ww.length * (1-%f), ST_X(ST_Line_Interpolate_Point(ww.the_geom, %f)), ST_Y(ST_Line_Interpolate_Point(ww.the_geom, %f)), ST_X(ST_Endpoint(ww.the_geom)), ST_Y(ST_Endpoint(ww.the_geom)) FROM ways ww WHERE ww.source = %s AND ww.target = %s" % (edgeid-1, nodeid, edge_tonode, perc, perc, perc, edge_fromnode, edge_tonode);

Donde edgeid es un id único (negativo) para esta arista temporal, nodeid un id único (negativo) para este nodo virtual, edge_fromnode el nodo de origen de la arista original, edge_tonode el nodo de destino de la arista original, perc es el porcentaje sobre la arista original (edge_fromnode, edge_tonode) del nuevo nodo virtual.

Hace una semana (9-1-2012) el boletín de pgrouting también tocó este tema. Ver: Pgrouting-users Digest, Vol 40, Issue 2 -> http://lists.osgeo.org/pipermail/pgrouting-users/2012-January/000927.html

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