Statistics
| Revision:

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
}