Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / AbstractShortestPathSolver.java @ 30840

History | View | Annotate | Download (14 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2008 Software Colaborativo (www.scolab.es)   development
26
*/
27
 
28
package org.gvsig.graph.solvers;
29

    
30
import java.util.ArrayList;
31
import java.util.Stack;
32

    
33
import org.gvsig.exceptions.BaseException;
34
import org.gvsig.graph.core.AbstractNetSolver;
35
import org.gvsig.graph.core.DefaultFeatureExtractor;
36
import org.gvsig.graph.core.GvEdge;
37
import org.gvsig.graph.core.GvFlag;
38
import org.gvsig.graph.core.GvNode;
39
import org.gvsig.graph.core.IFeatureExtractor;
40
import org.gvsig.graph.core.IGraph;
41
import org.gvsig.graph.core.InfoShp;
42
import org.gvsig.graph.core.Network;
43
import org.gvsig.graph.core.NetworkUtils;
44

    
45
import com.hardcode.gdbms.engine.values.Value;
46
import com.iver.cit.gvsig.fmap.core.IFeature;
47
import com.iver.cit.gvsig.fmap.core.IGeometry;
48
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
49
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
50
import com.vividsolutions.jts.geom.Coordinate;
51
import com.vividsolutions.jts.geom.Geometry;
52
import com.vividsolutions.jts.geom.GeometryFactory;
53
import com.vividsolutions.jts.geom.LineString;
54
import com.vividsolutions.jts.geom.MultiLineString;
55

    
56
public class AbstractShortestPathSolver extends AbstractNetSolver {
57

    
58
        private GeometryFactory geomFactory = new GeometryFactory();
59
        protected Route route = new Route();
60
        private int fieldIndexStreetName;
61
        private IFeatureExtractor featExtractor = null;
62

    
63
        public void setFielStreetName(String name) {
64
                try {
65
                        int aux = net.getLayer().getRecordset().getFieldIndexByName(name);
66
                        if (aux == -1)
67
                                throw new RuntimeException("Field " + name + " not found.");
68
                        fieldIndexStreetName = aux;
69
                } catch (BaseException e) {
70
                        // TODO Auto-generated catch block
71
                        e.printStackTrace();
72
                }
73
                
74
        }
75

    
76
        private void populateRouteSimple(int idStart, int idEnd)
77
                        throws BaseException {
78
                                int idEnlace;
79
                                GvNode node;
80
                                GvEdge link;
81
                                double costeEntrada;
82
                        
83
                                // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces
84
                                double Coste = 0;
85
                                double Coste2 = 0;
86
                                IGraph graph = net.getGraph();
87
                                node = graph.getNodeByID(idEnd);
88
                                int from_link = node.get_best_from_link();
89
                                VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource();
90
                                while (node.getIdNode() != idStart)
91
                                {
92
                                        if (from_link == -1)
93
                                        {
94
                                                throw new RuntimeException("Fallo al recorrer de manera inversa la soluci?n. Encontrado arco con -1");
95
                                                // break; // FALLO!!
96
                                        } 
97
                                        link = graph.getEdgeByID(from_link);
98
                                        IFeature feat = va.getFeature(link.getIdArc());
99
                                        route.addRouteFeature(feat.getGeometry(), link.getIdArc(), 
100
                                                        link.getWeight(), link.getDistance(), feat.getAttribute(getFieldIndexStreetName()).toString());
101
                        
102
                                        node = graph.getNodeByID(link.getIdNodeOrig());
103
                        
104
                                        Coste = Coste + link.getWeight();
105
                                        Coste2 = Coste2 + link.getDistance();
106
                        
107
                                        // TODO:
108
                                        // from_link = node.get_from_link(idEnlace, &costeEntrada);
109
                                        from_link = node.get_from_link(link.getIdEdge());
110
                                        
111
                            }        
112
                                System.out.println("Salgo con node = " + node.getIdNode());
113
                        }
114

    
115
        protected void populateRoute(GvFlag origin, GvFlag dest, int idStart,
116
                        int idEnd) throws BaseException {
117
                                        int idEnlace;
118
                                        GvNode node;
119
                                        GvEdge link;
120
                                        double costeEntrada;
121
                        
122
                                        // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces
123
                                        IGraph graph = net.getGraph();
124
                                        node = graph.getNodeByID(idEnd);
125
                                        int from_link = node.get_best_from_link();
126

    
127
                                        if (featExtractor == null)
128
                                                featExtractor = new DefaultFeatureExtractor(net.getLayer());
129

    
130
                                        VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource();
131
                                        
132
                                        /*        Miramos los nodos de los tramos inicio y final, y cogemos el nodo que tenga el from_link rellenado. E IGUAL A NUMSOLUCGLOBAL!!!!
133
                                                A partir de ah?, recorremos hacia atr?s y tenemos el cuerpo principal del shape. Luego, para
134
                                                las puntas hay que tener en cuenta los porcentajes, viendo el trozo que est? pegando a los nodos
135
                                                que sabemos que est?n en el path
136
                                        */
137
                        
138
                                        /* 22/9/2003 Corregimos el fallo que hab?a de escribir el shape de atr?s adelante.
139
                                        *  Guardamos lo que necesitamos en listaShapes y recorremos esa lista guardando los tramos
140
                                        *        con el sentido adecuado.
141
                                        */
142
                        
143
                                        /* 3/Febrero/2005 Limpieza de c?digo superfluo y correci?n de un fallo raro. Ahora es m?s simple y parece
144
                                        * que no falla. A ver si dura. IDEA: quiz?s se necesite meter el porcentaje en los arcos partidos.
145
                                        */        
146
                        
147
                                        // Define a template class for a vector of IDs.
148
                                        InfoShp infoShp;
149
                                        Stack pilaShapes = new Stack();
150
                        //                typedef stack<CInfoShp> PILAINFO;
151
                        //                PILAINFO pilaShapes;
152
                        
153
                                        double costeTramoFinal=-1;
154
                                        GvNode nodeEnd = graph.getNodeByID(idEnd);
155
                                        GvEdge finalEdge = graph.getEdgeByID(nodeEnd.get_best_from_link());
156
                                        costeTramoFinal = finalEdge.getWeight();
157
                        
158
                                        GvNode pNodo;
159
                                        GvEdge pEnlace;
160
                                        
161
                                        boolean bFlipearShape = false;
162
                        
163
                                        double pctMax, pctMin;
164
                        
165
                        
166
                        
167
                                        //////////////////////////////////////////////////////////////////////////////////////
168
                                        // Trozo del final
169
                                        // El shape va de idStop1 a idStop2, y el porcentaje viene en ese sentido.
170
                                        // Si el idEnd es idStop1, quiere decir que el tramo que falta va en ese sentido tambi?n,
171
                                        // as? que recorremos ese shape desde idStop1 hasta que rebasemos o igualemos ese porcentaje.
172
                                        // Si no, hemos pasado por idStop2 y la parte que hay que meter es desde el pto interior a idStop2
173
                                        ///////////////////////////////////////////////////////////////////////////////////////
174
//                                        IFeature feat = va.getFeature(finalEdge.getIdArc());
175
                                        IGeometry g = featExtractor.getGeometry(finalEdge.getIdArc());
176
                                        Value nameStreet = featExtractor.getFieldValue(finalEdge.getIdArc(), getFieldIndexStreetName());
177
                                        
178
                                        MultiLineString jtsGeom = (MultiLineString) g.toJTSGeometry();
179
                        //                CoordinateFilter removeDuplicates = new UniqueCoordinateArrayFilter(); 
180
                        //                jtsGeom.apply(removeDuplicates);
181
                        //                jtsGeom.geometryChanged();
182
                                        
183
                                        
184
                                        
185
                                        // SI ESTAMOS SOBRE EL MISMO TRAMO, CASO PARTICULAR
186
                                        // y el sentido de circulaci?n es correcto
187
                                        if ((origin.getIdArc() == dest.getIdArc()) && (nodeEnd.getBestCost() <= costeTramoFinal))
188
                                        {
189
                                                if (dest.getPct() > origin.getPct())
190
                                                {
191
                                                        pctMax = dest.getPct();
192
                                                        pctMin = origin.getPct(); 
193
                                                }
194
                                                else
195
                                                {
196
                                                        pctMax = origin.getPct();
197
                                                        pctMin = dest.getPct();
198
                                                        bFlipearShape = true;
199
                                                }
200
                        
201
                                                LineString line = NetworkUtils.getPartialLineString(jtsGeom, 
202
                                                                pctMax, 1);
203
                        
204
                                                pctMin = pctMin / pctMax; // Porque ha cambiado la longitud
205
                                                                                                        // del shape
206
                        
207
                                                line = NetworkUtils.getPartialLineString(line, pctMin, 0);
208
                        
209
                                                if (bFlipearShape)
210
                                                        line = line.reverse();
211
                                                
212
                                                IGeometry geom = FConverter.jts_to_igeometry(line);
213
                                                // TODO: Calcular bien el length de este arco, 
214
                                                // basandonos en el porcentaje costeTramoFinal / costeOriginal
215
                                                route.addRouteFeature(geom, origin.getIdArc(), 
216
                                                                costeTramoFinal, line.getLength(), nameStreet.toString());
217
                        
218
                        
219
                                                return ; // Deber?a sacar el coste
220
                                        }
221
                        
222
                                        
223
                        
224
                                        // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces
225
                                        pNodo = graph.getNodeByID(idEnd);
226
                                        
227
                                        from_link = pNodo.get_best_from_link();
228
                                        
229
                                        long t1 = System.currentTimeMillis();
230
                        
231
                                        while ((pNodo.getIdNode() != idStart)) 
232
                                        {
233
                                                idEnlace = from_link;
234
                                                
235
                                                pEnlace = graph.getEdgeByID(idEnlace);
236
//                                                System.err.println("from_link=" + from_link + " idTramo=" + pEnlace.getIdArc());
237
                                                
238
                                                pNodo = graph.getNodeByID(pEnlace.getIdNodeOrig());
239
                                                
240
                                                infoShp = new InfoShp();
241
                                                infoShp.distance = pEnlace.getDistance();
242
                                                infoShp.cost = pEnlace.getWeight();
243
                        
244
                                                if ((pEnlace.getIdArc() == origin.getIdArc()) || (pEnlace.getIdArc() == dest.getIdArc()))
245
                                                {
246
                                                        if (pEnlace.getIdArc() == origin.getIdArc())
247
                                                        {
248
                                                                infoShp.pct = origin.getPct();
249
                                                                infoShp.idArc = origin.getIdArc();
250
                                                                if (pEnlace.getDirec() == 0) 
251
                                                                {
252
                                                                        infoShp.direction = 1;
253
                                                                        infoShp.bFlip = true;
254
                                                                }
255
                                                                else // Hemos pasado por el 2
256
                                                                {
257
                                                                        infoShp.direction = 0;
258
                                                                        infoShp.bFlip = false;
259
                                                                } // if else */
260
                                                        }
261
                                                        else
262
                                                        {
263
                                                                infoShp.pct = dest.getPct();
264
                                                                infoShp.idArc = dest.getIdArc();
265
                                                                if (pEnlace.getDirec() == 0)
266
                                                                {
267
                                                                        infoShp.direction = 0;
268
                                                                        infoShp.bFlip = true;
269
                                                                }
270
                                                                else
271
                                                                {
272
                                                                        infoShp.direction = 1;
273
                                                                        infoShp.bFlip = false;
274
                                                                } // if else */
275
                                                        }
276
                                                }
277
                                                else
278
                                                {
279
                                                        infoShp.pct = 1.0;
280
                                                        infoShp.idArc = pEnlace.getIdArc();
281
                                                        
282
                                                        infoShp.direction =1;
283
                                                        if (pEnlace.getDirec() == 1)
284
                                                                infoShp.bFlip = false;
285
                                                        else
286
                                                                infoShp.bFlip = true;
287
                                                }
288
                        
289
                                                pilaShapes.push(infoShp);
290
                                                if (pNodo.getIdNode() != idStart)
291
                                                        from_link = pNodo.get_from_link(idEnlace);
292
                                        }
293
                                        long t2 = System.currentTimeMillis();
294
                                        System.out.println("T populate 1 = " + (t2-t1));
295
                        
296
                                        // Y ahora recorremos hacia atr?s el vector y escribimos los shapes.
297
                                        // VECTORINFO::iterator theIterator;
298
                                        int auxC = 0;
299
                                        
300
                                        t1 = System.currentTimeMillis();
301
                                        
302
                                        while (!pilaShapes.empty())  
303
                                        {
304
                                                infoShp = (InfoShp) pilaShapes.peek();
305
                                                g = featExtractor.getGeometry(infoShp.idArc);
306
                                                nameStreet = featExtractor.getFieldValue(infoShp.idArc, getFieldIndexStreetName());
307

    
308
                                                MultiLineString line = (MultiLineString) g.toJTSGeometry();
309
                                                
310
                                                LineString aux = null;
311
                                                if (infoShp.pct < 1.0)
312
                                                        aux = NetworkUtils.getPartialLineString(line, infoShp.pct,
313
                                                                        infoShp.direction);
314
                        
315
                        
316
                                                IGeometry geom = null;
317
                                                if (aux == null)
318
                                                {
319
                                                        if (infoShp.bFlip)
320
                                                                line = line.reverse();
321
                                                        geom = FConverter.jts_to_igeometry(line);
322
                                                }        
323
                                                else
324
                                                {
325
                                                        if (infoShp.bFlip)
326
                                                                aux = aux.reverse();
327
                                                        geom = FConverter.jts_to_igeometry(aux);
328
                                                }        
329
                        
330
                                                route.addRouteFeature(geom, infoShp.idArc, 
331
                                                                infoShp.cost, infoShp.distance, nameStreet.toString());
332
                        
333
                        
334
                                                pilaShapes.pop();
335
                                                auxC++;
336
                                                
337
                                        }
338
                                        t2 = System.currentTimeMillis();
339
                                        System.out.println("T populate 2 = " + (t2-t1));
340
                                        return;
341
                        
342
                                        
343
                                }
344

    
345
        LineString SituaSobreTramo(Geometry geom, int idArc, double pct, int parte) {
346
                int j, numVertices;
347
                double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
348
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
349
                double dist=0;
350
        
351
                longAcum = 0;
352
                longReal = geom.getLength();
353
                longBuscada = longReal * pct;
354
                Coordinate[] coords = geom.getCoordinates();
355
                Coordinate c1 = null, c2 = null;
356
                ArrayList savedCoords = new ArrayList();
357
        
358
                 if (parte > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no llegamos)
359
                {
360
                        for( j = 0; j < coords.length-1; j++ ) 
361
                        {
362
                                c1 = coords[j];
363
                                c2 = coords[j+1];
364
                                dist = c1.distance(c2);
365
                                longAcum += dist;
366
                                savedCoords.add(c1);
367
                                if (longAcum >= longBuscada)
368
                                {
369
                                        // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
370
                                        distSobre = dist - (longAcum - longBuscada);
371
                                        miniPorcentaje = distSobre/dist;
372
        
373
                                        nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje;
374
                                        nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje;
375
                
376
                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
377
                                        break;
378
                                } // if longAcum >= longBuscada
379
                        } // for j
380
                        
381
                }
382
                else // Hemos entrado por el 2 hacia el 1
383
                {
384
                        numVertices = 0;
385
                        for( j = 0; j < coords.length; j++ ) 
386
                        {
387
                                ////////////////////////////////////////////////////////////////
388
                                // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
389
                                // podemos acceder al elemento j+1 porque nos salimos del shape
390
                                /////////////////////////////////////////////////////////////////
391
                                c1 = coords[j];
392
                                if (j < coords.length -1)
393
                                {                                        
394
                                        c2 = coords[j+1];
395
        
396
                                        dist = c1.distance(c2);
397
                                        longAcum += dist;
398
                                }
399
        
400
                                if (longAcum >= longBuscada)
401
                                {
402
                                        // Hasta aqu?. Empezamos a meter puntos
403
        
404
                                        if (numVertices == 0) 
405
                                        {
406
                                                distSobre = dist - (longAcum - longBuscada);
407
                                                miniPorcentaje = distSobre/dist;
408
                                                nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje;
409
                                                nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje;
410
                                                
411
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
412
                                        }
413
                                        else
414
                                        {
415
                                                savedCoords.add(c2);
416
                                        }
417
                                        numVertices ++;
418
                                        // break;
419
                                } // if longAcum >= longBuscada
420
                        } // for j
421
                        
422
                        // savedCoords.add(c2);
423
                        
424
                } // if else
425
        
426
                 
427
                 return geomFactory.createLineString((Coordinate[] )savedCoords.toArray(new Coordinate[0]));
428
        }
429

    
430
        private int getFieldIndexStreetName() {
431
                return fieldIndexStreetName;
432
        }
433

    
434
        public IFeatureExtractor getFeatExtractor() {
435
                return featExtractor;
436
        }
437

    
438
        public void setFeatExtractor(IFeatureExtractor featExtractor) {
439
                this.featExtractor = featExtractor;
440
        }
441

    
442

    
443
}
444