El algoritmo, que parte de dos puntos que se desean conectar, se divide en dos pasos:
Paso 1. Se genera un frente de onda partiendo del punto origen de la ruta hasta tocar al punto destino. Este frente de onda se va extendiendo por la malla mediante un recorrido en amplitud marcando los puntos por los que va pasando y asignándoles valores cada vez mayores a medida que el frente de onda se aleja del punto origen.
A continuación puede verse cómo se propagaría el frente de onda desde el punto $o=(5, 5)$ y llega hasta el punto $d=(9, 9)$ sobre una malla de 11x11.
0 10 9 8 7 6 7 8 9 10 0
10 9 8 7 6 5 6 7 8 9 10
9 8 7 6 5 4 5 6 7 8 9
8 7 6 5 4 3 4 5 6 7 8
7 6 5 4 3 2 3 4 5 6 7
6 5 4 3 2 o1 2 3 4 5 6
7 6 5 4 3 2 3 4 5 6 7
8 7 6 5 4 3 4 5 6 7 8
9 8 7 6 5 4 5 6 7 8 9
0 9 8 7 6 5 6 7 8 d9 10
0 0 9 8 7 6 7 8 9 10 0
Paso 2. Se genera la ruta partiendo del punto destino y volviendo hacia atrás sobre las marcas generadas por el frente de onda de tal forma que cada punto sólo se conecta con otro que tenga una marca con un valor menor. Así hasta llegar al punto origen.
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0
En pseudocódigo sería algo así:
Entrada:
M : Malla de puntos en la que cada punto tiene una marca (número) y un trazo
origen : Punto origen de la malla
destino: Punto destino de la malla
Salida:
La misma malla M con los puntos trazados uniendo origen con destino
Algoritmo:
cola := {}
meter(cola, origen)
poner todas las marcas de la malla a 0
poner_marca(M, origen, 1)
hacer
p := sacar(cola)
para cada punto q de M vecino de p, no marcado, ni trazado hacer
meter(cola, q)
poner_marca(M, q, obtener_marca(M, p) + 1)
fin para
fin hacer mientras ((cola no vacía) y (p != destino))
si (p == destino)
p := destino
poner_trazo(M, p)
mientras (p != origen) hacer
aux := punto de la vecindad de p con marca inferior a p y más cercano a origen
poner_trazo(M, aux)
p := aux
fin mientras
en otro caso
error: no hay ruta desde origen a destino
fin si
En la sección soft de la web puede descargarse una implementación en C++ que he hecho de este algoritmo. Como se puede apreciar la mayor carga de complejidad computacional recae en la primera parte, encargada de la propagación del frente de onda ya que se trata de un recorrido en amplitud.
El código de ejemplo en C++ genera una malla de 11 por 11 puntos e intenta trazar sobre ella 6 rutas. Las 5 primeras rutas se trazan mientras que para el último par de puntos el algoritmo no encuentra una ruta válida.
tracing from (5, 5) to (9, 9)... ok
tracing from (5, 10) to (9, 3)... ok
tracing from (0, 10) to (10, 6)... ok
tracing from (1, 1) to (1, 1)... ok
tracing from (0, 1) to (2, 1)... ok
tracing from (6, 8) to (3, 2)... no route found
output grid:
5 5 5 0 0 0 0 0 0 0 0
5 4 5 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 3 3 3
0 0 0 0 0 0 0 3 3 2 3
0 0 0 0 3 3 3 3 0 2 3
0 0 0 0 3 1 1 0 0 2 3
0 0 0 0 3 0 1 1 0 2 3
0 0 0 3 3 0 0 1 1 2 2
0 0 3 3 0 0 0 0 1 1 2
0 3 3 0 0 0 0 0 0 1 2
3 3 0 0 0 2 2 2 2 2 2
Como se puede ver es un algoritmo muy útil para el trazado automático de circuitos impresos.
Efectivamente, como indicas al final, entiendo que el frente de onda debe propagarse en todas direcciones: aunque el destino esté a tu izquierda, es posible que el único camino posible te obligue a irte a la derecha un poco. Todo dependerá del resto de rutas que ya están ocupando la malla.
Gracias por comentar y por avisar del spam.
Sin haber probado el programa, ¿el "frente de onda" debe cubrir toda la malla o por ejemplo se puede evitar evaluar celdas a la izquierda del origen si el destino está a la derecha? Supongo que en la realidad puede haber huecos y que por eso hay que evaluar todas las rutas posibles.
Lo sentimos. No se permiten nuevos comentarios después de 90 días.