Statistics
| Revision:

root / trunk / extensions / extGraph / src / org / gvsig / graph / core / Network.java @ 37909

History | View | Annotate | Download (34.4 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.core;
42

    
43
import java.awt.geom.PathIterator;
44
import java.awt.geom.Point2D;
45
import java.util.ArrayList;
46
import java.util.Hashtable;
47
import java.util.Iterator;
48
import java.util.Map;
49
import java.util.TreeMap;
50

    
51
import org.cresques.cts.IProjection;
52
import org.gvsig.exceptions.BaseException;
53

    
54
import com.iver.cit.gvsig.fmap.ViewPort;
55
import com.iver.cit.gvsig.fmap.core.IGeometry;
56
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
57
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
58
import com.iver.cit.gvsig.fmap.layers.CancelationException;
59
import com.iver.cit.gvsig.fmap.layers.FBitSet;
60
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
61
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
62
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
63
import com.vividsolutions.jts.geom.Coordinate;
64
import com.vividsolutions.jts.geom.LineSegment;
65
import com.vividsolutions.jts.geom.MultiLineString;
66

    
67
public class Network {
68
        protected FLyrVect lyrVect;
69

    
70
        protected IGraph graph;
71

    
72
        protected ArrayList flags = new ArrayList();
73

    
74
        protected int numOriginalEdges;
75

    
76
        protected int numOriginalNodes;
77

    
78
        private ArrayList modifiedCosts = new ArrayList();
79
        private ArrayList flagListeners = new ArrayList();
80
        private boolean dispatching = true;
81

    
82
        private Hashtable velocities = null;
83

    
84
        private ArrayList<GvTurn> turnCosts = new ArrayList();
85
        
86
        private IFeatureExtractor featExtractor = null;
87

    
88
        public void reconstruyeTramo(int idArc) {
89
                GvNode pN1, pN2;
90
                int i;
91
                
92
                // Si encontramos un enlace con idEdge >= numOriginalEdges, lo cambiamos.
93
                // Y CON ESE IDarc!!
94
                // Si hay varios, no pasa nada, volvemos a llamar a esta funci?n con IdTramo
95

    
96
                EdgePair edgePair = graph.getEdgesByIdArc(idArc);
97
                if (edgePair.getIdEdge() != -1)
98
                {
99
                        // Restauramos los enlaces de los nodos de ese tramo.
100
//                        pN1 = &Nodos[Arcos[IndiceArcos[idTramo].idArco].idNodo1];
101
//                        pN2 = &Nodos[Arcos[IndiceArcos[idTramo].idArco].idNodo2];
102
                        GvEdge edge = graph.getEdgeByID(edgePair.getIdEdge());
103
                        pN1 = graph.getNodeByID(edge.getIdNodeOrig());
104
                        pN2 = graph.getNodeByID(edge.getIdNodeEnd());
105

    
106
                        // Metemos idArco en los enlaces de Nodo1
107
//                        for (i=0; i< pN1.getOutputLinks().size(); i++)
108
//                        {
109
//                                GvEdge auxEdge = (GvEdge) pN1.getOutputLinks().get(i);
110
//                                if (auxEdge.getIdArc() == idArc)
111
//                                {
112
//                                        if (auxEdge.getIdEdge() >= numOriginalEdges) 
113
//                                        {
114
//                                                pN1.getOutputLinks().set(i, graph.getEdgeByID(edgePair.getIdEdge()));
115
//                                                break;
116
//                                        }
117
//                                }
118
//                        }
119
                        restoreConnectors(edge);
120
                        
121
                }
122

    
123
                if (edgePair.idInverseEdge != -1)
124
                {
125
//                        pN1 = &Nodos[Arcos[IndiceArcos[idTramo].idContraArco].idNodo1];
126
//                        pN2 = &Nodos[Arcos[IndiceArcos[idTramo].idContraArco].idNodo2];
127
                        GvEdge edge = graph.getEdgeByID(edgePair.getIdInverseEdge());
128
                        pN1 = graph.getNodeByID(edge.getIdNodeOrig());
129

    
130
//                        for (i=0; i< pN1.getOutputLinks().size(); i++)
131
//                        {
132
//                                if (edge.getIdArc() == idArc)
133
//                                {
134
//                                        GvEdge auxEdge = (GvEdge) pN1.getOutputLinks().get(i);
135
//                                        if (auxEdge.getIdEdge() >= numOriginalEdges) 
136
//                                        {
137
//                                                pN1.getOutputLinks().set(i, graph.getEdgeByID(edgePair.getIdInverseEdge()));
138
//                                                break;
139
//                                        }
140
//                                }                                                                
141
//                        }
142
                        restoreConnectors(edge);
143
                }
144

    
145
                int numEdges = graph.numEdges();
146
                int numNodes = graph.numVertices();
147
                for (int idEdge = numEdges-1; idEdge >= numOriginalEdges; idEdge--)
148
                {
149
                        graph.removeEdge(idEdge);
150
                }
151
                for (int idNode = numNodes-1; idNode >= numOriginalNodes; idNode--)
152
                {
153
                        graph.removeNode(idNode);
154
                }
155

    
156
        }
157

    
158
        private void restoreConnectors(GvEdge edge) {
159
                GvNode pN1 = graph.getNodeByID(edge.getIdNodeOrig());
160
                GvNode pN2 = graph.getNodeByID(edge.getIdNodeEnd());
161
                for (int iCon = 0; iCon < pN1.getConnectors().size(); iCon++) {
162
                        GvConnector c = pN1.getConnectors().get(iCon);
163
                        if (c.getEdgeOut() != null) {
164
                                if ((c.getEdgeOut().getIdEdge() >= numOriginalEdges) && (c.getEdgeOut().getIdArc() == edge.getIdArc())) {
165
                                        c.setEdgeOut(edge);
166
                                }
167
                        }
168
                }
169
                for (int iCon = 0; iCon < pN2.getConnectors().size(); iCon++) {
170
                        GvConnector c = pN2.getConnectors().get(iCon);
171
                        if (c.getEdgeIn() != null) {
172
                                if ((c.getEdgeIn().getIdEdge() >= numOriginalEdges) && (c.getEdgeIn().getIdArc() == edge.getIdArc())) {
173
                                        c.setEdgeIn(edge);
174
                                }
175
                        }
176
                }
177
        }
178

    
179
        /**
180
         * Closest ID to this point. -1 if out from tolerance.
181
         * @param x
182
         * @param y
183
         * @param tolerance
184
         * @param nearest. Point to receive the nearest point ON arc.
185
         * @return
186
         */
187
        public int findClosestArc(double x, double y, double tolerance, Point2D nearestPoint) {
188
                Point2D p = new Point2D.Double(x, y);
189
                
190
                if (featExtractor != null)
191
                {
192
                        if (! (featExtractor instanceof DefaultFeatureExtractor)) {
193
                                return findClosestArcWithFeatExtractor(p, tolerance, nearestPoint);
194
                        }
195
                }
196
                FBitSet bitSet;
197
                try {
198
                        bitSet = lyrVect.queryByPoint(p, tolerance);
199
                        ReadableVectorial va = lyrVect.getSource();
200
                        va.start();
201
                        double minDist = tolerance;
202
                        int foundGeom = -1;
203
                        for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet
204
                                        .nextSetBit(i + 1)) {
205
                                IGeometry geom;
206
                                geom = va.getShape(i);
207
                                IProjection proj = lyrVect.getProjection();
208
                            if (proj != null) {
209
                                    if (!proj.getAbrev().equals(lyrVect.getMapContext().getViewPort().getProjection().getAbrev())){
210
                                            geom.reProject(lyrVect.getCoordTrans());
211
                                    }
212
                            }
213
                                
214
                                Point2D nearest = getNearestPoint(p, geom, tolerance);
215
                                if (nearest != null) {
216
                                        double dist = nearest.distance(p);
217
                                        if (dist < minDist) {
218
                                                minDist = dist;
219
                                                foundGeom = i;
220
                                                nearestPoint.setLocation(nearest);
221
                                        }
222
                                }
223
                        }
224
                        va.stop();
225
                        return foundGeom;
226
                } catch (BaseException e1) {
227
                        // TODO Auto-generated catch block
228
                        e1.printStackTrace();
229
                }
230
                return -1;
231

    
232
        }
233

    
234
        private int findClosestArcWithFeatExtractor(Point2D p, double tolerance,
235
                        Point2D nearestPoint) {
236
                double minDist = tolerance;
237
                int foundGeom = -1;
238
                for (int i = 0; i < featExtractor.getNumFeatures(); i++) {
239
                        IGeometry geom = featExtractor.getGeometry(i);
240
                        Point2D nearest = getNearestPoint(p, geom, tolerance);
241
                        if (nearest != null) {
242
                                double dist = nearest.distance(p);
243
                                if (dist < minDist) {
244
                                        minDist = dist;
245
                                        foundGeom = i;
246
                                        nearestPoint.setLocation(nearest);
247
                                }
248
                        }
249
                }
250
                return foundGeom;
251

    
252
        }
253

    
254
        protected Point2D getNearestPoint(Point2D point, IGeometry geom,
255
                        double tolerance) {
256
                Point2D resul = null;
257
                Coordinate c = new Coordinate(point.getX(), point.getY());
258

    
259
                PathIterator theIterator = geom.getPathIterator(null,
260
                                FConverter.FLATNESS); // polyLine.getPathIterator(null,
261
                                                                                // flatness);
262
                double[] theData = new double[6];
263
                double minDist = tolerance;
264
                Coordinate from = null, first = null;
265
                while (!theIterator.isDone()) {
266
                        // while not done
267
                        int theType = theIterator.currentSegment(theData);
268

    
269
                        switch (theType) {
270
                        case PathIterator.SEG_MOVETO:
271
                                from = new Coordinate(theData[0], theData[1]);
272
                                first = from;
273
                                break;
274

    
275
                        case PathIterator.SEG_LINETO:
276

    
277
                                // System.out.println("SEG_LINETO");
278
                                Coordinate to = new Coordinate(theData[0], theData[1]);
279
                                LineSegment line = new LineSegment(from, to);
280
                                Coordinate closestPoint = line.closestPoint(c);
281
                                double dist = c.distance(closestPoint);
282
                                if ((dist < minDist)) {
283
                                        resul = new Point2D.Double(closestPoint.x, closestPoint.y);
284
                                        minDist = dist;
285
                                }
286

    
287
                                from = to;
288
                                break;
289
                        case PathIterator.SEG_CLOSE:
290
                                line = new LineSegment(from, first);
291
                                closestPoint = line.closestPoint(c);
292
                                dist = c.distance(closestPoint);
293
                                if ((dist < minDist)) {
294
                                        resul = new Point2D.Double(closestPoint.x, closestPoint.y);
295
                                        minDist = dist;
296
                                }
297

    
298
                                from = first;
299
                                break;
300

    
301
                        } // end switch
302

    
303
                        theIterator.next();
304
                }
305

    
306
                return resul;
307
        }
308

    
309
        /**
310
         * TODO: POR TERMINAR!!!
311
         * 
312
         * @param flag
313
         * @return
314
         */
315
        public int creaArcosVirtuales(GvFlag flag) {
316
                // Devuelve el idNodo del nodo virtual creado.
317
                /*
318
                 * 0.- Creamos el nuevo Nodo virtual. 1.- Recorremos los arcos nuevos
319
                 * mirando su idTramo. 2.- Si existe ese idtramo=> Ya hemos partido
320
                 * antes ese idTramo. Buscamos el arco virtual que contiene ese nodo y
321
                 * lo partimos. Ojo, recorrer hasta el final los tramos para asegurarnos
322
                 * de que es el trozo m?s peque?o. 3.- Si NO existe, utilizamos el
323
                 * IndiceArcos para coger los arcos que toca y partirlos.
324
                 * 
325
                 * 4.- OJO: Si el porcentaje es 0 ? 100, no partimos el arco, devolvemos
326
                 * el id del nodo que toca.
327
                 */
328
                // NUEVO: 20/7/2004:
329
                // Cuando trabajamos con sentidos, al partir un arco no podemos insertar
330
                // 2 nuevos sin mirar
331
                // si es o no de un ?nico sentido.) (Mirar idArco. Si es -1, no partimos
332
                // el arco).
333
                // FIN NUEVO
334
                int idNodo1, idNodo2;
335
                int idArco, elIdArco, elIdContraArco;
336
                boolean encontrado;
337
                GvNode newNode;
338

    
339
                // Sacamos los idNodos del tramo
340
                EdgePair edgePair = graph.getEdgesByIdArc(flag.getIdArc());
341
                if (edgePair.getIdEdge() != -1) {
342
                        // idNodo1 = Arcos[IndiceArcos[idTramo].idArco].idNodo1;
343
                        // idNodo2 = Arcos[IndiceArcos[idTramo].idArco].idNodo2;
344
                        idNodo1 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeOrig();
345
                        idNodo2 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeEnd();
346

    
347
                } else {
348
                        // idNodo2 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo1;
349
                        // idNodo1 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo2;
350
                        idNodo2 = graph.getEdgeByID(edgePair.getIdInverseEdge())
351
                                        .getIdNodeOrig();
352
                        idNodo1 = graph.getEdgeByID(edgePair.getIdInverseEdge())
353
                                        .getIdNodeEnd();
354

    
355
                }
356

    
357
                if (flag.getPct() == 0)
358
                        return idNodo1;
359
                if (flag.getPct() == 1)
360
                        return idNodo2;
361

    
362
                // Creamos el nodo de enmedio
363

    
364
                // if (numNodos == maxNodos) // La jodimos, T?rtola, hay que usar
365
                // reallocate
366
                // {
367
                // // NOTA: ESTO EN DEBUG HACE QUE FALLE AL USAR DESPUES EnlacesSTL. ES
368
                // POR NO S? QU? HISTORIA
369
                // // DEL HEAP. EN RELEASE NO FALLA. (TAMPOCO S? SI FASTIDIA ALGO).
370
                // Nodos = (CNode *) realloc(Nodos,(numNodos + MAX_RESERVA_NODOS) *
371
                // sizeof(CNode)); // Deber?amos chequear que devuelve algo correcto
372
                // maxNodos = numNodos + MAX_RESERVA_NODOS;
373
                // }
374

    
375
                newNode = new GvNode();
376
                // Nodo = &Nodos[numNodos];
377

    
378
                // pNuevoNodo->idNodo = numNodos;
379
                newNode.setIdNode(graph.numVertices());
380

    
381
                // OJO: Las coordenadas estas puede que no tengan que ver con la
382
                // realidad. Algo m?s correcto
383
                // ser?a tener en cuenta el shape de verdad, pero creo que no influye en
384
                // el resultado final.
385
                // pNuevoNodo->x = Nodos[idNodo1].x + (Nodos[idNodo2].x -
386
                // Nodos[idNodo1].x) * Porcentaje;
387
                // pNuevoNodo->y = Nodos[idNodo1].y + (Nodos[idNodo2].y -
388
                // Nodos[idNodo1].y) * Porcentaje;
389
                GvNode node1 = graph.getNodeByID(idNodo1);
390
                GvNode node2 = graph.getNodeByID(idNodo2);
391
                newNode.setX(node1.getX() + (node2.getX() - node1.getX())
392
                                * flag.getPct());
393
                newNode.setY(node1.getY() + (node2.getY() - node1.getY())
394
                                * flag.getPct());
395
                graph.addNode(newNode);
396
                Coordinate newC = new Coordinate(newNode.getX(), newNode.getY());
397

    
398
                encontrado = false;
399

    
400
                elIdArco = -1;
401
                elIdContraArco = -1;
402

    
403
                boolean bIdTramoYaPartido = false;
404

    
405
                // TODO: POR AQUI VOY
406
                for (idArco = numOriginalEdges; idArco < graph.numEdges(); idArco++) {
407
                        GvEdge addedEdge = graph.getEdgeByID(idArco);
408
                        if (addedEdge.getIdArc() == flag.getIdArc()) {
409
                                bIdTramoYaPartido = true;
410

    
411
                                idNodo1 = addedEdge.getIdNodeOrig();
412
                                idNodo2 = addedEdge.getIdNodeEnd();
413

    
414
                                // Comprobamos si est? enmedio
415
                                GvNode n1 = graph.getNodeByID(idNodo1);
416
                                GvNode n2 = graph.getNodeByID(idNodo2);
417
                                Coordinate c1 = new Coordinate(n1.getX(), n1.getY());
418
                                Coordinate c2 = new Coordinate(n2.getX(), n2.getY());
419
                                LineSegment line = new LineSegment(c1, c2);
420
                                double t = line.projectionFactor(newC);
421

    
422
                                // Si la proyecci?n es positiva y menor que la magnitud d, est?
423
                                // en medio
424
                                if ((t >= 0) && (t <= 1)) {
425
                                        encontrado = true;
426
                                        if (t == 0)
427
                                                return idNodo1; // No partimos
428
                                        if (t == 1)
429
                                                return idNodo2; // Tampoco partimos
430

    
431
                                        if (addedEdge.getDirec() == 1)
432
                                                elIdArco = idArco;
433
                                        else
434
                                                elIdContraArco = idArco;
435

    
436
                                } // if est? enmedio
437
                        } // if idTramo encontrado
438
                } // for idArco
439
                if (bIdTramoYaPartido && (!encontrado))
440
                        throw new RuntimeException(
441
                                        "Algo va mal con lo del producto escalar");
442

    
443
                if (encontrado) {
444
                        // sprintf(Mensaje,"Voy a partir el idTramo= %ld (idArco
445
                        // %ld)",idTramo,elIdArco);
446
                        // MessageBox(NULL,Mensaje,"",MB_OK);
447
                        if (elIdArco != -1)
448
                                PartirArco(elIdArco, newNode.getIdNode());
449

    
450
                        if (elIdContraArco != -1)
451
                                PartirArco(elIdContraArco, newNode.getIdNode());
452
                } else {
453
                        // Creamos 2 Arcos por cada arco que ten?amos antes.
454
                        if (edgePair.getIdEdge() != -1)
455
                                PartirArco(edgePair.getIdEdge(), newNode.getIdNode());
456

    
457
                        if (edgePair.getIdInverseEdge() != -1)
458
                                PartirArco(edgePair.getIdInverseEdge(), newNode.getIdNode());
459

    
460
                } // else encontrado
461

    
462
                return newNode.getIdNode();
463

    
464
        }
465

    
466
        /**
467
         * Cogemos el nodo m?s cercano y ponemos el pct a ese flag.
468
         * 
469
         * @param flag
470
         * @return
471
         */
472
        public int getClosestIdNode(GvFlag flag) {
473
                EdgePair pair = graph.getEdgesByIdArc(flag.getIdArc());
474
                if (pair.getIdEdge() != -1) {
475
                        GvEdge edge = graph.getEdgeByID(pair.getIdEdge());
476
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
477
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
478

    
479
                        double dist1 = flag.getOriginalPoint().distance(from.getX(),
480
                                        from.getY());
481
                        double dist2 = flag.getOriginalPoint().distance(to.getX(),
482
                                        to.getY());
483
                        if (dist1 < dist2) {
484
                                flag.setPct(0);
485
                                return from.getIdNode();
486
                        }
487
                        else
488
                        {
489
                                flag.setPct(1.0);
490
                                return to.getIdNode();
491
                        }
492
                } else {
493
                        GvEdge edge = graph.getEdgeByID(pair.getIdInverseEdge());
494
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
495
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
496

    
497
                        double dist1 = flag.getOriginalPoint().distance(from.getX(),
498
                                        from.getY());
499
                        double dist2 = flag.getOriginalPoint().distance(to.getX(),
500
                                        to.getY());
501
                        if (dist1 < dist2)
502
                        {
503
                                flag.setPct(0);
504
                                return from.getIdNode();
505
                        }
506
                        else
507
                        {
508
                                flag.setPct(1.0);
509
                                return to.getIdNode();
510
                        }
511
                        // if (flag.getPct() < 0.5)
512
                        // return to.getIdNode();
513
                        // else
514
                        // return from.getIdNode();
515
                }
516
        }
517

    
518
        /**
519
         * @param idArc
520
         * @param x
521
         * @param y
522
         * @return entre 0.0 y 1.0
523
         * @throws DriverIOException
524
         */
525
        private double percentAlong(int idArc, double x, double y)
526
                        throws BaseException {
527
                // Le pasamos el idTramo, la coordenada X de donde hemos pulsado y la
528
                // coordenada Y
529
                // Primero calculamos la longitud total del shape.
530
                // Luego calculamos el punto m?s cercano y su distancia para cada
531
                // segmento del shape.
532
                // Nos quedamos con el que est? m?s cerca y luego recorremos hasta ?l
533
                // acumulando distancia.
534
                // Finalmente, dividimos esa distancia por la longitud total.
535
//                lyrVect.getSource().start();
536
//                IGeometry geom = lyrVect.getSource().getShape(idArc);
537
                IGeometry geom = featExtractor.getGeometry(idArc);
538
                MultiLineString jtsGeom = (MultiLineString) geom.toJTSGeometry();
539

    
540
                Coordinate[] coords = jtsGeom.getCoordinates();
541

    
542
                Coordinate userCoord = new Coordinate(x, y);
543

    
544
                double longReal = 0;
545
                // Le pegamos una primera pasada para saber su longitud real.
546
                // OJO, NO TRABAJAMOS CON SHAPES MULTIPARTE, NO TIENE SENTIDO CON LAS
547
                // REDES (CREO)
548
                // POR ESO SUPONEMOS UNA ?NICA PARTE (L?NEA CONT?NUA)
549
                // A la vez calculamos el punto m?s cercano y su distancia para cada
550
                // segmento.
551
                double minDist = Double.MAX_VALUE;
552
                double distTo = 0;
553
                double dist = 0;
554
                Coordinate cOrig = null;
555
                Coordinate closestPoint = null;
556
                for (int j = 0; j < coords.length - 1; j++) {
557
                        Coordinate c1 = coords[j];
558
                        Coordinate c2 = coords[j + 1];
559
                        LineSegment line = new LineSegment(c1, c2);
560

    
561
                        Coordinate auxPoint = line.closestPoint(userCoord);
562
                        dist = userCoord.distance(auxPoint);
563
                        if ((dist < minDist)) {
564
                                minDist = dist;
565
                                cOrig = c1;
566
                                closestPoint = auxPoint;
567
                                distTo = longReal;
568
                        }
569
                        longReal += line.getLength();
570
                }
571
//                lyrVect.getSource().stop();
572
                dist = cOrig.distance(closestPoint);
573
                double longBuscada = distTo + dist;
574

    
575
                double pct;
576
                if (longReal > 0)
577
                        pct = longBuscada / longReal;
578
                else
579
                        pct = 0.0;
580

    
581
                return pct;
582
        }
583

    
584
        /**
585
         * Adds a flag on a network. flagDirection set if the flag must be on left
586
         * or right edge.
587
         * 
588
         * @param x
589
         * @param y
590
         * @param flagDirection
591
         * @param tol
592
         *            tolerance in map units
593
         * @return null if there is no place to add flag. You can increase the
594
         *         tolerance, then.
595
         * @throws GraphException
596
         */
597
        public GvFlag addFlag(double x, double y, int flagDirection, double tol)
598
                        throws GraphException {
599
                try {
600
                        Point2D nearestPoint = new Point2D.Double();
601
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
602
                        if (idArc == -1)
603
                                return null;
604
                        GvFlag flag = new GvFlag(x, y);
605
                        flag.setIdArc(idArc);
606

    
607
                        flag.setPct(percentAlong(idArc, x, y));
608
                        flag.setDirec(flagDirection);
609
                        flag.setIdFlag(flags.size());
610
                        callFlagsChanged(IFlagListener.FLAG_ADDED);
611
                        return flag;
612
                } catch (BaseException e) {
613
                        e.printStackTrace();
614
                        throw new GraphException(e);
615
                }
616

    
617
        }
618

    
619
        /**
620
         * Adds 2 flags on a network. (On both sides of an arc)
621
         * 
622
         * @param x
623
         * @param y
624
         * @param tol
625
         *            tolerance in map units
626
         * @return null if there is no place to add flag. You can increase the
627
         *         tolerance, then.
628
         * @throws GraphException 
629
         */
630
        public GvFlag addFlag(double x, double y, double tol) throws GraphException {
631
                try {
632
                        Point2D nearestPoint = new Point2D.Double();
633
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
634
                        if (idArc == -1)
635
                                return null;
636

    
637
                        GvFlag flag = new GvFlag(x, y);
638
                        flag.setIdArc(idArc);
639
                        EdgePair edgePair = graph.getEdgesByIdArc(idArc);
640
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
641

    
642
                        flag.setPct(percentAlong(idArc, x, y));
643
                        flag.setIdFlag(flags.size());
644
                        flags.add(flag);
645
                        callFlagsChanged(IFlagListener.FLAG_ADDED);
646
                        return flag;
647
                } catch (BaseException e) {
648
                        e.printStackTrace();
649
                        throw new GraphException(e);
650
                }
651

    
652
        }
653

    
654
        /**
655
         * Create a flag in both directions, but NOT add it to the Network.
656
         * We use it on onetomany solver
657
         * @param x
658
         * @param y
659
         * @param tol
660
         * @return
661
         * @throws GraphException
662
         */
663
        public GvFlag createFlag(double x, double y, double tol) throws GraphException {
664
                try {
665
                        Point2D nearestPoint = new Point2D.Double();
666
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
667
                        if (idArc == -1)
668
                                return null;
669

    
670
                        GvFlag flag = new GvFlag(x, y);
671
                        flag.setIdArc(idArc);
672
//                        EdgePair edgePair = graph.getEdgesByIdArc(idArc);
673
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
674

    
675
                        flag.setPct(percentAlong(idArc, x, y));
676
                        flag.setIdFlag(flags.size());
677
                        return flag;
678
                } catch (BaseException e) {
679
                        e.printStackTrace();
680
                        throw new GraphException(e);
681
                }
682

    
683
        }
684

    
685
        public GvFlag addFlagToNode(double x, double y, double tol) throws GraphException {
686
                Point2D nearestPoint = new Point2D.Double();
687
                int idArc = findClosestArc(x, y, tol, nearestPoint);
688
                if (idArc == -1)
689
                        return null;
690

    
691
                GvFlag flag = new GvFlag(x, y);
692
                flag.setIdArc(idArc);
693
                flag.setDirec(GvFlag.BOTH_DIRECTIONS);
694
                int idNode = getClosestIdNode(flag);
695
                
696
                GvNode node = graph.getNodeByID(idNode);
697
                flag.setOriginalPoint(node.getX(), node.getY());
698
                flag.setIdFlag(flags.size());
699
                flags.add(flag);
700
                callFlagsChanged(IFlagListener.FLAG_ADDED);
701
                return flag;
702

    
703
        }
704

    
705

    
706
        public void addFlag(GvFlag flag) {
707
                flags.add(flag);
708
                callFlagsChanged(IFlagListener.FLAG_ADDED);
709
        }
710

    
711
        public GvFlag[] getFlags() {
712
                ArrayList aux = new ArrayList();
713
                for (int i=0; i < getOriginaFlags().size(); i++)
714
                {
715
                        GvFlag flag = (GvFlag) getOriginaFlags().get(i);
716
                        if (flag.isEnabled()) aux.add(flag);
717
                }
718

    
719
                return (GvFlag[]) aux.toArray(new GvFlag[0]);
720
        }
721
        
722
        public int getFlagsCount(){
723
                return this.getOriginaFlags().size();
724
        }
725
        
726
        /**
727
         * Suitable to change directly the flags collection
728
         * @return
729
         */
730
        public ArrayList getOriginaFlags() {
731
                return flags;
732
        }
733

    
734

    
735
        public void setFlags(ArrayList flags) {
736
                this.flags = flags;
737
        }
738

    
739
        public IGraph getGraph() {
740
                return graph;
741
        }
742

    
743
        public void setGraph(IGraph graph) {
744
                this.graph = graph;
745
                numOriginalEdges = graph.numEdges();
746
                numOriginalNodes = graph.numVertices();
747
        }
748

    
749
        public FLyrVect getLayer() {
750
                return lyrVect;
751
        }
752

    
753
        public void setLayer(FLyrVect lyr) {
754
                this.lyrVect = lyr;
755
                this.featExtractor = new DefaultFeatureExtractor(lyr);
756
                // FJP: Workarround to avoid using SpatialIndex with reprojected layers
757
            if (lyrVect.getCoordTrans() != null) {
758
                    if (!lyrVect.getProjection().getAbrev().equals(lyrVect.getMapContext().getViewPort().getProjection().getAbrev()))
759
                            lyrVect.setISpatialIndex(null);
760
                }
761
                
762
                // fin 
763
                
764
        }
765

    
766
        public void removeFlags() {
767
                flags = new ArrayList();
768
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
769
        }
770
        
771
        public void removeFlag(GvFlag flag){
772
                flags.remove(flag);
773
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
774
        }
775

    
776
        void PartirArco(int idEdge, int idNode) {
777
                // Se supone que el nuevo Nodo YA est? creado. Aqui dentro se coge el
778
                // arco viejo y se le pega un tajo.
779
                // (Se modifican los enlaces de los nodos de ese arco y se crean los
780
                // arcos nuevos, fijando sus costes).
781
                // Para sacar el porcentaje nos aprovechamos de que el nuevo nodo est?
782
                // puesto en base a ese porcentaje
783
                // en distancia de los extremos.
784
                GvEdge oldEdge;
785
                GvNode pN1, pN2;
786
                double pct;
787

    
788
                oldEdge = graph.getEdgeByID(idEdge);
789

    
790
                // OJO, controlando los ceros por si acaso la recta es horizontal o
791
                // vertical (Y si mide cero???)
792

    
793
                // pN1 = &Nodos[Arcos[idArco].idNodo1];
794
                // pN2 = &Nodos[Arcos[idArco].idNodo2];
795
                pN1 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeOrig());
796
                pN2 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeEnd());
