Statistics
| Revision:

root / trunk / extensions / extGraph / src / org / gvsig / graph / solvers / AbstractShortestPathSolver.java @ 37909

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

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

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

    
59
public abstract class AbstractShortestPathSolver extends AbstractNetSolver {
60

    
61
        private GeometryFactory geomFactory = new GeometryFactory();
62
        protected Route route = new Route();
63
        private int fieldIndexStreetName;
64
        private IFeatureExtractor featExtractor = null;
65

    
66
        public abstract Route calculateRoute() throws GraphException;
67

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

    
84
        }
85

    
86
        private void populateRouteSimple(int idStart, int idEnd)
87
                        throws BaseException {
88
                int idEnlace;
89
                GvNode node;
90
                GvEdge link;
91
                double costeEntrada;
92

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

    
113
                        node = graph.getNodeByID(link.getIdNodeOrig());
114

    
115
                        Coste = Coste + link.getWeight();
116
                        Coste2 = Coste2 + link.getDistance();
117

    
118
                        // TODO:
119
                        // from_link = node.get_from_link(idEnlace, &costeEntrada);
120
                        from_link = node.get_from_link(link.getIdEdge());
121

    
122
                }
123
                System.out.println("Salgo con node = " + node.getIdNode());
124
        }
125

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

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

    
153
                if (featExtractor == null)
154
                {
155
                        if (net.getFeatExtractor() == null) { 
156
                                featExtractor = new DefaultFeatureExtractor(net.getLayer());
157
                                net.setFeatExtractor(featExtractor);
158
                        }
159
                        featExtractor = net.getFeatExtractor();
160
                                        
161
                }
162

    
163
//                VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource();
164
//                va.start();
165

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

    
175
                /*
176
                 * 22/9/2003 Corregimos el fallo que hab?a de escribir el shape de atr?s
177
                 * adelante. Guardamos lo que necesitamos en listaShapes y recorremos
178
                 * esa lista guardando los tramos con el sentido adecuado.
179
                 */
180

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

    
187
                // Define a template class for a vector of IDs.
188
                InfoShp infoShp;
189
                LinkedList pilaShapes = new LinkedList();
190
                // typedef stack<CInfoShp> PILAINFO;
191
                // PILAINFO pilaShapes;
192

    
193
                double costeTramoFinal = -1;
194
                GvNode nodeEnd = graph.getNodeByID(idEnd);
195
                GvEdge finalEdge = graph.getEdgeByID(nodeEnd.get_best_from_link());
196
                costeTramoFinal = finalEdge.getWeight();
197

    
198
                GvNode pNodo;
199
                GvEdge pEnlace;
200

    
201
                boolean bFlipearShape = false;
202

    
203
                double pctMax, pctMin;
204

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

    
221
//                MultiLineString jtsGeom = (MultiLineString) g.toJTSGeometry();
222
                // CoordinateFilter removeDuplicates = new
223
                // UniqueCoordinateArrayFilter();
224
                // jtsGeom.apply(removeDuplicates);
225
                // jtsGeom.geometryChanged();
226

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

    
240
                        IGeometry line = NetworkUtils.getPartialLineString(g,
241
                                        pctMax, 1);
242

    
243
                        pctMin = pctMin / pctMax; // Porque ha cambiado la longitud
244
                        // del shape
245

    
246
                        line = NetworkUtils.getPartialLineString(line, pctMin, 0);
247

    
248
                        if (bFlipearShape)
249
                                line = NetworkUtils.flipGeometry(line);
250

    
251
                        IGeometry geom = line;
252
                        // TODO: Calcular bien el length de este arco,
253
                        // basandonos en el porcentaje costeTramoFinal / costeOriginal
254
                        route.addRouteFeature(geom, origin.getIdArc(), nodeEnd
255
                                        .getBestCost(), nodeEnd.getAccumulatedLength(), nameStreet
256
                                        .toString());
257

    
258
                        return; // Deber?a sacar el coste
259
                }
260

    
261
                // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los
262
                // Enlaces
263
                pNodo = graph.getNodeByID(idEnd);
264

    
265
                from_link = pNodo.get_best_from_link();
266

    
267
                long t1 = System.currentTimeMillis();
