Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / ShortestPathSolverDijkstra.java @ 31524

History | View | Annotate | Download (7.32 KB)

1
/* 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
package org.gvsig.graph.solvers;
42

    
43
import java.util.ArrayList;
44

    
45
import org.gvsig.exceptions.BaseException;
46
import org.gvsig.graph.core.AbstractNetSolver;
47
import org.gvsig.graph.core.GlobalCounter;
48
import org.gvsig.graph.core.GraphException;
49
import org.gvsig.graph.core.GvConnector;
50
import org.gvsig.graph.core.GvEdge;
51
import org.gvsig.graph.core.GvFlag;
52
import org.gvsig.graph.core.GvNode;
53
import org.gvsig.graph.core.GvTurn;
54
import org.gvsig.graph.core.IGraph;
55

    
56
import com.hardcode.gdbms.engine.data.driver.DriverException;
57

    
58
public class ShortestPathSolverDijkstra extends AbstractShortestPathSolver {
59
        
60
        /**
61
         * @return a list of features
62
         * @throws GraphException 
63
         */
64
        public Route calculateRoute() throws GraphException {
65
                GvFlag[] flags = net.getFlags();
66
                if (flags.length == 0)
67
                        throw new RuntimeException("Please, add flags before");
68
                int desde = 0;
69
                int hasta = 1;
70
                double elCoste1 = 0;
71
                route = new Route();
72
                for (int i = 0; i < flags.length - 1; i++) {
73
                        GvFlag fFrom = flags[desde];
74
                        GvFlag fTo = flags[hasta];
75

    
76
                        if (fFrom != fTo) {
77
                                int idStart = net.creaArcosVirtuales(fFrom);
78
                                int idStop = net.creaArcosVirtuales(fTo);
79

    
80
                                double newCost = dijkstra(idStart, idStop);
81
                                elCoste1 += newCost;
82

    
83
                                if (newCost != Double.MAX_VALUE)
84
                                {
85
                                        try {
86
                                                populateRoute(fFrom, fTo, idStart, idStop);
87
                                        } catch (BaseException e) {
88
                                                e.printStackTrace();
89
                                                throw new GraphException(e);
90
                                        }
91
                                }
92
                                else
93
                                {
94
                                        // No way
95
                                }
96

    
97
                                net.reconstruyeTramo(fFrom.getIdArc());
98
                                net.reconstruyeTramo(fTo.getIdArc());
99
                                desde = hasta;
100
                        } // if son puntos distintos
101
                        hasta++;
102
                }
103

    
104
                return route;
105
        }
106

    
107
        private double dijkstra(int idStart, int idStop) {
108
                int nodeNum;
109
                int linkNum;
110
                double newCost;
111
                int idSiguienteNodo;
112
                GvNode node, toNode, finalNode, bestNode; // , *pNodoProv;
113
                GvEdge link;
114
                boolean bExit = false;
115
                double bestCost;
116

    
117
                boolean bGiroProhibido;
118
                ArrayList candidatos = new ArrayList();
119

    
120
                GvTurn theTurn;
121
                // char Mensaje[200];
122
                
123
                IGraph graph = net.getGraph();
124

    
125
                // NUEVO: 27-6-2003
126
                // Cada nodo y cada arco llevan un numero de soluci?n. Se supone
127
                // que si lo del nodo y el arco no coincide con
128
                // este numero, todav?a no ha sido inicializado y hay que hacerlo.
129
                // Para evitar coincidencias cuando de la vuelta el contador, cada
130
                // 65000 peticiones (por ejemplo), repasamos toda
131
                // la red y ponemos numSolucGlobal a -1
132
                if (GlobalCounter.increment())
133
                {
134
                        for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) {
135
                                node = graph.getNodeByID(nodeNum);
136
                                node.initialize();
137
                        } // for nodeNum */
138
                }
139

    
140
                candidatos.clear();
141
                // A?adimos el Start Node a la lista de candidatosSTL
142
                // Nodo final
143
                finalNode = graph.getNodeByID(idStop);
144
                finalNode.initialize();
145

    
146
                node = graph.getNodeByID(idStart);
147
                node.initialize();
148
                bestNode = node;
149

    
150
                candidatos.add(node);
151
                node.setCostZero();
152
                node.setStatus(GvNode.statNowInList);
153
                bestCost = Double.MAX_VALUE;
154

    
155
                // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
156
                // Nodos