797
                GvNode newNode = graph.getNodeByID(idNode);
798

    
799
                if (newNode.getX() != pN1.getX())
800
                        pct = Math.abs((newNode.getX() - pN1.getX())
801
                                        / (pN2.getX() - pN1.getX()));
802
                else
803
                        pct = Math.abs((newNode.getY() - pN1.getY())
804
                                        / (pN2.getY() - pN1.getY()));
805

    
806
                GvEdge first = new GvEdge();
807
                first.setIdEdge(graph.numEdges());
808
                first.setIdArc(oldEdge.getIdArc());
809
                first.setDistance(oldEdge.getDistance() * pct);
810
                first.setWeight(oldEdge.getWeight() * pct);
811

    
812
                first.setDirec(oldEdge.getDirec());
813
                first.setIdNodeOrig(oldEdge.getIdNodeOrig());
814
                first.setType(oldEdge.getType());
815
                first.setIdNodeEnd(idNode);
816
                graph.addEdge(first);
817

    
818
                GvEdge second = new GvEdge();
819
                second.setIdEdge(graph.numEdges());
820
                second.setDistance(oldEdge.getDistance() * (1.0 - pct));
821
                second.setWeight(oldEdge.getWeight() * (1.0 - pct));
822
                second.setIdArc(oldEdge.getIdArc());