268

    
269
                while ((pNodo.getIdNode() != idStart)) {
270
                        idEnlace = from_link;
271

    
272
                        pEnlace = graph.getEdgeByID(idEnlace);
273
                        // System.err.println("from_link=" + from_link + " idTramo=" +
274
                        // pEnlace.getIdArc());
275

    
276
                        pNodo = graph.getNodeByID(pEnlace.getIdNodeOrig());
277

    
278
                        infoShp = new InfoShp();
279
                        infoShp.distance = pEnlace.getDistance();
280
                        infoShp.cost = pEnlace.getWeight();
281

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

    
310
                                infoShp.direction = 1;
311
                                if (pEnlace.getDirec() == 1)
312
                                        infoShp.bFlip = false;
313
                                else
314
                                        infoShp.bFlip = true;
315
                        }
316

    
317
                        pilaShapes.addFirst(infoShp);
318
                        if (pNodo.getIdNode() != idStart)
319
                                from_link = pNodo.get_from_link(idEnlace);
320
                }
321
                long t2 = System.currentTimeMillis();
322
                System.out.println("T populate 1 = " + (t2 - t1));
323

    
324
                // Y ahora recorremos hacia atr?s el vector y escribimos los shapes.
325
                // VECTORINFO::iterator theIterator;
326
                int auxC = 0;
327

    
328
                t1 = System.currentTimeMillis();
329

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

    
344
                        IGeometry geom = null;
345
                        if (aux == null) {
346
                                if (infoShp.bFlip)
347
                                        line = NetworkUtils.flipGeometry(line);
348
                                geom = line; //FConverter.jts_to_igeometry(line);
349
                        } else {
350
                                if (infoShp.bFlip)
351
                                        aux = NetworkUtils.flipGeometry(aux); //aux.reverse();
352
                                geom = aux; //FConverter.jts_to_igeometry(aux);
353
                        }
354

    
355
                        route.addRouteFeature(geom, infoShp.idArc, infoShp.cost,
356
                                        infoShp.distance, nameStreet.toString());
357

    
358
                        pilaShapes.removeFirst();
359
                        auxC++;
360

    
361
                }
362
//                va.stop();
363
                t2 = System.currentTimeMillis();
364
                System.out.println("T populate 2 = " + (t2 - t1));
365
                return;
366

    
367
        }
368

    
369
        LineString SituaSobreTramo(Geometry geom, int idArc, double pct, int parte) {
370
                int j, numVertices;
371
                double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
372
                double nuevaX, nuevaY; // Por cuestiones de claridad al programar
373
                double dist = 0;
374

    
375
                longAcum = 0;
376
                longReal = geom.getLength();
377
                longBuscada = longReal * pct;
378
                Coordinate[] coords = geom.getCoordinates();
379
                Coordinate c1 = null, c2 = null;
380
                ArrayList savedCoords = new ArrayList();
381

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

    
395
                                        nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
396
                                        nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
397

    
398
                                        savedCoords.add(new Coordinate(nuevaX, nuevaY));
399
                                        break;
400
                                } // if longAcum >= longBuscada
401
                        } // for j
402

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

    
415
                                        dist = c1.distance(c2);
416
                                        longAcum += dist;
417
                                }
418

    
419
                                if (longAcum >= longBuscada) {
420
                                        // Hasta aqu?. Empezamos a meter puntos
421

    
422
                                        if (numVertices == 0) {
423
                                                distSobre = dist - (longAcum - longBuscada);
424
                                                miniPorcentaje = distSobre / dist;
425
                                                nuevaX = c1.x + (c2.x - c1.x) * miniPorcentaje;
426
                                                nuevaY = c1.y + (c2.y - c1.y) * miniPorcentaje;
427

    
428
                                                savedCoords.add(new Coordinate(nuevaX, nuevaY));
429
                                        } else {
430
                                                savedCoords.add(c2);
431
                                        }
432
                                        numVertices++;
433
                                        // break;
434
                                } // if longAcum >= longBuscada
435
                        } // for j
436

    
437
                        // savedCoords.add(c2);
438

    
439
                } // if else
440

    
441
                return geomFactory.createLineString((Coordinate[]) savedCoords
442
                                .toArray(new Coordinate[0]));
443
        }
444

    
445
        private int getFieldIndexStreetName() {
446
                return fieldIndexStreetName;
447
        }
448

    
449
        public IFeatureExtractor getFeatExtractor() {
450
                return featExtractor;
451
        }
452

    
453
        public void setFeatExtractor(IFeatureExtractor featExtractor) {
454
                this.featExtractor = featExtractor;
455
        }
456

    
457
}