root / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / ShortestPathSolverDijkstra.java @ 35157
History | View | Annotate | Download (7.65 KB)
1 | 8499 | fjp | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | 22182 | fpenarrubia | package org.gvsig.graph.solvers; |
42 | 8499 | fjp | |
43 | import java.util.ArrayList; |
||
44 | 35157 | fpenarrubia | import java.util.PriorityQueue; |
45 | 8499 | fjp | |
46 | 13583 | fjp | import org.gvsig.exceptions.BaseException; |
47 | 22182 | fpenarrubia | import org.gvsig.graph.core.AbstractNetSolver; |
48 | import org.gvsig.graph.core.GlobalCounter; |
||
49 | import org.gvsig.graph.core.GraphException; |
||
50 | 25339 | fpenarrubia | import org.gvsig.graph.core.GvConnector; |
51 | 22182 | fpenarrubia | import org.gvsig.graph.core.GvEdge; |
52 | import org.gvsig.graph.core.GvFlag; |
||
53 | import org.gvsig.graph.core.GvNode; |
||
54 | import org.gvsig.graph.core.GvTurn; |
||
55 | import org.gvsig.graph.core.IGraph; |
||
56 | 33741 | fpenarrubia | import org.gvsig.graph.solvers.pqueue.FibHeap; |
57 | 13583 | fjp | |
58 | import com.hardcode.gdbms.engine.data.driver.DriverException; |
||
59 | 8499 | fjp | |
60 | 25339 | fpenarrubia | public class ShortestPathSolverDijkstra extends AbstractShortestPathSolver { |
61 | 8499 | fjp | |
62 | /**
|
||
63 | * @return a list of features
|
||
64 | * @throws GraphException
|
||
65 | */
|
||
66 | public Route calculateRoute() throws GraphException { |
||
67 | GvFlag[] flags = net.getFlags();
|
||
68 | if (flags.length == 0) |
||
69 | throw new RuntimeException("Please, add flags before"); |
||
70 | int desde = 0; |
||
71 | int hasta = 1; |
||
72 | double elCoste1 = 0; |
||
73 | route = new Route();
|
||
74 | for (int i = 0; i < flags.length - 1; i++) { |
||
75 | GvFlag fFrom = flags[desde]; |
||
76 | GvFlag fTo = flags[hasta]; |
||
77 | |||
78 | if (fFrom != fTo) {
|
||
79 | int idStart = net.creaArcosVirtuales(fFrom);
|
||
80 | int idStop = net.creaArcosVirtuales(fTo);
|
||
81 | |||
82 | double newCost = dijkstra(idStart, idStop);
|
||
83 | elCoste1 += newCost; |
||
84 | |||
85 | if (newCost != Double.MAX_VALUE) |
||
86 | { |
||
87 | try {
|
||
88 | populateRoute(fFrom, fTo, idStart, idStop); |
||
89 | 13583 | fjp | } catch (BaseException e) {
|
90 | 8499 | fjp | e.printStackTrace(); |
91 | throw new GraphException(e); |
||
92 | } |
||
93 | } |
||
94 | else
|
||
95 | { |
||
96 | // No way
|
||
97 | } |
||
98 | |||
99 | net.reconstruyeTramo(fFrom.getIdArc()); |
||
100 | net.reconstruyeTramo(fTo.getIdArc()); |
||
101 | desde = hasta; |
||
102 | } // if son puntos distintos
|
||
103 | hasta++; |
||
104 | } |
||
105 | |||
106 | return route;
|
||
107 | } |
||
108 | |||
109 | private double dijkstra(int idStart, int idStop) { |
||
110 | int nodeNum;
|
||
111 | int linkNum;
|
||
112 | double newCost;
|
||
113 | int idSiguienteNodo;
|
||
114 | 33741 | fpenarrubia | GvNode node, toNode, finalNode;// , bestNode; // , *pNodoProv;
|
115 | 8499 | fjp | GvEdge link; |
116 | boolean bExit = false; |
||
117 | double bestCost;
|
||
118 | |||
119 | boolean bGiroProhibido;
|
||
120 | 33741 | fpenarrubia | // ArrayList candidatos = new ArrayList();
|
121 | 8499 | fjp | |
122 | 13583 | fjp | GvTurn theTurn; |
123 | 8499 | fjp | // char Mensaje[200];
|
124 | |||
125 | IGraph graph = net.getGraph(); |
||
126 | |||
127 | // NUEVO: 27-6-2003
|
||
128 | 13583 | fjp | // Cada nodo y cada arco llevan un numero de soluci?n. Se supone
|
129 | 8499 | fjp | // que si lo del nodo y el arco no coincide con
|
130 | // este numero, todav?a no ha sido inicializado y hay que hacerlo.
|
||
131 | // Para evitar coincidencias cuando de la vuelta el contador, cada
|
||
132 | // 65000 peticiones (por ejemplo), repasamos toda
|
||
133 | // la red y ponemos numSolucGlobal a -1
|
||
134 | 14780 | fpenarrubia | if (GlobalCounter.increment())
|
135 | { |
||
136 | 8499 | fjp | for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) { |
137 | node = graph.getNodeByID(nodeNum); |
||
138 | node.initialize(); |
||
139 | } // for nodeNum */
|
||
140 | } |
||
141 | |||
142 | 33741 | fpenarrubia | // candidatos.clear();
|
143 | 8499 | fjp | // A?adimos el Start Node a la lista de candidatosSTL
|
144 | // Nodo final
|
||
145 | finalNode = graph.getNodeByID(idStop); |
||
146 | finalNode.initialize(); |
||
147 | |||
148 | node = graph.getNodeByID(idStart); |
||
149 | node.initialize(); |
||
150 | 33741 | fpenarrubia | // bestNode = node;
|
151 | 8499 | fjp | |
152 | 33741 | fpenarrubia | // candidatos.add(node);
|
153 | 25339 | fpenarrubia | node.setCostZero(); |
154 | 8499 | fjp | node.setStatus(GvNode.statNowInList); |
155 | bestCost = Double.MAX_VALUE;
|
||
156 | 33741 | fpenarrubia | // Priority Queue
|
157 | 35157 | fpenarrubia | PriorityQueue<GvNode> pq = new PriorityQueue<GvNode>(); |
158 | pq.add(node); |
||
159 | 8499 | fjp | |
160 | // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
|
||
161 | // Nodos
|
||
162 | |||
163 | 35157 | fpenarrubia | while ((!bExit) && (!pq.isEmpty())) {
|
164 | 8499 | fjp | // Buscamos el nodo con m?nimo coste
|
165 | 33741 | fpenarrubia | // node = (GvNode) candidatos.get(0);
|
166 | // bestNode = node;
|
||
167 | // bestCost = node.getBestCost();
|
||
168 | // for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
|
||
169 | // node = (GvNode) candidatos.get(nodeNum);
|
||
170 | // if (node.getBestCost() < bestCost) {
|
||
171 | // bestCost = node.getBestCost();
|
||
172 | // bestNode = node;
|
||
173 | // }
|
||
174 | // } // for nodeNum candidatosSTL
|
||
175 | //
|
||
176 | //
|
||
177 | // node = bestNode;
|
||
178 | 35157 | fpenarrubia | node = pq.poll(); // get the lowest-weightSum Vertex 'u',
|
179 | 8499 | fjp | // Borramos el mejor nodo de la lista de candidatosSTL
|
180 | node.setStatus(GvNode.statWasInList); |
||
181 | // TODO: BORRAR POR INDEX, NO AS?. ES M?S LENTO QUE SI BORRAMOS EL i-?simo.
|
||
182 | 33741 | fpenarrubia | // candidatos.remove(node);
|
183 | 8499 | fjp | // System.out.println("LINK " + link.getIdArc() + " from ");
|
184 | // System.out.println("from " + idStart + " to " + finalNode.getIdNode() + ". node=" + node.getIdNode());
|
||
185 | // Miramos si hemos llegado donde quer?amos
|
||
186 | 33741 | fpenarrubia | if (node.getIdNode() == idStop) {
|
187 | 8499 | fjp | bExit = true;
|
188 | break;
|
||
189 | } |
||
190 | |||
191 | // sprintf(Mensaje,"Enlaces en el nodo %ld:
|
||
192 | // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
|
||
193 | // AfxMessageBox(Mensaje);
|
||
194 | |||
195 | // A?adimos a la lista de candidatosSTL los vecinos del nodo que
|
||
196 | // acabamos de borrar
|
||
197 | // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
|
||
198 | // SALEN.
|
||
199 | 25339 | fpenarrubia | // for (linkNum = 0; linkNum < node.getOutputLinks().size(); linkNum++) {
|
200 | for (int iConec=0; iConec< node.getConnectors().size(); iConec++) { |
||
201 | 8499 | fjp | // Pillamos el nodo vecino
|
202 | 25339 | fpenarrubia | GvConnector c = node.getConnectors().get(iConec); |
203 | if (c.getEdgeOut() == null) continue; |
||
204 | |||
205 | link = (GvEdge) c.getEdgeOut(); |
||
206 | // link = (GvEdge) node.getOutputLinks().get(linkNum);
|
||
207 | 8499 | fjp | idSiguienteNodo = link.getIdNodeEnd(); |
208 | 30891 | fpenarrubia | // To avoid U-turn
|
209 | 30907 | fpenarrubia | if (c.getEdgeIn() != null) |
210 | if (c.getFrom_link_c() == c.getEdgeIn().getIdEdge())
|
||
211 | continue;
|
||
212 | 8499 | fjp | |
213 | toNode = graph.getNodeByID(idSiguienteNodo); |
||
214 | |||
215 | // 27_5_2004
|
||
216 | // Si un arco tiene coste negativo, lo ignoramos
|
||
217 | if (link.getWeight() < 0) |
||
218 | continue;
|
||
219 | |||
220 | // Fin arco con coste negativo
|
||
221 | |||
222 | // NUEVO: 26-7-2003: Comprobamos si est? inicializado
|
||
223 | 14780 | fpenarrubia | if (toNode.getNumSoluc() != GlobalCounter.getGlobalSolutionNumber()) {
|
224 | 8499 | fjp | toNode.initialize(); |
225 | } |
||
226 | else
|
||
227 | { |
||
228 | // System.out.println("Nodo ya inicializado");
|
||
229 | } |
||
230 | |||
231 | // Miramos si ese nodo ya ha estado antes en la lista de
|
||
232 | // candidatos
|
||
233 | if (toNode.getStatus() != GvNode.statWasInList) {
|
||
234 | // Miramos a ver si podemos mejorar su best_cost
|
||
235 | 25339 | fpenarrubia | newCost = c.getBestCostOut() + link.getWeight(); |
236 | 8499 | fjp | |
237 | 25339 | fpenarrubia | // Change to take care of turn costs
|
238 | if (toNode.existeMejora(link, newCost)) { // Es una mejora, as? que actualizamos el vecino y |
||
239 | // // lo a?adimos a los candidatosSTL
|
||
240 | // toNode.setBestCost(newCost);
|
||
241 | //
|
||
242 | // toNode.setFromLink(link.getIdEdge());
|
||
243 | 31524 | fpenarrubia | double newLength = node.getAccumulatedLength() + link.getDistance();
|
244 | toNode.setAccumulatedLength(newLength); |
||
245 | 8499 | fjp | |
246 | 31524 | fpenarrubia | |
247 | 8499 | fjp | if (toNode.getStatus() != GvNode.statNowInList) {
|
248 | toNode.setStatus(GvNode.statNowInList); |
||
249 | 35157 | fpenarrubia | toNode.setStimation(newCost); |
250 | pq.add(toNode); |
||
251 | 33741 | fpenarrubia | //candidatos.add(toNode);
|
252 | 8499 | fjp | } |
253 | } // Si hay mejora
|
||
254 | } // if ese nodo no ha estado en la lista de candidatosSTL
|
||
255 | |||
256 | } // for linkNum
|
||
257 | } // while candidatosSTL
|
||
258 | |||
259 | newCost = finalNode.getBestCost(); |
||
260 | |||
261 | return newCost;
|
||
262 | } |
||
263 | |||
264 | } |