823
                second.setDirec(oldEdge.getDirec());
824
                second.setType(oldEdge.getType());
825
                second.setIdNodeOrig(idNode);
826
                second.setIdNodeEnd(oldEdge.getIdNodeEnd());
827
                graph.addEdge(second);
828

    
829
                // ////////////////////////////////////////////////////
830
                // Ahora retocamos los enlaces que salen de cada nodo
831
                // ////////////////////////////////////////////////////
832
                int i;
833
                // boolean encontrado = false;
834
//                for (i = 0; i < pN1.getOutputLinks().size(); i++) {
835
//                        GvEdge aux = (GvEdge) pN1.getOutputLinks().get(i);
836
//                        if (aux.getIdEdge() == idEdge) {
837
//                                pN1.getOutputLinks().set(i, first);
838
//                                // encontrado = true;
839
//                                break;
840
//                        }
841
//                } // for
842
                for (i = 0; i < pN1.getConnectors().size(); i++) {
843
                        GvConnector c = pN1.getConnectors().get(i);
844
                        if ((c.getEdgeOut() != null) && (c.getEdgeOut().getIdEdge()== idEdge)) {
845
                                c.setEdgeOut(first);
846
                                // encontrado = true;
847
                                break;
848
                        }
849
                } // for
850

    
851
                // Conector de entrada 
