Statistics
| Revision:

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

History | View | Annotate | Download (13.9 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.LinkedList;
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.GraphException;
37
import org.gvsig.graph.core.GvEdge;
38
import org.gvsig.graph.core.GvFlag;
39
import org.gvsig.graph.core.GvNode;
40
import org.gvsig.graph.core.IFeatureExtractor;
41
import org.gvsig.graph.core.IGraph;
42
import org.gvsig.graph.core.InfoShp;
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.layers.VectorialAdapter;
49
import com.vividsolutions.jts.geom.Coordinate;
50
import com.vividsolutions.jts.geom.Geometry;
51
import com.vividsolutions.jts.geom.GeometryFactory;
52
import com.vividsolutions.jts.geom.LineString;
53

    
54
public abstract class AbstractShortestPathSolver extends AbstractNetSolver {
55

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

    
61
        public abstract Route calculateRoute() throws GraphException;
62

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

    
79
        }
80

    
81
        private void populateRouteSimple(int idStart, int idEnd)
82
                        throws BaseException {
83
                int idEnlace;
84
                GvNode node;
85
                GvEdge link;
86
                double costeEntrada;
87

    
88
                // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los
89
                // Enlaces
90
                double Coste = 0;
91
                double Coste2 = 0;
92
                IGraph graph = net.getGraph();
93
                node = graph.getNodeByID(idEnd);
94
                int from_link = node.get_best_from_link();
95
                VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource();
96
                while (node.getIdNode() != idStart) {
97
                        if (from_link == -1) {
98
                                throw new RuntimeException(
99
                                                "Fallo al recorrer de manera inversa la soluci?n. Encontrado arco con -1");
100
                                // break; // FALLO!!
101
                        }
102
                        link = graph.getEdgeByID(from_link);
103
                        IFeature feat = va.getFeature(link.getIdArc());
104
                        route.addRouteFeature(feat.getGeometry(), link.getIdArc(), link
105
                                        .getWeight(), link.getDistance(), feat.getAttribute(
106
                                        getFieldIndexStreetName()).toString());
107

    
108
                        node = graph.getNodeByID(link.getIdNodeOrig());
109

    
110
                        Coste = Coste + link.getWeight();
111
                        Coste2 = Coste2 + link.getDistance();
112

    
113
                        // TODO:
114
                        // from_link = node.get_from_link(idEnlace, &costeEntrada);
115
                        from_link = node.get_from_link(link.getIdEdge());
116

    
117
                }
118
                System.out.println("Salgo con node = " + node.getIdNode());
119
        }
120

    
121
        /**
122
         * TODO: DON'T USE JTS GEOMETRIES IN ORDER TO DO IT MUCH FASTER!!
123
         *                         => Implement 
124
         * @param origin
125
         * @param dest
126
         * @param idStart
127
         * @param idEnd
128
         * @throws BaseException
129
         */
130
        protected void populateRoute(GvFlag origin, GvFlag dest, int idStart,
131
                        int idEnd) throws BaseException {
132
                int idEnlace;
133
                GvNode node;
134
                GvEdge link;
135
                double costeEntrada;
136

    
137
                // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los
138
                // Enlaces
139
                
140
                if (idStart == idEnd) {
141
                        // Mismo punto.
142
                        return;
143
                }
144
                IGraph graph = net.getGraph();
145
                node = graph.getNodeByID(idEnd);
146
                int from_link = node.get_best_from_link();
147

    
148
                if (featExtractor == null)
149
                {
150
                        if (net.getFeatExtractor() == null) { 
151
                                featExtractor = new DefaultFeatureExtractor(net.getLayer());
152
                                net.setFeatExtractor(featExtractor);
153
                        }
154
                        featExtractor = net.getFeatExtractor();
155
                                        
156
                }
157

    
158
//                VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource();
159
//                va.start();
160

    
161
                /*
162
                 * Miramos los nodos de los tramos inicio y final, y cogemos el nodo que
163
                 * tenga el from_link rellenado. E IGUAL A NUMSOLUCGLOBAL!!!! A partir
164
                 * de ah?, recorremos hacia atr?s y tenemos el cuerpo principal del
165
                 * shape. Luego, para las puntas hay que tener en cuenta los
166
                 * porcentajes, viendo el trozo que est? pegando a los nodos que sabemos
167
                 * que est?n en el path
168
                 */
169

    
170
                /*
171
                 * 22/9/2003 Corregimos el fallo que hab?a de escribir el shape de atr?s
172
                 * adelante. Guardamos lo que necesitamos en listaShapes y recorremos
173
                 * esa lista guardando los tramos con el sentido adecuado.
174
                 */
175

    
176
                /*
177
                 * 3/Febrero/2005 Limpieza de c?digo superfluo y correci?n de un fallo
178
                 * raro. Ahora es m?s simple y parece que no falla. A ver si dura. IDEA:
179
                 * quiz?s se necesite meter el porcentaje en los arcos partidos.
180
                 */
181

    
182
                // Define a template class for a vector of IDs.
183
                InfoShp infoShp;
184
                LinkedList pilaShapes = new LinkedList();
185
                // typedef stack<CInfoShp> PILAINFO;
186
                // PILAINFO pilaShapes;
187

    
188
                double costeTramoFinal = -1;
189
                GvNode nodeEnd = graph.getNodeByID(idEnd);
190
                GvEdge finalEdge = graph.getEdgeByID(nodeEnd.get_best_from_link());
191
                costeTramoFinal = finalEdge.getWeight();
192

    
193
                GvNode pNodo;
194
                GvEdge pEnlace;
195

    
196
                boolean bFlipearShape = false;
197

    
198
                double pctMax, pctMin;
199

    
200
                // ////////////////////////////////////////////////////////////////////////////////////
201
                // Trozo del final
202
                // El shape va de idStop1 a idStop2, y el porcentaje viene en ese
203
                // sentido.
204
                // Si el idEnd es idStop1, quiere decir que el tramo que falta va en ese
205
                // sentido tambi?n,
206
                // as? que recorremos ese shape desde idStop1 hasta que rebasemos o
207
                // igualemos ese porcentaje.
208
                // Si no, hemos pasado por idStop2 y la parte que hay que meter es desde
209
                // el pto interior a idStop2
210
                // /////////////////////////////////////////////////////////////////////////////////////
211
                // IFeature feat = va.getFeature(finalEdge.getIdArc());
212
                IGeometry g = featExtractor.getGeometry(finalEdge.getIdArc());
213
                Value nameStreet = featExtractor.getFieldValue(finalEdge.getIdArc(),
214
                                getFieldIndexStreetName());
215

    
216
//                MultiLineString jtsGeom = (MultiLineString) g.toJTSGeometry();
217
                // CoordinateFilter removeDuplicates = new
218
                // UniqueCoordinateArrayFilter();
219
                // jtsGeom.apply(removeDuplicates);
220
                // jtsGeom.geometryChanged();
221

    
222
                // SI ESTAMOS SOBRE EL MISMO TRAMO, CASO PARTICULAR
223
                // y el sentido de circulaci?n es correcto
224
                if ((origin.getIdArc() == dest.getIdArc())
225
                                && (nodeEnd.getBestCost() <= costeTramoFinal)) {
226
                        if (dest.getPct() > origin.getPct()) {
227
                                pctMax = dest.getPct();
228
                                pctMin = origin.getPct();
229
                        } else {
230
                                pctMax = origin.getPct();
231
                                pctMin = dest.getPct();
232
                                bFlipearShape = true;
233
                        }
234

    
235
                        IGeometry line = NetworkUtils.getPartialLineString(g,
236
                                        pctMax, 1);
237

    
238
                        pctMin = pctMin / pctMax; // Porque ha cambiado la longitud
239
                        // del shape
240

    
241
                        line = NetworkUtils.getPartialLineString(line, pctMin, 0);
242

    
243
                        if (bFlipearShape)
244
                                line = NetworkUtils.flipGeometry(line);
245

    
246
                        IGeometry geom = line;
247
                        // TODO: Calcular bien el length de este arco,
248
                        // basandonos en el porcentaje costeTramoFinal / costeOriginal
249
                        route.addRouteFeature(geom, origin.getIdArc(), nodeEnd
250
                                        .getBestCost(), nodeEnd.getAccumulatedLength(), nameStreet
251
                                        .toString());
252

    
253
                        return; // Deber?a sacar el coste
254
                }
255

    
256
                // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los
257
                // Enlaces
258
                pNodo = graph.getNodeByID(idEnd);
259

    
260
                from_link = pNodo.get_best_from_link();
261

    
262
                long t1 = System.currentTimeMillis();
263

    
264
                while ((pNodo.getIdNode() != idStart)) {
265
                        idEnlace = from_link;
266

    
267
                        pEnlace = graph.getEdgeByID(idEnlace);
268
                        // System.err.println("from_link=" + from_link + " idTramo=" +
269
                        // pEnlace.getIdArc());
270

    
271
                        pNodo = graph.getNodeByID(pEnlace.getIdNodeOrig());
272

    
273
                        infoShp = new InfoShp();
274
                        infoShp.distance = pEnlace.getDistance();
275
                        infoShp.cost = pEnlace.getWeight();
276

    
277
                        if ((pEnlace.getIdArc() == origin.getIdArc())
278
                                        || (pEnlace.getIdArc() == dest.getIdArc())) {
279
                                if (pEnlace.getIdArc() == origin.getIdArc()) {
280
                                        infoShp.pct = origin.getPct();
281
                                        infoShp.idArc = origin.getIdArc();
282
                                        if (pEnlace.getDirec() == 0) {
283
                                                infoShp.direction = 1;
284
                                                infoShp.bFlip = true;
285
                                        } else // Hemos pasado por el 2
286
                                        {
287
                                                infoShp.direction = 0;
288
                                                infoShp.bFlip = false;
289
                                        } // if else */
290
                                } else {
291
                                        infoShp.pct = dest.getPct();
292
                                        infoShp.idArc = dest.getIdArc();
293
                                        if (pEnlace.getDirec() == 0) {
294
                                                infoShp.direction = 0;
295
                                                infoShp.bFlip = true;
296
                                        } else {
297
                                                infoShp.direction = 1;
298
                                                infoShp.bFlip = false;
299
                                        } // if else */
300
                                }
301
                        } else {
302
                                infoShp.pct = 1.0;
303
                                infoShp.idArc = pEnlace.getIdArc();
304

    
305
                                infoShp.direction = 1;
306
                                if (pEnlace.getDirec() == 1)
307
                                        infoShp.bFlip = false;
308
                                else
309
                                        infoShp.bFlip = true;
310
                        }
311

    
312
                        pilaShapes.addFirst(infoShp);
313
                        if (pNodo.getIdNode() != idStart)
314
                                from_link = pNodo.get_from_link(idEnlace);
315
                }
316
                long t2 = System.currentTimeMillis();
317
                System.out.println("T populate 1 = " + (t2 - t1));
318

    
319
                // Y ahora recorremos hacia atr?s el vector y escribimos los shapes.
320
                // VECTORINFO::iterator theIterator;
321
                int auxC = 0;
322

    
323
                t1 = System.currentTimeMillis();
324

    
325
                while (!pilaShapes.isEmpty()) {
326
                        infoShp = (InfoShp) pilaShapes.peek();
327
                        g = featExtractor.getGeometry(infoShp.idArc);
328
                        nameStreet = featExtractor.getFieldValue(infoShp.idArc,
329
                                        getFieldIndexStreetName());
330
//                        nameStreet = ValueFactory.createValue("TEST");
331
                        
332
//                        MultiLineString line = (MultiLineString) g.toJTSGeometry();
333
                        IGeometry line = g;
334
                        IGeometry aux = null;
335
                        if (infoShp.pct < 1.0)
336
                                aux = NetworkUtils.getPartialLineString(g, infoShp.pct,
337
                                                infoShp.direction);
338

    
339
                        IGeometry geom = null;
340
                        if (aux == null) {
341
                                if (infoShp.bFlip)
342
                                        line = NetworkUtils.flipGeometry(line);
343
                                geom = line; //FConverter.jts_to_igeometry(line);
344
                        } else {
345
                                if (infoShp.bFlip)
346
                                        aux = NetworkUtils.flipGeometry(aux); //aux.reverse();
347
                                geom = aux; //FConverter.jts_to_igeometry(aux);
348
                        }
349

    
350
                        route.addRouteFeature(geom, infoShp.idArc, infoShp.cost,
351
                                        infoShp.distance, nameStreet.toString());
352

    
353
                        pilaShapes.removeFirst();
354
                        auxC++;
355

    
356
                }
357
//                va.stop();
358
                t2 = System.currentTimeMillis();
359
                System.out.println("T populate 2 = " + (t2 - t1));
360
                return;
361

    
362
        }
363

    
364
        LineString SituaSobreTramo(Geometry geom, int idArc, double pct, int parte) {
365
                int j, numVertices;
366
                double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
367
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
368
                double dist = 0;
369

    
370
                longAcum = 0;
371
                longReal = geom.getLength();
372
                longBuscada = longReal * pct;
373
                Coordinate[] coords = geom.getCoordinates();
374
                Coordinate c1 = null, c2 = null;
375
                ArrayList savedCoords = new ArrayList();
376

    
377
                if (parte > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no llegamos)
378
                {
379
                        for (j = 0; j < coords.length - 1; j++) {
380
                                c1 = coords[j];
381
                                c2 = coords[j + 1];
382
                                dist = c1.distance(c2);
383
                                longAcum += dist;
384
                                savedCoords.add(c1);
385
                                if (longAcum >= longBuscada) {
386
                                        // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
387
                                        distSobre = dist - (longAcum - longBuscada);
388
                                        miniPorcentaje = distSobre / dist;
389

    
390
                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
391
                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
392

    
393
                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
394
                                        break;
395
                                } // if longAcum >= longBuscada
396
                        } // for j
397

    
398
                } else // Hemos entrado por el 2 hacia el 1
399
                {
400
                        numVertices = 0;
401
                        for (j = 0; j < coords.length; j++) {
402
                                // //////////////////////////////////////////////////////////////
403
                                // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
404
                                // podemos acceder al elemento j+1 porque nos salimos del shape
405
                                // ///////////////////////////////////////////////////////////////
406
                                c1 = coords[j];
407
                                if (j < coords.length - 1) {
408
                                        c2 = coords[j + 1];
409

    
410
                                        dist = c1.distance(c2);
411
                                        longAcum += dist;
412
                                }
413

    
414
                                if (longAcum >= longBuscada) {
415
                                        // Hasta aqu?. Empezamos a meter puntos
416

    
417
                                        if (numVertices == 0) {
418
                                                distSobre = dist - (longAcum - longBuscada);
419
                                                miniPorcentaje = distSobre / dist;
420
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
421
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
422

    
423
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
424
                                        } else {
425
                                                savedCoords.add(c2);
426
                                        }
427
                                        numVertices++;
428
                                        // break;
429
                                } // if longAcum >= longBuscada
430
                        } // for j
431

    
432
                        // savedCoords.add(c2);
433

    
434
                } // if else
435

    
436
                return geomFactory.createLineString((Coordinate[]) savedCoords
437
                                .toArray(new Coordinate[0]));
438
        }
439

    
440
        private int getFieldIndexStreetName() {
441
                return fieldIndexStreetName;
442
        }
443

    
444
        public IFeatureExtractor getFeatExtractor() {
445
                return featExtractor;
446
        }
447

    
448
        public void setFeatExtractor(IFeatureExtractor featExtractor) {
449
                this.featExtractor = featExtractor;
450
        }
451

    
452
}