Statistics
| Revision:

root / tags / PilotoRedes_Build_4 / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / solvers / OneToManySolver.java @ 12191

History | View | Annotate | Download (11 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 com.iver.cit.gvsig.graph.solvers;
42

    
43
import java.util.ArrayList;
44

    
45
import com.iver.cit.gvsig.graph.GraphException;
46
import com.iver.cit.gvsig.graph.core.AbstractNetSolver;
47
import com.iver.cit.gvsig.graph.core.GvEdge;
48
import com.iver.cit.gvsig.graph.core.GvFlag;
49
import com.iver.cit.gvsig.graph.core.GvNode;
50
import com.iver.cit.gvsig.graph.core.IGraph;
51

    
52
public class OneToManySolver extends AbstractNetSolver {
53

    
54
        private int idStart = -1;
55
        private ArrayList idStops = null;
56
        
57
        private class StopAux {
58
                public StopAux(Integer idStop2) {
59
                        idStop = idStop2;
60
                        bFound = false;
61
                }
62
                private Integer idStop;
63
                private boolean bFound;
64
                public boolean isFound() {
65
                        return bFound;
66
                }
67
                public void setFound(boolean found) {
68
                        bFound = found;
69
                }
70
                public Integer getIdStop() {
71
                        return idStop;
72
                }
73
        }
74
        
75
        private GvFlag sourceFlag;
76
        
77

    
78
        
79
        /**
80
         * We have this method separated from calculate to speed up odmatrix calculations.
81
         * The developer can position flags once, and call calculate only changing source
82
         * (idStart). This way, destination flags are positionned only once.
83
         * @throws GraphException
84
         */
85
        public void putDestinationsOnNetwork() throws GraphException
86
        {
87
                GvFlag[] flags = net.getFlags(); // Destinations
88
                
89
                if (flags.length == 0)
90
                        throw new RuntimeException("Please, add flags before");
91
                
92
                idStops = new ArrayList();
93
                for (int i = 0; i < flags.length; i++) {
94
                        GvFlag fTo = flags[i];
95

    
96
                        int idStop = net.creaArcosVirtuales(fTo);
97
                        idStops.add(new Integer(idStop));
98
                }
99
                
100
        }
101
        public void removeDestinationsFromNetwork()
102
        {
103
                GvFlag[] flags = net.getFlags(); // Destinations
104
                for (int i = 0; i < flags.length; i++)
105
                {
106
                        GvFlag fTo = flags[i];
107
                        net.reconstruyeTramo(fTo.getIdArc());                        
108
                }
109
                
110
        }
111
        /**
112
         * @throws GraphException 
113
         */
114
        public void calculate() throws GraphException {
115
                if (idStops == null)
116
                {
117
                        throw new RuntimeException("Please, call putDestinationsOnNetwork before calculate()");
118
                }
119
                GvFlag[] flags = net.getFlags(); // Destinations
120
                idStart = net.creaArcosVirtuales(sourceFlag);
121
                dijkstra(idStart, idStops);
122
                
123
                IGraph graph = net.getGraph();
124
                for (int i = 0; i < flags.length; i++)
125
                {
126
                        GvFlag fTo = flags[i];
127
                        Integer auxId = (Integer) idStops.get(i);
128
                        GvNode auxNode = graph.getNodeByID(auxId.intValue());
129
//                        System.out.println("Asigno bestCost = " + auxNode.getBestCost());
130
                        if (auxNode.getBestCost() == Double.MAX_VALUE)
131
                        {
132
                                fTo.setCost(-1);
133
                                fTo.setAccumulatedLength(-1);
134
                        }
135
                        else
136
                        {
137
                                fTo.setCost(auxNode.getBestCost());
138
                                fTo.setAccumulatedLength(auxNode.getAccumulatedLength());                                
139
                        }
140
                }
141
                
142
                // TODO: No podemos reconstruir el tramo porque perdemos la conectividad
143
                // con el resto de destinos.
144
//                net.reconstruyeTramo(sourceFlag.getIdArc());
145
        }
146

    
147

    
148
        private void dijkstra(int idStart, ArrayList stops) {
149
                int nodeNum;
150
                int linkNum;
151
                double newCost;
152
                int idSiguienteNodo;
153
                GvNode node, toNode, bestNode; // , *pNodoProv;
154
                GvEdge link;
155
                boolean bExit = false;
156
                double bestCost;
157

    
158
                boolean bGiroProhibido;
159
                // List clonedStops = Collections.synchronizedList(stops);
160
                ArrayList clonedStops = new ArrayList();
161
                for (int i=0; i < stops.size(); i++)
162
                {
163
                        Integer idStop = (Integer) stops.get(i);
164
                        clonedStops.add(new StopAux(idStop));
165
                }
166
                ArrayList candidatos = new ArrayList();
167

    
168
//                GvTurn elGiro;
169
                // char Mensaje[200];
170
                
171
                IGraph graph = net.getGraph();
172

    
173
                // NUEVO: 27-6-2003
174
                // Cada nodo y cada arco llevan un nuemero de soluci?n. Se supone
175
                // que si lo del nodo y el arco no coincide con
176
                // este numero, todav?a no ha sido inicializado y hay que hacerlo.
177
                // Para evitar coincidencias cuando de la vuelta el contador, cada
178
                // 65000 peticiones (por ejemplo), repasamos toda
179
                // la red y ponemos numSolucGlobal a -1
180
                if (numSolucGlobal > 65000) {
181
                        numSolucGlobal = -1;
182

    
183
                        for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) {
184
                                node = graph.getNodeByID(nodeNum);
185
                                node.initialize();
186
                        } // for nodeNum */
187

    
188
                }
189
                numSolucGlobal++;
190

    
191
                candidatos.clear();
192
                // A?adimos el Start Node a la lista de candidatosSTL
193
                // Nodos finales
194
                for (int h=0; h < clonedStops.size(); h++)
195
                {
196
                        StopAux auxStop = (StopAux) clonedStops.get(h);
197
                        int idStop = auxStop.getIdStop().intValue();
198
                
199
                        GvNode auxNode = graph.getNodeByID(idStop);
200
                        auxNode.initialize();
201
                }
202
                node = graph.getNodeByID(idStart);
203
                node.initialize();
204
                bestNode = node;
205

    
206
                candidatos.add(node);
207
                node.setBestCost(0);
208
                node.setStatus(GvNode.statNowInList);
209
                bestCost = Double.MAX_VALUE;
210

    
211
                // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
212
                // Nodos
213
                int stopActual = 0;
214

    
215
                while ((!bExit) && (candidatos.size() > 0)) {
216
                        // Buscamos el nodo con m?nimo coste
217
                        node = (GvNode) candidatos.get(0);
218
                        bestNode = node;
219
                        bestCost = node.getBestCost();
220
                        for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
221
                                node = (GvNode) candidatos.get(nodeNum);
222
                                if (node.getBestCost() < bestCost) {
223
                                        bestCost = node.getBestCost();
224
                                        bestNode = node;
225
                                }
226
                        } // for nodeNum candidatosSTL
227

    
228
                        node = bestNode;
229
                        // Borramos el mejor nodo de la lista de candidatosSTL
230
                        node.setStatus(GvNode.statWasInList);
231
                        // TODO: BORRAR POR INDEX, NO AS?. ES M?S LENTO QUE SI BORRAMOS EL i-?simo.
232
                        candidatos.remove(node);
233
                        // System.out.println("LINK " + link.getIdArc() + " from ");
234
                        // System.out.println("from " + idStart + " to " + finalNode.getIdNode() + ". node=" + node.getIdNode());
235
                        // Miramos si hemos llegado donde quer?amos
236
                        StopAux auxStop = (StopAux) clonedStops.get(stopActual);
237
                        int idStop = auxStop.getIdStop().intValue();
238
                        
239
                        if (bestNode.getIdNode() == idStop) {
240
                                // Hemos llegado a ese punto. Miramos el resto de puntos destino
241
                                // a ver si ya hemos pasado por alguno de ellos.
242
                                // Si con algun punto no pasamos por aqu?, no habremos llegado a ese punto.
243
                                // No importa, puede que al resto s?, y esos nodos a los que s? hemos llegado
244
                                // tendr?n bien rellenado el coste.
245
                                auxStop.setFound(true);
246
                                for (int i=stopActual; i < clonedStops.size(); i++)
247
                                {
248
                                        auxStop = (StopAux) clonedStops.get(i);
249
                                        if (!auxStop.isFound())
250
                                        {
251
                                                Integer id = auxStop.getIdStop();
252
        
253
                                                GvNode auxNode = graph.getNodeByID(id.intValue());
254
                                                if (auxNode.getStatus() == GvNode.statWasInList)
255
                                                {
256
                                                        auxStop.setFound(true);
257
                                                }
258
                                                else
259
                                                {
260
                                                        stopActual = i;
261
                                                        break;
262
                                                }
263
                                        }
264
                                }                                                
265
                                if (clonedStops.size() == 0)
266
                                {
267
                                        bExit = true;
268
                                        break; // Ya hemos llegado a todos los nodos
269
                                }                                
270
                        }
271
                        // sprintf(Mensaje,"Enlaces en el nodo %ld:
272
                        // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
273
                        // AfxMessageBox(Mensaje);
274

    
275
                        // A?adimos a la lista de candidatosSTL los vecinos del nodo que
276
                        // acabamos de borrar
277
                        // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
278
                        // SALEN.
279
                        for (linkNum = 0; linkNum < node.getEnlaces().size(); linkNum++) {
280
                                // Pillamos el nodo vecino
281
                                link = (GvEdge) node.getEnlaces().get(linkNum);
282
                                idSiguienteNodo = link.getIdNodeEnd();
283

    
284
                                toNode = graph.getNodeByID(idSiguienteNodo);
285

    
286
                                // 27_5_2004
287
                                // Si un arco tiene coste negativo, lo ignoramos
288
                                if (link.getWeight() < 0)
289
                                        continue;
290

    
291
                                // Fin arco con coste negativo
292

    
293
                                // NUEVO: 26-7-2003: Comprobamos si est? inicializado
294
                                if (toNode.getNumSoluc() != numSolucGlobal) {
295
                                        toNode.initialize();
296
                                }
297
                                else
298
                                {
299
                                        // System.out.println("Nodo ya inicializado");
300
                                }
301

    
302
                                // Miramos si ese nodo ya ha estado antes en la lista de
303
                                // candidatos
304
                                if (toNode.getStatus() != GvNode.statWasInList) {
305
                                        // Miramos a ver si podemos mejorar su best_cost
306
                                        newCost = node.getBestCost() + link.getWeight();
307
                                        
308

    
309
                                        // Miramos la lista de Giros de ese nodo
310
                                        bGiroProhibido = false;
311
                                        for (int idGiro = 0; idGiro < node.getTurns().size(); idGiro++) {
312
                                                // Si est? prohibido, a por otro
313
//                                                elGiro = (GvTurn) node.getTurns().get(idGiro);
314
                                                // TODO: HABILITAR ESTO
315
                                                // if ((elGiro.idTramoOrigen ==
316
                                                // Arcos[pNodo->from_link].idTramo) &&
317
                                                // (elGiro.idTramoDestino == pEnlace->idTramo))
318
                                                // {
319
                                                // if (elGiro.cost < 0)
320
                                                // {
321
                                                // bGiroProhibido = true;
322
                                                // // No podemos inicializar por completo el nodo porque
323
                                                // entonces
324
                                                // // perdemos el fromLink (el arco desde donde hemos
325
                                                // llegado hasta
326
                                                // // este nodo, que es necesario para calcular los
327
                                                // costes y generar
328
                                                // // el shape recorriendo hacia atr?s el camino
329
                                                // realizado.
330
                                                // // Si hab?a m?s de un nodo con costes prohibidos,
331
                                                // cab?a la posibilidad
332
                                                // // de que perdieramos este enlace.
333
                                                //                                                                        
334
                                                // // Para que pueda volver a entrar en c?lculos
335
                                                // pNodo->status = statNotInList;
336
                                                // pNodo->best_cost = INFINITO;
337
                                                //
338
                                                // }
339
                                                // else
340
                                                // newCost += elGiro.cost;
341
                                                // break; // Salimos del for porque ya hemos encontrado
342
                                                // el giro
343
                                                // }
344
                                        }
345
                                        // Si est? prohibido, vamos a por otro enlace, PERO
346
                                        // MARCAMOS EL NODO
347
                                        // COMO NO VISITADO PARA QUE PUEDA VOLVER A ENTRAR EN LA
348
                                        // LISTA DE CANDIDATOS
349
                                        // SI VENIMOS POR OTRO LADO.
350
                                        if (bGiroProhibido) {
351
                                                continue;
352
                                        }
353

    
354
                                        if (newCost < toNode.getBestCost()) {
355
                                                // Es una mejora, as? que actualizamos el vecino y
356
                                                // lo a?adimos a los candidatosSTL
357
                                                toNode.setBestCost(newCost);
358
                                                double newLength = node.getAccumulatedLength() + link.getDistance();
359
                                                toNode.setAccumulatedLength(newLength);
360
                                                toNode.setFromLink(link.getIdEdge());
361

    
362
                                                if (toNode.getStatus() != GvNode.statNowInList) {
363
                                                        toNode.setStatus(GvNode.statNowInList);
364
                                                        candidatos.add(toNode);
365
                                                }
366
                                        } // Si hay mejora
367
                                } // if ese nodo no ha estado en la lista de candidatosSTL
368

    
369
                        } // for linkNum
370
                } // while candidatosSTL
371

    
372
        }
373

    
374

    
375
        public GvFlag getSourceFlag() {
376
                return sourceFlag;
377
        }
378

    
379

    
380
        public void setSourceFlag(GvFlag sourceFlag) {
381
                this.sourceFlag = sourceFlag;
382
                
383
        }
384

    
385
}