Statistics
| Revision:

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

History | View | Annotate | Download (12.3 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
import java.util.Stack;
45

    
46
import org.gvsig.exceptions.BaseException;
47
import org.gvsig.graph.core.AbstractNetSolver;
48
import org.gvsig.graph.core.GlobalCounter;
49
import org.gvsig.graph.core.GraphException;
50
import org.gvsig.graph.core.GvConnector;
51
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.IGraph;
55
import org.gvsig.graph.core.InfoShp;
56
import org.gvsig.graph.core.NetworkUtils;
57

    
58
import com.iver.cit.gvsig.fmap.core.IFeature;
59
import com.iver.cit.gvsig.fmap.core.IGeometry;
60
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
61
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
62
import com.vividsolutions.jts.geom.Coordinate;
63
import com.vividsolutions.jts.geom.Geometry;
64
import com.vividsolutions.jts.geom.GeometryFactory;
65
import com.vividsolutions.jts.geom.LineString;
66
import com.vividsolutions.jts.geom.MultiLineString;
67

    
68

    
69
public class OneToManySolver extends AbstractNetSolver {
70

    
71
        protected int idStart = -1;
72
        protected ArrayList idStops = null;
73
        
74
        // Soporte listeners
75
        protected ArrayList<IDijkstraListener> listeners = new ArrayList<IDijkstraListener>();
76
        
77
        public void addListener(IDijkstraListener listener) {
78
                listeners.add(listener);
79
        }
80
        protected boolean callMinimumCostNodeSelectedListeners(GvNode node) {
81
                for (IDijkstraListener listener : listeners) {
82
                        if (listener.minimumCostNodeSelected(node))
83
                                return true;
84
                }
85
                return false;
86
        }
87
        protected boolean callAdjacenteEdgeVisitedListeners(GvNode fromNode, GvEdge edge) {
88
                for (IDijkstraListener listener : listeners) {
89
                        if (listener.adjacentEdgeVisited(fromNode, edge))
90
                                return true;
91
                }
92
                return false;
93
        }
94
        
95
        protected class StopAux {
96
                public StopAux(Integer idStop2) {
97
                        idStop = idStop2;
98
                        bFound = false;
99
                }
100
                private Integer idStop;
101
                private boolean bFound;
102
                public boolean isFound() {
103
                        return bFound;
104
                }
105
                public void setFound(boolean found) {
106
                        bFound = found;
107
                }
108
                public Integer getIdStop() {
109
                        return idStop;
110
                }
111
        }
112
        
113
        protected GvFlag sourceFlag;
114
        protected boolean bExploreAll = false; // by default
115
        protected double maxCost = Double.MAX_VALUE;
116
        protected double maxDistance = Double.MAX_VALUE;
117
        protected GvFlag[] destinations;
118
        protected Route route = new Route();
119
        
120

    
121
        
122
        /**
123
         * We have this method separated from calculate to speed up odmatrix calculations.
124
         * The developer can position flags once, and call calculate only changing source
125
         * (idStart). This way, destination flags are positionned only once.
126
         * @throws GraphException
127
         */
128
        public void putDestinationsOnNetwork(GvFlag[] flags) throws GraphException
129
        {
130
//                GvFlag[] flags = net.getFlags(); // Destinations
131
                
132
                if (flags.length == 0)
133
                        throw new RuntimeException("Please, add flags before");
134
                
135
                idStops = new ArrayList();
136
                for (int i = 0; i < flags.length; i++) {
137
                        GvFlag fTo = flags[i];
138

    
139
                        int idStop = net.creaArcosVirtuales(fTo);
140
                        idStops.add(new Integer(idStop));
141
                }
142
                destinations = flags;
143
                
144
        }
145
        public void removeDestinationsFromNetwork(GvFlag[] flags)
146
        {
147
//                GvFlag[] flags = net.getFlags(); // Destinations
148
                if (sourceFlag != null)
149
                        net.reconstruyeTramo(sourceFlag.getIdArc());
150
                for (int i = 0; i < flags.length; i++)
151
                {
152
                        GvFlag fTo = flags[i];
153
                        net.reconstruyeTramo(fTo.getIdArc());                        
154
                }
155
                
156
        }
157
        /**
158
         * @throws GraphException 
159
         */
160
        public void calculate() throws GraphException {
161
                if (idStops == null)
162
                {
163
                        throw new RuntimeException("Please, call putDestinationsOnNetwork before calculate()");
164
                }
165
//                destinations = net.getFlags();
166
                idStart = net.creaArcosVirtuales(sourceFlag);
167
                dijkstra(idStart, idStops);
168
                
169
                IGraph graph = net.getGraph();
170
                for (int i = 0; i < destinations.length; i++)
171
                {
172
                        GvFlag fTo = destinations[i];
173
                        Integer auxId = (Integer) idStops.get(i);
174
                        GvNode auxNode = graph.getNodeByID(auxId.intValue());
175
//                        System.out.println("Asigno bestCost = " + auxNode.getBestCost());
176
                        if (auxNode.getBestCost() == Double.MAX_VALUE)
177
                        {
178
                                fTo.setCost(-1);
179
                                fTo.setAccumulatedLength(-1);
180
                        }
181
                        else
182
                        {
183
                                fTo.setCost(auxNode.getBestCost());
184
                                fTo.setAccumulatedLength(auxNode.getAccumulatedLength());                                
185
                        }
186
                }
187
                
188
                // TODO: No podemos reconstruir el tramo porque perdemos la conectividad
189
                // con el resto de destinos.
190
//                net.reconstruyeTramo(sourceFlag.getIdArc());
191
        }
192

    
193

    
194
        private void dijkstra(int idStart, ArrayList stops) {
195
                int nodeNum;
196
                int linkNum;
197
                double newCost;
198
                int idSiguienteNodo;
199
                GvNode node, toNode, bestNode; // , *pNodoProv;
200
                GvEdge link;
201
                boolean bExit = false;
202
                double bestCost;
203

    
204
                boolean bGiroProhibido;
205
                // List clonedStops = Collections.synchronizedList(stops);
206
                ArrayList clonedStops = new ArrayList();
207
                for (int i=0; i < stops.size(); i++)
208
                {
209
                        Integer idStop = (Integer) stops.get(i);
210
                        clonedStops.add(new StopAux(idStop));
211
                }
212
                ArrayList candidatos = new ArrayList();
213

    
214
//                GvTurn elGiro;
215
                // char Mensaje[200];
216
                
217
                IGraph graph = net.getGraph();
218

    
219
                // NUEVO: 27-6-2003
220
                // Cada nodo y cada arco llevan un nuemero de soluci?n. Se supone
221
                // que si lo del nodo y el arco no coincide con
222
                // este numero, todav?a no ha sido inicializado y hay que hacerlo.
223
                // Para evitar coincidencias cuando de la vuelta el contador, cada
224
                // 65000 peticiones (por ejemplo), repasamos toda
225
                // la red y ponemos numSolucGlobal a -1
226
                if (GlobalCounter.increment())
227
                {
228
                        for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) {
229
                                node = graph.getNodeByID(nodeNum);
230
                                node.initialize();
231
                        } // for nodeNum */
232
                }
233

    
234
                candidatos.clear();
235
                // A?adimos el Start Node a la lista de candidatosSTL
236
                // Nodos finales
237
                for (int h=0; h < clonedStops.size(); h++)
238
                {
239
                        StopAux auxStop = (StopAux) clonedStops.get(h);
240
                        int idStop = auxStop.getIdStop().intValue();
241
                
242
                        GvNode auxNode = graph.getNodeByID(idStop);
243
                        auxNode.initialize();
244
                }
245
                node = graph.getNodeByID(idStart);
246
                node.initialize();
247
                bestNode = node;
248

    
249
                candidatos.add(node);
250
                node.setCostZero();
251
                node.setStatus(GvNode.statNowInList);
252
                bestCost = Double.MAX_VALUE;
253

    
254
                // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
255
                // Nodos
256
                int stopActual = 0;
257

    
258
                while ((!bExit) && (candidatos.size() > 0)) {
259
                        // Buscamos el nodo con m?nimo coste
260
                        node = (GvNode) candidatos.get(0);
261
                        bestNode = node;
262
                        bestCost = node.getBestCost();
263
                        for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) {
264
                                node = (GvNode) candidatos.get(nodeNum);
265
                                if (node.getBestCost() < bestCost) {
266
                                        bestCost = node.getBestCost();
267
                                        bestNode = node;
268
                                }
269
                        } // for nodeNum candidatosSTL
270

    
271
                        node = bestNode;
272
                        // Borramos el mejor nodo de la lista de candidatosSTL
273
                        node.setStatus(GvNode.statWasInList);
274
                        // TODO: BORRAR POR INDEX, NO AS?. ES M?S LENTO QUE SI BORRAMOS EL i-?simo.
275
                        candidatos.remove(node);
276
                        
277
                        if (callMinimumCostNodeSelectedListeners(node))
278
                                bExit = true;
279
                        
280
                        // Si hemos fijado un m?ximo coste de exploraci?n, lo
281
                        // tenemos en cuenta para salir.
282
                        if ((maxCost < bestNode.getBestCost()) ||
283
                                        maxDistance < bestNode.getAccumulatedLength())
284
                        {
285
                                bExit=true;
286
                        }
287
                        
288
                        // System.out.println("LINK " + link.getIdArc() + " from ");
289
                        // System.out.println("from " + idStart + " to " + finalNode.getIdNode() + ". node=" + node.getIdNode());
290
                        if (!bExploreAll)
291
                        {
292
                                // Miramos si hemos llegado donde quer?amos
293
                                StopAux auxStop = (StopAux) clonedStops.get(stopActual);
294
                                int idStop = auxStop.getIdStop().intValue();
295
                                
296
                                if (bestNode.getIdNode() == idStop) {
297
                                        // Hemos llegado a ese punto. Miramos el resto de puntos destino
298
                                        // a ver si ya hemos pasado por alguno de ellos.
299
                                        // Si con algun punto no pasamos por aqu?, no habremos llegado a ese punto.
300
                                        // No importa, puede que al resto s?, y esos nodos a los que s? hemos llegado
301
                                        // tendr?n bien rellenado el coste.
302
                                        auxStop.setFound(true);
303
                                        for (int i=stopActual; i < clonedStops.size(); i++)
304
                                        {
305
                                                auxStop = (StopAux) clonedStops.get(i);
306
                                                if (!auxStop.isFound())
307
                                                {
308
                                                        Integer id = auxStop.getIdStop();
309
                
310
                                                        GvNode auxNode = graph.getNodeByID(id.intValue());
311
                                                        if (auxNode.getStatus() == GvNode.statWasInList)
312
                                                        {
313
                                                                auxStop.setFound(true);
314
                                                        }
315
                                                        else
316
                                                        {
317
                                                                stopActual = i;
318
                                                                break;
319
                                                        }
320
                                                }
321
                                        }                                                
322
                                        if (clonedStops.size() == 0)
323
                                        {
324
                                                bExit = true;
325
                                                break; // Ya hemos llegado a todos los nodos
326
                                        }                                
327
                                }
328
                        } // if bExploreAll
329
                        
330
                        // sprintf(Mensaje,"Enlaces en el nodo %ld:
331
                        // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
332
                        // AfxMessageBox(Mensaje);
333

    
334
                        // A?adimos a la lista de candidatosSTL los vecinos del nodo que
335
                        // acabamos de borrar
336
                        // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
337
                        // SALEN.
338
//                        for (linkNum = 0; linkNum < node.getOutputLinks().size(); linkNum++) {
339
                        for (int iConec=0; iConec< node.getConnectors().size();  iConec++) {
340
                                // Pillamos el nodo vecino
341
                                GvConnector c = node.getConnectors().get(iConec);
342
                                if (c.getEdgeOut() == null) continue;
343
                                
344
                                link = (GvEdge) c.getEdgeOut();
345
                                idSiguienteNodo = link.getIdNodeEnd();
346
                                
347
                                // To avoid U-turn
348
                                if (c.getEdgeIn() != null)
349
                                        if (c.getFrom_link_c() == c.getEdgeIn().getIdEdge())
350
                                                continue;
351

    
352

    
353
                                
354
                                toNode = graph.getNodeByID(idSiguienteNodo);
355

    
356
                                // 27_5_2004
357
                                // Si un arco tiene coste negativo, lo ignoramos
358
                                if (link.getWeight() < 0)
359
                                        continue;
360

    
361
                                // Fin arco con coste negativo
362

    
363
                                // NUEVO: 26-7-2003: Comprobamos si est? inicializado
364
                                if (toNode.getNumSoluc() != GlobalCounter.getGlobalSolutionNumber()) {
365
                                        toNode.initialize();
366
                                }
367
                                else
368
                                {
369
                                        // System.out.println("Nodo ya inicializado");
370
                                }
371

    
372
                                // Miramos si ese nodo ya ha estado antes en la lista de
373
                                // candidatos
374
                                if (toNode.getStatus() != GvNode.statWasInList) {
375
                                        // Miramos a ver si podemos mejorar su best_cost
376
                                        newCost = c.getBestCostOut() + link.getWeight();
377
//                                        newCost = node.getBestCost() + link.getWeight();
378
                                        // Change to take care of turn costs
379
                                        if (toNode.existeMejora(link, newCost)) {  // Es una mejora, as? que actualizamos el vecino y
380
//                                                // lo a?adimos a los candidatosSTL
381
//                                                toNode.setBestCost(newCost);
382
//                                                 
383
//                                                toNode.setFromLink(link.getIdEdge());
384
                                                // Es una mejora, as? que actualizamos el vecino y
385
                                                // lo a?adimos a los candidatosSTL
386
                                                double newLength = node.getAccumulatedLength() + link.getDistance();
387
                                                toNode.setAccumulatedLength(newLength);
388

    
389
                                                if (toNode.getStatus() != GvNode.statNowInList) {
390
                                                        toNode.setStatus(GvNode.statNowInList);
391
                                                        candidatos.add(toNode);
392
                                                }
393
                                        } // Si hay mejora
394
                                } // if ese nodo no ha estado en la lista de candidatosSTL
395
                                if (callAdjacenteEdgeVisitedListeners(bestNode, link))
396
                                        continue;                                
397

    
398
                        } // for linkNum
399
                } // while candidatosSTL
400

    
401
        }
402

    
403

    
404
        public GvFlag getSourceFlag() {
405
                return sourceFlag;
406
        }
407

    
408

    
409
        public void setSourceFlag(GvFlag sourceFlag) {
410
                this.sourceFlag = sourceFlag;
411
                
412
        }
413
        public void setExploreAllNetwork(boolean b) {
414
                bExploreAll  = b;
415
        }
416
        public double getMaxCost() {
417
                return maxCost;
418
        }
419
        public void setMaxCost(double maxCost) {
420
                this.maxCost = maxCost;
421
        }
422
        public double getMaxDistance() {
423
                return maxDistance;
424
        }
425
        public void setMaxDistance(double maxDistance) {
426
                this.maxDistance = maxDistance;
427
        }
428

    
429
}