852
//                GvConnector newCon = new GvConnector();
853
//                newCon.setEdgeIn(first);
854
//                newNode.getConnectors().add(newCon);
855
                addInputLink(newNode, first);
856

    
857
                // Conector de salida 
858
//                GvConnector conOut = new GvConnector();
859
//                conOut.setEdgeOut(second);
860
//                newNode.getConnectors().add(conOut);
861
                addOutputLink(newNode, second);
862
                
863
                // Y hacemos que el conector de entrada del idNodo2 tenga el arco nuevo
864
                // log("Y hacemos que el conector de entrada del idNodo2 tenga el arco nuevo");
865
                for (i = 0; i < pN2.getConnectors().size(); i++) {
866
                        GvConnector c = pN2.getConnectors().get(i);
867
                        if ((c.getEdgeIn() != null) && (c.getEdgeIn().getIdEdge()== idEdge)) {
868
                                c.setEdgeIn(second);
869
                                // encontrado = true;
870
                                break;
871
                        }
872
                } // for
873
        }
874
        
875
        /**
876
         * Add an edge out to this node. This function takes care of creating the needed connectors
877
         * @param edge
878
         */
879
        private void addOutputLink(GvNode n, GvEdge edge) {
880
//                outputLinks.add(edge);
881
                // Create connectors
882
                // First, search the connector if it is already created
883
                GvConnector c;
884
                boolean bFound = false;
885
                GvConnector cFound = null;
886
                for (int iConec=0; iConec< n.getConnectors().size();  iConec++)
887
                {
888
                        c = n.getConnectors().get(iConec);
889
                        if ((c.getEdgeIn() != null) && (c.getEdgeIn().getIdNodeOrig() == edge.getIdNodeEnd())
890
                                && (c.getEdgeIn().getIdNodeEnd() == edge.getIdNodeOrig())) {
891
                                // Found. This connector has been originated before by the same edge
892
                                bFound = true;
893
                                cFound = c;
894
                                break;
895
                        }
896
                }
897
                if (!bFound) {
898
                        GvConnector newCon = new GvConnector();
899
                        newCon.setEdgeOut(edge);
900
                        n.getConnectors().add(newCon);
901
                }
902
                else
903
                {
904
                        cFound.setEdgeOut(edge);
905
                }
906
                
907
        }