157

    
158
                while ((!bExit) && (candidatos.size() > 0)) {
159
                        // Buscamos el nodo con m?nimo coste
160
                        node = (GvNode) candidatos.get(0);
161
                        bestNode = node;
162
                        bestCost = node.getBestCost();
163
                        for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
164
                                node = (GvNode) candidatos.get(nodeNum);
165
                                if (node.getBestCost() < bestCost) {
166
                                        bestCost = node.getBestCost();
167
                                        bestNode = node;
168
                                }
169
                        } // for nodeNum candidatosSTL
170

    
171
                        node = bestNode;
172
                        // Borramos el mejor nodo de la lista de candidatosSTL
173
                        node.setStatus(GvNode.statWasInList);
174
                        // TODO: BORRAR POR INDEX, NO AS?. ES M?S LENTO QUE SI BORRAMOS EL i-?simo.
175
                        candidatos.remove(node);
176
                        // System.out.println("LINK " + link.getIdArc() + " from ");
177
                        // System.out.println("from " + idStart + " to " + finalNode.getIdNode() + ". node=" + node.getIdNode());
178
                        // Miramos si hemos llegado donde quer?amos
179
                        if (bestNode.getIdNode() == idStop) {
180
                                bExit = true;
181
                                break;
182
                        }
183

    
184
                        // sprintf(Mensaje,"Enlaces en el nodo %ld:
185
                        // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
186
                        // AfxMessageBox(Mensaje);
187

    
188
                        // A?adimos a la lista de candidatosSTL los vecinos del nodo que
189
                        // acabamos de borrar
190
                        // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
191
                        // SALEN.
192
//                        for (linkNum = 0; linkNum < node.getOutputLinks().size(); linkNum++) {
193
                        for (int iConec=0; iConec< node.getConnectors().size();  iConec++) {
194
                                // Pillamos el nodo vecino
195
                                GvConnector c = node.getConnectors().get(iConec);
196
                                if (c.getEdgeOut() == null) continue;
197
                                
198
                                link = (GvEdge) c.getEdgeOut();
199
//                                link = (GvEdge) node.getOutputLinks().get(linkNum);
200
                                idSiguienteNodo = link.getIdNodeEnd();
201
                                // To avoid U-turn
202
                                if (c.getEdgeIn() != null)
203
                                        if (c.getFrom_link_c() == c.getEdgeIn().getIdEdge())
204
                                                continue;
205

    
206
                                toNode = graph.getNodeByID(idSiguienteNodo);
207

    
208
                                // 27_5_2004
209
                                // Si un arco tiene coste negativo, lo ignoramos
210
                                if (link.getWeight() < 0)
211
                                        continue;
212

    
213
                                // Fin arco con coste negativo
214

    
215
                                // NUEVO: 26-7-2003: Comprobamos si est? inicializado
216
                                if (toNode.getNumSoluc() != GlobalCounter.getGlobalSolutionNumber()) {
217
                                        toNode.initialize();
218
                                }
219
                                else
220
                                {
221
                                        // System.out.println("Nodo ya inicializado");
222
                                }
223

    
224
                                // Miramos si ese nodo ya ha estado antes en la lista de
225
                                // candidatos
226
                                if (toNode.getStatus() != GvNode.statWasInList) {
227
                                        // Miramos a ver si podemos mejorar su best_cost
228
                                        newCost = c.getBestCostOut() + link.getWeight();
229

    
230
                                        // Change to take care of turn costs
231
                                        if (toNode.existeMejora(link, newCost)) {  // Es una mejora, as? que actualizamos el vecino y
232
//                                                // lo a?adimos a los candidatosSTL
233
//                                                toNode.setBestCost(newCost);
234
//                                                 
235
//                                                toNode.setFromLink(link.getIdEdge());
236
                                                double newLength = node.getAccumulatedLength() + link.getDistance();
237
                                                toNode.setAccumulatedLength(newLength);
238

    
239

    
240
                                                if (toNode.getStatus() != GvNode.statNowInList) {
241
                                                        toNode.setStatus(GvNode.statNowInList);
242
                                                        candidatos.add(toNode);
243
                                                }
244
                                        } // Si hay mejora
245
                                } // if ese nodo no ha estado en la lista de candidatosSTL
246

    
247
                        } // for linkNum
248
                } // while candidatosSTL
249

    
250
                newCost = finalNode.getBestCost();
251

    
252
                return newCost;
253
        }
254

    
255
}