Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / ShortestPathSolverAStar.java @ 30907

History | View | Annotate | Download (8.83 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.GlobalCounter;
47
import org.gvsig.graph.core.GraphException;
48
import org.gvsig.graph.core.GvConnector;
49
import org.gvsig.graph.core.GvEdge;
50
import org.gvsig.graph.core.GvFlag;
51
import org.gvsig.graph.core.GvNode;
52
import org.gvsig.graph.core.GvTurn;
53
import org.gvsig.graph.core.IGraph;
54

    
55
/**
56
 * @author fjp Este es ?til solo cuando podemos calcular la distancia estimada
57
 *         entre 2 nodos. (Es decir, para temas de cartograf?a). Para analizar
58
 *         relaciones creo que no servir?a).
59
 */
60
public class ShortestPathSolverAStar extends AbstractShortestPathSolver {
61

    
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
                GvFlag fFrom = flags[0];
75
                fFrom.setCost(0);
76
                for (int i = 0; i < flags.length - 1; i++) {
77
                        fFrom = flags[desde];
78
                        GvFlag fTo = flags[hasta];
79

    
80
                        if (fFrom != fTo) {
81
                                int idStart = net.creaArcosVirtuales(fFrom);
82
                                int idStop = net.creaArcosVirtuales(fTo);
83

    
84
                                long tA1= System.currentTimeMillis();
85
                                double newCost = AStar(idStart, idStop);
86
                                long tA2= System.currentTimeMillis();
87
                                System.out.println("T Astar = " + (tA2-tA1));
88
                                
89
                                elCoste1 += newCost;
90
                                fTo.setCost(elCoste1);
91

    
92
                                if (newCost != Double.MAX_VALUE) {
93
                                        try {
94
                                                long t1 = System.currentTimeMillis();
95
                                                populateRoute(fFrom, fTo, idStart, idStop);
96
                                                long t2 = System.currentTimeMillis();
97
                                                System.out.println("T populateRoute=" + (t2-t1));
98
                                        } catch (BaseException e) {
99
                                                e.printStackTrace();
100
                                                throw new GraphException(e);
101
                                        }
102
                                } else {
103
                                        // No way
104
                                }
105

    
106
                                net.reconstruyeTramo(fFrom.getIdArc());
107
                                net.reconstruyeTramo(fTo.getIdArc());
108
                                desde = hasta;
109
                        } // if son puntos distintos
110
                        hasta++;
111
                }
112

    
113
                return route;
114
        }
115

    
116
        private double AStar(int idStart, int idStop) {
117
                int nodeNum;
118
                int linkNum;
119
                double newCost;
120
                int idSiguienteNodo;
121
                GvNode node, toNode, finalNode, bestNode; // , *pNodoProv;
122
                GvEdge link;
123
                boolean bExit = false;
124

    
125
                boolean bGiroProhibido;
126
                ArrayList candidatos = new ArrayList();
127

    
128
                // char Mensaje[200];
129

    
130
                IGraph graph = net.getGraph();
131

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

    
147
                candidatos.clear();
148
                // A?adimos el Start Node a la lista de candidatosSTL
149
                // Nodo final
150
                finalNode = graph.getNodeByID(idStop);
151
                finalNode.initialize();
152

    
153
                node = graph.getNodeByID(idStart);
154
                node.initialize();
155
                bestNode = node;
156

    
157
                candidatos.add(node);
158
                node.setCostZero();
159
                node.setStatus(GvNode.statNowInList);
160
                node.calculateStimation(finalNode, 0);
161

    
162
                // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
163
                // Nodos
164
                double bestStimation;
165

    
166
                while ((!bExit) && (candidatos.size() > 0)) {
167
                        // Buscamos el nodo con m?nimo coste
168
                        node = (GvNode) candidatos.get(0);
169
                        bestNode = node;
170
                        bestStimation = node.getStimation();
171
                        for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
172
                                node = (GvNode) candidatos.get(nodeNum);
173
                                if (node.getStimation() < bestStimation) {
174
                                        bestStimation = node.getStimation();
175
                                        bestNode = node;
176
                                }
177
                        } // for nodeNum candidatosSTL
178

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

    
194
                        // sprintf(Mensaje,"Enlaces en el nodo %ld:
195
                        // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
196
                        // AfxMessageBox(Mensaje);
197

    
198
                        // A?adimos a la lista de candidatosSTL los vecinos del nodo que
199
                        // acabamos de borrar
200
                        // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
201
                        // SALEN.
202
//                        for (linkNum = 0; linkNum < node.getOutputLinks().size(); linkNum++) {
203
                        for (int iConec=0; iConec< node.getConnectors().size();  iConec++) {
204
                                // Pillamos el nodo vecino
205
                                GvConnector c = node.getConnectors().get(iConec);
206
                                if (c.getEdgeOut() == null) continue;
207
                                
208
                                link = (GvEdge) c.getEdgeOut();
209
                                // Pillamos el nodo vecino
210
//                                link = (GvEdge) node.getOutputLinks().get(linkNum);
211
                                idSiguienteNodo = link.getIdNodeEnd();
212
                                
213
                                // To avoid U-turn
214
                                if (c.getEdgeIn() != null)
215
                                        if (c.getFrom_link_c() == c.getEdgeIn().getIdEdge())
216
                                                continue;
217

    
218
                                toNode = graph.getNodeByID(idSiguienteNodo);
219
                                
220
                                // 27_5_2004
221
                                // Si un arco tiene coste negativo, lo ignoramos
222
                                if (link.getWeight() < 0)
223
                                        continue;
224

    
225
                                // Fin arco con coste negativo
226
//                                int from_link = c.getFrom_link_c();
227
//
228
//                                if (from_link != -1) {
229
//                                        if (c.getEdgeIn().getIdEdge() == from_link) continue; // No queremos entrar y salir
230
                                                                                                                                // por el mismo conector
231
                                // NUEVO: 26-7-2003: Comprobamos si est? inicializado
232
                                if (toNode.getNumSoluc() != GlobalCounter.getGlobalSolutionNumber()) {
233
                                        toNode.initialize();
234
                                } else {
235
                                        // System.out.println("Nodo ya inicializado");
236
                                }
237
                                // Miramos a ver si podemos mejorar su best_cost
238
//                                double costeGiro = 0;
239
//
240
//                                // Miramos la lista de Giros de ese nodo
241
//                                bGiroProhibido = false;
242
//                                if (from_link != -1) {
243
//                                        GvEdge edgeFrom = graph.getEdgeByID(from_link);
244
//                                        for (int idGiro=0; idGiro < node.getTurnCosts().size(); idGiro++)
245
//                                        {
246
//                                                // Si est? prohibido, a por otro
247
//                                                GvTurn elGiro = node.getTurnCosts().get(idGiro);
248
//                                                if ((elGiro.getIdArcFrom() == edgeFrom.getIdArc()) && 
249
//                                                        (elGiro.getIdArcTo() == link.getIdArc()))
250
//                                                {
251
//                                                        if (elGiro.getCost() < 0)
252
//                                                        {
253
//                                                                bGiroProhibido = true;
254
//                                                        }
255
//                                                        else
256
//                                                                costeGiro = elGiro.getCost();
257
//        
258
//                                                        // Para que pueda volver a entrar en los c?lculos
259
//                                                        node.setStatus(GvNode.statNotInList);
260
//                                                        break; // Salimos del for porque ya hemos encontrado el giro
261
//                                                }
262
//                                        }
263
//                                }
264
//                                // Si est? prohibido, vamos a por otro enlace
265
//                                if (bGiroProhibido)
266
//                                {
267
//                                        continue;                                        
268
//                                }
269
                                // TODO: REVISAR SI HAY QUE SUMAR EL COSTE DEL GIRO A NEWCOST
270
                                // Y SI LO DE TURNCOSTS NO DEBE IR EN EXISTEMEJORA
271

    
272
                                // Miramos a ver si podemos mejorar su best_cost
273
                                newCost = c.getBestCostOut() + link.getWeight();
274

    
275
                                // Change to take care of turn costs
276
                                if (toNode.existeMejora(link, newCost)) {  // Es una mejora, as? que actualizamos el vecino y
277
//                                        // lo a?adimos a los candidatosSTL
278
//                                        toNode.setBestCost(newCost);
279
//                                         
280
//                                        toNode.setFromLink(link.getIdEdge());
281

    
282
                                        toNode.calculateStimation(finalNode, newCost);
283

    
284
                                        if (toNode.getStatus() != GvNode.statNowInList) {
285
                                                toNode.setStatus(GvNode.statNowInList);
286
                                                candidatos.add(toNode);
287
                                        }
288
                                } // Si hay mejora
289

    
290
                        } // for linkNum
291
                } // while candidatosSTL
292

    
293
                newCost = finalNode.getBestCost();
294

    
295
                return newCost;
296
        }
297

    
298
}