908

    
909
        /**
910
         * Add an input edge to this node. This function takes care of creating the needed connectors
911
         * @param edge
912
         */
913
        private void addInputLink(GvNode n, GvEdge edge) {
914
//                inputLinks.add(edge);
915
                // First, search the connector if it is already created
916
                GvConnector c;
917
                boolean bFound = false;
918
                GvConnector cFound = null;
919
                for (int iConec=0; iConec< n.getConnectors().size();  iConec++)
920
                {
921
                        c = n.getConnectors().get(iConec);
922
                        if ((c.getEdgeOut() != null) && (c.getEdgeOut().getIdNodeOrig() == edge.getIdNodeEnd())
923
                                        && (c.getEdgeOut().getIdNodeEnd() == edge.getIdNodeOrig())) {
924
                                // Found. This connector has been originated before by the same arc
925
                                bFound = true;
926
                                cFound = c;
927
                                break;
928
                        }
929
                }
930
                if (!bFound) {
931
                        GvConnector newCon = new GvConnector();
932
                        newCon.setEdgeIn(edge);
933
                        n.getConnectors().add(newCon);
934
                }
935
                else
936
                {
937
                        cFound.setEdgeIn(edge);
938
                }
939
                
940
        }
941
        
942

    
943
        public ArrayList getModifiedCosts() {
944
                return modifiedCosts;
945
                
946
        }
947
        
948
        private int[] BuscaNodosDeTramo(EdgePair pair) {
949
                int[] resul = new int[2];
950
                if ((pair.idEdge == -1) && (pair.idInverseEdge == -1))
951
                {
952
                        return null; // Error: No existen esos arcos.
953
                }
954

    
955
                if (pair.idEdge != -1)
956
                {
957
                        resul[0] = graph.getEdgeByID(pair.idEdge).getIdNodeOrig();
958
                        resul[1]= graph.getEdgeByID(pair.idEdge).getIdNodeEnd();
959
                }
960
                else
961
                {
962
                        resul[0] = graph.getEdgeByID(pair.idInverseEdge).getIdNodeOrig();
963
                        resul[1]= graph.getEdgeByID(pair.idInverseEdge).getIdNodeEnd();
964
                }
965
                return resul;
966

    
967
        }
968

    
969
        public GvTurn addTurnCost(int idArcOrigin, int idArcDestination, double newCost) {
970
                GvTurn turnCost = new GvTurn(idArcOrigin, idArcDestination, newCost);                
971
                EdgePair edgePairFrom = getGraph().getEdgesByIdArc(idArcOrigin);
972
                EdgePair edgePairTo = getGraph().getEdgesByIdArc(idArcDestination);
973
                
974
                // We found the node that connects these arcs, 
975
                // and add the new turnCost to its list of turnCosts.
976
                GvNode searchedNode;
977
                int idNa1, idNa2, idNb1, idNb2, idNodoBuscado;
978
                int[] A, B;
979

    
980
                A = BuscaNodosDeTramo(edgePairFrom);
981
                if (A == null) return null; // No existen arcos para ese idTramo
982
                
983

    
984
                B = BuscaNodosDeTramo(edgePairTo);
985
                if (B == null) return null; // No existen arcos para ese idTramo
986

    
987
                idNa1 = A[0]; idNa2 = A[1];
988
                idNb1 = B[0]; idNb2 = B[1];
989

    
990
                // Buscamos el nodo que est? entre fromIdTramo y toIdTramo
991
                // y el arco. Al arco hay que cambiarle el destino
992
                if (idNa1 == idNb1)
993
                        idNodoBuscado = idNa1;
994
                else
995
                        if (idNa1 == idNb2)
996
                                idNodoBuscado = idNa1;
997
                        else
998
                                if (idNa2 == idNb1)
999
                                        idNodoBuscado = idNa2;
1000
                                else
1001
                                        if (idNa2 == idNb2)
1002
                                                idNodoBuscado = idNa2;
1003
                                        else // ERROR
1004
                                                return null; // esos tramos no conectan.
1005

    
1006
                // Podemos funcionar con idTramo en lugar de idArco porque cada CLink lleva dentro
1007
                // el idTramo que lo origin?, y en el algoritmo podemos mirarlo.
1008

    
1009
                searchedNode = graph.getNodeByID(idNodoBuscado);
1010
                searchedNode.addTurnCost(turnCost);                        
1011
                turnCosts.add(turnCost); //useful to remove them one by one without iterating the whole graph.
1012
                
1013
                return turnCost; // everything is fine
1014
        }
1015
        /**
1016
         * Create, add and apply a new modified cost to the graph. 
1017
         * @param idArc where the cost will be applied.
1018
         * @param newCost. -1 if you want tu put a BARRIER.
1019
         * @param direction. 1-> edge of digitalized direction. 2-> inverse edge. 3-> Both directions
1020
         */
1021
        public GvModifiedCost addModifiedCost(int idArc, double newCost, int direction) {
1022
                GvModifiedCost modifiedCost = new GvModifiedCost(idArc, newCost, direction);
1023
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
1024
                modifiedCost.setIdEdge(edgePair.idEdge);
1025
                modifiedCost.setIdInverseEdge(edgePair.idInverseEdge);
1026
                if (direction == 3)
1027
                {
1028
                        if (edgePair.getIdEdge() != -1)
1029
                        {
1030
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
1031
                                modifiedCost.setOldCost(edge.getWeight());
1032
                                edge.setWeight(-1.0);
1033
                        }
1034
                        if (edgePair.getIdInverseEdge() != -1)
1035
                        {
1036
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
1037
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
1038
                                inverseEdge.setWeight(-1.0);
1039
                        }
1040
                }
1041
                if (direction == 1)
1042
                {
1043
                        if (edgePair.getIdEdge() != -1)
1044
                        {
1045
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
1046
                                modifiedCost.setOldCost(edge.getWeight());
1047
                                edge.setWeight(-1.0);
1048
                        }
1049
                }
1050
                if (direction == 2)
1051
                {
1052
                        if (edgePair.getIdInverseEdge() != -1)
1053
                        {
1054
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
1055
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
1056
                                inverseEdge.setWeight(-1.0);
1057
                        }
1058
                }
1059
                modifiedCosts.add(modifiedCost);
1060
                modifiedCost.setApplied(true);
1061
                return modifiedCost;
1062
        }
1063
        
1064
        /**
1065
         * Remove ALL turn costs
1066
         */
1067
        public void removeTurnCosts() {
1068
                for (int i=0; i < turnCosts.size(); i++) {
1069
                        GvTurn turn = turnCosts.get(i);
1070
//                        turn.getNode().getTurnCosts().remove(turn);
1071
                        if (turn.getNode() == null)
1072
                        {
1073
                                System.err.println("El turnCost " + i + " no tiene nodo asociado.");
1074
                                continue;
1075
                        }
1076
                        turn.getNode().removeTurnCosts();
1077
                }
1078
                turnCosts = new ArrayList<GvTurn>();
1079
        }
1080

    
1081
        /**
1082
         * Be careful about the ORDER!!!!
1083
         * @param modifiedCost
1084
         */
1085
        public boolean removeModifiedCost(GvModifiedCost modifiedCost) {
1086
                if (!modifiedCosts.remove(modifiedCost))
1087
                        return false;
1088
                int idArc = modifiedCost.getIdArc();
1089
                int direction = modifiedCost.getDirection();
1090
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
1091
                if (direction == 3)
1092
                {
1093
                        if (edgePair.getIdEdge() != -1)
1094
                        {
1095
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
1096
                                edge.setWeight(modifiedCost.getOldCost());
1097
                        }
1098
                        if (edgePair.getIdInverseEdge() != -1)
1099
                        {
1100
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
1101
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
1102
                        }
1103
                }
1104
                if (direction == 1)
1105
                {
1106
                        if (edgePair.getIdEdge() != -1)
1107
                        {
1108
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
1109
                                edge.setWeight(modifiedCost.getOldCost());
1110
                        }
1111
                }
1112
                if (direction == 2)
1113
                {
1114
                        if (edgePair.getIdInverseEdge() != -1)
1115
                        {
1116
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
1117
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
1118
                        }
1119
                }
1120
                return true;
1121
        }
1122

    
1123
        public void addFlagListener(IFlagListener listener) {
1124
                if (!flagListeners.contains(listener)) {
1125
                        flagListeners.add(listener);
1126
                }
1127
        }
1128
        
1129
        public void removeFlagListener(IFlagListener listener){
1130
                flagListeners.remove(listener);
1131
        }
1132
        
1133
        private void callFlagsChanged(int reason) {
1134
                if (dispatching) {
1135
                        for (int i=0; i < flagListeners.size(); i++)
1136
                        {
1137
                                IFlagListener listener = (IFlagListener) flagListeners.get(i);
1138
                                listener.flagsChanged(reason);
1139
                        }
1140
                }
1141
        }
1142
        
1143
        /**
1144
         * Useful to do batch modifies. (For example, add lot of flags
1145
         * and when finished (endModifying), throw event.
1146
         */
1147
        public void beginModifyingFlags() {
1148
                dispatching = false;
1149
        }
1150

    
1151
        public void endModifyingFlags() {
1152
                dispatching = true;
1153
                callFlagsChanged(IFlagListener.FLAG_MANY_CHANGES);
1154
        }
1155
        /**
1156
         * Mueve un flag de la posici?n from a la posici?n to.
1157
         *
1158
         * @param from origen.
1159
         * @param to destino.
1160
         * 
1161
         */
1162
        public void moveTo(int from, int to) throws CancelationException {
1163
                int newfrom=flags.size()-from-1;
1164
                int newto=flags.size()-to-1;
1165
                if ( newfrom < 0 || newfrom >=flags.size() || newto < 0 || newto >= flags.size()) return;
1166
                GvFlag aux = (GvFlag) flags.get(newfrom);
1167
                flags.remove(newfrom);
1168
                flags.add(newto, aux);
1169
                callFlagsChanged(IFlagListener.FLAG_REORDER);
1170
        }
1171

    
1172
        public ArrayList getEdgeTypes() {
1173
                // TODO: Tener esto precalculado
1174
                TreeMap map = new TreeMap();
1175
                ArrayList ret = new ArrayList();
1176
                for (int i = 0; i < graph.numEdges(); i++)
1177
                {
1178
                        GvEdge edge = graph.getEdgeByID(i);
1179
                        Integer type = new Integer(edge.getType());
1180
                        if (!map.containsKey(type))
1181
                        {
1182
                                map.put(type, type);                                
1183
                        }
1184
                }
1185
                Iterator it = map.entrySet().iterator();
1186
                while (it.hasNext())
1187
                {
1188
                        Map.Entry entry = (Map.Entry) it.next();
1189
                        Integer type = (Integer) entry.getKey();
1190
                        ret.add(type);
1191
                }
1192
                return ret;
1193
        }
1194

    
1195
        public Hashtable getVelocities() {
1196
                return velocities ;
1197
        }
1198

    
1199
        public void setVelocities(Hashtable veloMeters) {
1200
                for (int i=0; i < getGraph().numEdges(); i++)
1201
                {
1202
                        GvEdge edge = getGraph().getEdgeByID(i);
1203
                        
1204
                        Integer key = new Integer(edge.getType());
1205
                        Double vel = (Double) veloMeters.get(key);
1206
                        edge.setWeight(edge.getDistance() / vel.doubleValue()); // segundos
1207
                }
1208
                this.velocities = veloMeters;
1209

    
1210
                
1211
        }
1212

    
1213
        public ArrayList<GvTurn> getTurnCosts() {
1214
                return turnCosts;
1215
        }
1216

    
1217
        public IFeatureExtractor getFeatExtractor() {
1218
                return featExtractor;
1219
        }
1220

    
1221
        public void setFeatExtractor(IFeatureExtractor featExtractor) {
1222
                this.featExtractor = featExtractor;
1223
                if (featExtractor instanceof DefaultFeatureExtractor) {
1224
                        setLayer(((DefaultFeatureExtractor) featExtractor).getLyrVect());
1225
                }
1226
        }
1227

    
1228
}