Statistics
| Revision:

svn-gvsig-desktop / tags / v1_1_2_Build_1044 / prototypes / VectorialAvanzado / extensions / extGraph / src / com / iver / cit / gvsig / graph / core / Network.java @ 20099

History | View | Annotate | Download (26.3 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package com.iver.cit.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 com.iver.cit.gvsig.fmap.DriverException;
52
import com.iver.cit.gvsig.fmap.core.IGeometry;
53
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
54
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
55
import com.iver.cit.gvsig.fmap.layers.CancelationException;
56
import com.iver.cit.gvsig.fmap.layers.FBitSet;
57
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
58
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
59
import com.vividsolutions.jts.geom.Coordinate;
60
import com.vividsolutions.jts.geom.LineSegment;
61
import com.vividsolutions.jts.geom.MultiLineString;
62

    
63
public class Network {
64
        protected FLyrVect lyrVect;
65

    
66
        protected IGraph graph;
67

    
68
        protected ArrayList flags = new ArrayList();
69

    
70
        protected int numOriginalEdges;
71

    
72
        protected int numOriginalNodes;
73

    
74
        private ArrayList modifiedCosts = new ArrayList();
75
        private ArrayList flagListeners = new ArrayList();
76
        private boolean dispatching = true;
77

    
78
        private Hashtable velocities = null;
79

    
80
        public void reconstruyeTramo(int idArc) {
81
                GvNode pN1;
82
                int i;
83
                
84
                // Si encontramos un enlace con idEdge >= numOriginalEdges, lo cambiamos.
85
                // Y CON ESE IDarc!!
86
                // Si hay varios, no pasa nada, volvemos a llamar a esta funci?n con IdTramo
87

    
88
                EdgePair edgePair = graph.getEdgesByIdArc(idArc);
89
                if (edgePair.getIdEdge() != -1)
90
                {
91
                        // Restauramos los enlaces de los nodos de ese tramo.
92
//                        pN1 = &Nodos[Arcos[IndiceArcos[idTramo].idArco].idNodo1];
93
//                        pN2 = &Nodos[Arcos[IndiceArcos[idTramo].idArco].idNodo2];
94
                        GvEdge edge = graph.getEdgeByID(edgePair.getIdEdge());
95
                        pN1 = graph.getNodeByID(edge.getIdNodeOrig());
96

    
97
                        // Metemos idArco en los enlaces de Nodo1
98
                        for (i=0; i< pN1.getEnlaces().size(); i++)
99
                        {
100
                                GvEdge auxEdge = (GvEdge) pN1.getEnlaces().get(i);
101
                                if (auxEdge.getIdArc() == idArc)
102
                                {
103
                                        if (auxEdge.getIdEdge() >= numOriginalEdges) 
104
                                        {
105
                                                pN1.getEnlaces().set(i, graph.getEdgeByID(edgePair.getIdEdge()));
106
                                                break;
107
                                        }
108
                                }
109
                        }
110
                }
111

    
112
                if (edgePair.idInverseEdge != -1)
113
                {
114
//                        pN1 = &Nodos[Arcos[IndiceArcos[idTramo].idContraArco].idNodo1];
115
//                        pN2 = &Nodos[Arcos[IndiceArcos[idTramo].idContraArco].idNodo2];
116
                        GvEdge edge = graph.getEdgeByID(edgePair.getIdInverseEdge());
117
                        pN1 = graph.getNodeByID(edge.getIdNodeOrig());
118

    
119
                        for (i=0; i< pN1.getEnlaces().size(); i++)
120
                        {
121
                                if (edge.getIdArc() == idArc)
122
                                {
123
                                        GvEdge auxEdge = (GvEdge) pN1.getEnlaces().get(i);
124
                                        if (auxEdge.getIdEdge() >= numOriginalEdges) 
125
                                        {
126
                                                pN1.getEnlaces().set(i, graph.getEdgeByID(edgePair.getIdInverseEdge()));
127
                                                break;
128
                                        }
129
                                }
130
                        }
131
                }
132

    
133
                int numEdges = graph.numEdges();
134
                int numNodes = graph.numVertices();
135
                for (int idEdge = numEdges-1; idEdge >= numOriginalEdges; idEdge--)
136
                {
137
                        graph.removeEdge(idEdge);
138
                }
139
                for (int idNode = numNodes-1; idNode >= numOriginalNodes; idNode--)
140
                {
141
                        graph.removeNode(idNode);
142
                }
143

    
144
        }
145

    
146
        /**
147
         * Closest ID to this point. -1 if out from tolerance.
148
         * @param x
149
         * @param y
150
         * @param tolerance
151
         * @param nearest. Point to receive the nearest point ON arc.
152
         * @return
153
         */
154
        public int findClosestArc(double x, double y, double tolerance, Point2D nearestPoint) {
155
                Point2D p = new Point2D.Double(x, y);
156
                FBitSet bitSet;
157
                try {
158
                        bitSet = lyrVect.queryByPoint(p, tolerance);
159
                        VectorialAdapter va = (VectorialAdapter) lyrVect.getSource();
160
                        va.start();
161
                        double minDist = tolerance;
162
                        int foundGeom = -1;
163
                        for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet
164
                                        .nextSetBit(i + 1)) {
165
                                IGeometry geom;
166
                                geom = va.getShape(i);
167
                                Point2D nearest = getNearestPoint(p, geom, tolerance);
168
                                if (nearest != null) {
169
                                        double dist = nearest.distance(p);
170
                                        if (dist < minDist) {
171
                                                minDist = dist;
172
                                                foundGeom = i;
173
                                                nearestPoint.setLocation(nearest);
174
                                        }
175
                                }
176
                        }
177
                        va.stop();
178
                        return foundGeom;
179
                } catch (DriverException e1) {
180
                        // TODO Auto-generated catch block
181
                        e1.printStackTrace();
182
                } catch (DriverIOException e) {
183
                        // TODO Auto-generated catch block
184
                        e.printStackTrace();
185
                }
186
                return -1;
187

    
188
        }
189

    
190
        protected Point2D getNearestPoint(Point2D point, IGeometry geom,
191
                        double tolerance) {
192
                Point2D resul = null;
193
                Coordinate c = new Coordinate(point.getX(), point.getY());
194

    
195
                PathIterator theIterator = geom.getPathIterator(null,
196
                                FConverter.FLATNESS); // polyLine.getPathIterator(null,
197
                                                                                // flatness);
198
                double[] theData = new double[6];
199
                double minDist = tolerance;
200
                Coordinate from = null, first = null;
201
                while (!theIterator.isDone()) {
202
                        // while not done
203
                        int theType = theIterator.currentSegment(theData);
204

    
205
                        switch (theType) {
206
                        case PathIterator.SEG_MOVETO:
207
                                from = new Coordinate(theData[0], theData[1]);
208
                                first = from;
209
                                break;
210

    
211
                        case PathIterator.SEG_LINETO:
212

    
213
                                // System.out.println("SEG_LINETO");
214
                                Coordinate to = new Coordinate(theData[0], theData[1]);
215
                                LineSegment line = new LineSegment(from, to);
216
                                Coordinate closestPoint = line.closestPoint(c);
217
                                double dist = c.distance(closestPoint);
218
                                if ((dist < minDist)) {
219
                                        resul = new Point2D.Double(closestPoint.x, closestPoint.y);
220
                                        minDist = dist;
221
                                }
222

    
223
                                from = to;
224
                                break;
225
                        case PathIterator.SEG_CLOSE:
226
                                line = new LineSegment(from, first);
227
                                closestPoint = line.closestPoint(c);
228
                                dist = c.distance(closestPoint);
229
                                if ((dist < minDist)) {
230
                                        resul = new Point2D.Double(closestPoint.x, closestPoint.y);
231
                                        minDist = dist;
232
                                }
233

    
234
                                from = first;
235
                                break;
236

    
237
                        } // end switch
238

    
239
                        theIterator.next();
240
                }
241

    
242
                return resul;
243
        }
244

    
245
        /**
246
         * TODO: POR TERMINAR!!!
247
         * 
248
         * @param flag
249
         * @return
250
         */
251
        public int creaArcosVirtuales(GvFlag flag) {
252
                // Devuelve el idNodo del nodo virtual creado.
253
                /*
254
                 * 0.- Creamos el nuevo Nodo virtual. 1.- Recorremos los arcos nuevos
255
                 * mirando su idTramo. 2.- Si existe ese idtramo=> Ya hemos partido
256
                 * antes ese idTramo. Buscamos el arco virtual que contiene ese nodo y
257
                 * lo partimos. Ojo, recorrer hasta el final los tramos para asegurarnos
258
                 * de que es el trozo m?s peque?o. 3.- Si NO existe, utilizamos el
259
                 * IndiceArcos para coger los arcos que toca y partirlos.
260
                 * 
261
                 * 4.- OJO: Si el porcentaje es 0 ? 100, no partimos el arco, devolvemos
262
                 * el id del nodo que toca.
263
                 */
264
                // NUEVO: 20/7/2004:
265
                // Cuando trabajamos con sentidos, al partir un arco no podemos insertar
266
                // 2 nuevos sin mirar
267
                // si es o no de un ?nico sentido.) (Mirar idArco. Si es -1, no partimos
268
                // el arco).
269
                // FIN NUEVO
270
                int idNodo1, idNodo2;
271
                int idArco, elIdArco, elIdContraArco;
272
                boolean encontrado;
273
                GvNode newNode;
274

    
275
                // Sacamos los idNodos del tramo
276
                EdgePair edgePair = graph.getEdgesByIdArc(flag.getIdArc());
277
                if (edgePair.getIdEdge() != -1) {
278
                        // idNodo1 = Arcos[IndiceArcos[idTramo].idArco].idNodo1;
279
                        // idNodo2 = Arcos[IndiceArcos[idTramo].idArco].idNodo2;
280
                        idNodo1 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeOrig();
281
                        idNodo2 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeEnd();
282

    
283
                } else {
284
                        // idNodo2 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo1;
285
                        // idNodo1 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo2;
286
                        idNodo2 = graph.getEdgeByID(edgePair.getIdInverseEdge())
287
                                        .getIdNodeOrig();
288
                        idNodo1 = graph.getEdgeByID(edgePair.getIdInverseEdge())
289
                                        .getIdNodeEnd();
290

    
291
                }
292

    
293
                if (flag.getPct() == 0)
294
                        return idNodo1;
295
                if (flag.getPct() == 1)
296
                        return idNodo2;
297

    
298
                // Creamos el nodo de enmedio
299

    
300
                // if (numNodos == maxNodos) // La jodimos, T?rtola, hay que usar
301
                // reallocate
302
                // {
303
                // // NOTA: ESTO EN DEBUG HACE QUE FALLE AL USAR DESPUES EnlacesSTL. ES
304
                // POR NO S? QU? HISTORIA
305
                // // DEL HEAP. EN RELEASE NO FALLA. (TAMPOCO S? SI FASTIDIA ALGO).
306
                // Nodos = (CNode *) realloc(Nodos,(numNodos + MAX_RESERVA_NODOS) *
307
                // sizeof(CNode)); // Deber?amos chequear que devuelve algo correcto
308
                // maxNodos = numNodos + MAX_RESERVA_NODOS;
309
                // }
310

    
311
                newNode = new GvNode();
312
                // Nodo = &Nodos[numNodos];
313

    
314
                // pNuevoNodo->idNodo = numNodos;
315
                newNode.setIdNode(graph.numVertices());
316

    
317
                // OJO: Las coordenadas estas puede que no tengan que ver con la
318
                // realidad. Algo m?s correcto
319
                // ser?a tener en cuenta el shape de verdad, pero creo que no influye en
320
                // el resultado final.
321
                // pNuevoNodo->x = Nodos[idNodo1].x + (Nodos[idNodo2].x -
322
                // Nodos[idNodo1].x) * Porcentaje;
323
                // pNuevoNodo->y = Nodos[idNodo1].y + (Nodos[idNodo2].y -
324
                // Nodos[idNodo1].y) * Porcentaje;
325
                GvNode node1 = graph.getNodeByID(idNodo1);
326
                GvNode node2 = graph.getNodeByID(idNodo2);
327
                newNode.setX(node1.getX() + (node2.getX() - node1.getX())
328
                                * flag.getPct());
329
                newNode.setY(node1.getY() + (node2.getY() - node1.getY())
330
                                * flag.getPct());
331
                graph.addNode(newNode);
332
                Coordinate newC = new Coordinate(newNode.getX(), newNode.getY());
333

    
334
                encontrado = false;
335

    
336
                elIdArco = -1;
337
                elIdContraArco = -1;
338

    
339
                boolean bIdTramoYaPartido = false;
340

    
341
                // TODO: POR AQUI VOY
342
                for (idArco = numOriginalEdges; idArco < graph.numEdges(); idArco++) {
343
                        GvEdge addedEdge = graph.getEdgeByID(idArco);
344
                        if (addedEdge.getIdArc() == flag.getIdArc()) {
345
                                bIdTramoYaPartido = true;
346

    
347
                                idNodo1 = addedEdge.getIdNodeOrig();
348
                                idNodo2 = addedEdge.getIdNodeEnd();
349

    
350
                                // Comprobamos si est? enmedio
351
                                GvNode n1 = graph.getNodeByID(idNodo1);
352
                                GvNode n2 = graph.getNodeByID(idNodo2);
353
                                Coordinate c1 = new Coordinate(n1.getX(), n1.getY());
354
                                Coordinate c2 = new Coordinate(n2.getX(), n2.getY());
355
                                LineSegment line = new LineSegment(c1, c2);
356
                                double t = line.projectionFactor(newC);
357

    
358
                                // Si la proyecci?n es positiva y menor que la magnitud d, est?
359
                                // en medio
360
                                if ((t >= 0) && (t <= 1)) {
361
                                        encontrado = true;
362
                                        if (t == 0)
363
                                                return idNodo1; // No partimos
364
                                        if (t == 1)
365
                                                return idNodo2; // Tampoco partimos
366

    
367
                                        if (addedEdge.getDirec() == 1)
368
                                                elIdArco = idArco;
369
                                        else
370
                                                elIdContraArco = idArco;
371

    
372
                                } // if est? enmedio
373
                        } // if idTramo encontrado
374
                } // for idArco
375
                if (bIdTramoYaPartido && (!encontrado))
376
                        throw new RuntimeException(
377
                                        "Algo va mal con lo del producto escalar");
378

    
379
                if (encontrado) {
380
                        // sprintf(Mensaje,"Voy a partir el idTramo= %ld (idArco
381
                        // %ld)",idTramo,elIdArco);
382
                        // MessageBox(NULL,Mensaje,"",MB_OK);
383
                        if (elIdArco != -1)
384
                                PartirArco(elIdArco, newNode.getIdNode());
385

    
386
                        if (elIdContraArco != -1)
387
                                PartirArco(elIdContraArco, newNode.getIdNode());
388
                } else {
389
                        // Creamos 2 Arcos por cada arco que ten?amos antes.
390
                        if (edgePair.getIdEdge() != -1)
391
                                PartirArco(edgePair.getIdEdge(), newNode.getIdNode());
392

    
393
                        if (edgePair.getIdInverseEdge() != -1)
394
                                PartirArco(edgePair.getIdInverseEdge(), newNode.getIdNode());
395

    
396
                } // else encontrado
397

    
398
                return newNode.getIdNode();
399

    
400
        }
401

    
402
        /**
403
         * Cogemos el nodo m?s cercano y ponemos el pct a ese flag.
404
         * 
405
         * @param flag
406
         * @return
407
         */
408
        public int getClosestIdNode(GvFlag flag) {
409
                EdgePair pair = graph.getEdgesByIdArc(flag.getIdArc());
410
                if (pair.getIdEdge() != -1) {
411
                        GvEdge edge = graph.getEdgeByID(pair.getIdEdge());
412
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
413
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
414

    
415
                        double dist1 = flag.getOriginalPoint().distance(from.getX(),
416
                                        from.getY());
417
                        double dist2 = flag.getOriginalPoint().distance(to.getX(),
418
                                        to.getY());
419
                        if (dist1 < dist2) {
420
                                flag.setPct(0);
421
                                return from.getIdNode();
422
                        }
423
                        else
424
                        {
425
                                flag.setPct(1.0);
426
                                return to.getIdNode();
427
                        }
428
                } else {
429
                        GvEdge edge = graph.getEdgeByID(pair.getIdInverseEdge());
430
                        GvNode from = graph.getNodeByID(edge.getIdNodeOrig());
431
                        GvNode to = graph.getNodeByID(edge.getIdNodeEnd());
432

    
433
                        double dist1 = flag.getOriginalPoint().distance(from.getX(),
434
                                        from.getY());
435
                        double dist2 = flag.getOriginalPoint().distance(to.getX(),
436
                                        to.getY());
437
                        if (dist1 < dist2)
438
                        {
439
                                flag.setPct(0);
440
                                return from.getIdNode();
441
                        }
442
                        else
443
                        {
444
                                flag.setPct(1.0);
445
                                return to.getIdNode();
446
                        }
447
                        // if (flag.getPct() < 0.5)
448
                        // return to.getIdNode();
449
                        // else
450
                        // return from.getIdNode();
451
                }
452
        }
453

    
454
        /**
455
         * @param idArc
456
         * @param x
457
         * @param y
458
         * @return entre 0.0 y 1.0
459
         * @throws DriverIOException
460
         */
461
        private double percentAlong(int idArc, double x, double y)
462
                        throws DriverIOException {
463
                // Le pasamos el idTramo, la coordenada X de donde hemos pulsado y la
464
                // coordenada Y
465
                // Primero calculamos la longitud total del shape.
466
                // Luego calculamos el punto m?s cercano y su distancia para cada
467
                // segmento del shape.
468
                // Nos quedamos con el que est? m?s cerca y luego recorremos hasta ?l
469
                // acumulando distancia.
470
                // Finalmente, dividimos esa distancia por la longitud total.
471
                lyrVect.getSource().start();
472
                IGeometry geom = lyrVect.getSource().getShape(idArc);
473
                MultiLineString jtsGeom = (MultiLineString) geom.toJTSGeometry();
474

    
475
                Coordinate[] coords = jtsGeom.getCoordinates();
476

    
477
                Coordinate userCoord = new Coordinate(x, y);
478

    
479
                double longReal = 0;
480
                // Le pegamos una primera pasada para saber su longitud real.
481
                // OJO, NO TRABAJAMOS CON SHAPES MULTIPARTE, NO TIENE SENTIDO CON LAS
482
                // REDES (CREO)
483
                // POR ESO SUPONEMOS UNA ?NICA PARTE (L?NEA CONT?NUA)
484
                // A la vez calculamos el punto m?s cercano y su distancia para cada
485
                // segmento.
486
                double minDist = Double.MAX_VALUE;
487
                double distTo = 0;
488
                double dist = 0;
489
                Coordinate cOrig = null;
490
                Coordinate closestPoint = null;
491
                for (int j = 0; j < coords.length - 1; j++) {
492
                        Coordinate c1 = coords[j];
493
                        Coordinate c2 = coords[j + 1];
494
                        LineSegment line = new LineSegment(c1, c2);
495

    
496
                        Coordinate auxPoint = line.closestPoint(userCoord);
497
                        dist = userCoord.distance(auxPoint);
498
                        if ((dist < minDist)) {
499
                                minDist = dist;
500
                                cOrig = c1;
501
                                closestPoint = auxPoint;
502
                                distTo = longReal;
503
                        }
504
                        longReal += line.getLength();
505
                }
506
                lyrVect.getSource().stop();
507
                dist = cOrig.distance(closestPoint);
508
                double longBuscada = distTo + dist;
509

    
510
                double pct;
511
                if (longReal > 0)
512
                        pct = longBuscada / longReal;
513
                else
514
                        pct = 0.0;
515

    
516
                return pct;
517
        }
518

    
519
        /**
520
         * Adds a flag on a network. flagDirection set if the flag must be on left
521
         * or right edge.
522
         * 
523
         * @param x
524
         * @param y
525
         * @param flagDirection
526
         * @param tol
527
         *            tolerance in map units
528
         * @return null if there is no place to add flag. You can increase the
529
         *         tolerance, then.
530
         * @throws GraphException
531
         */
532
        public GvFlag addFlag(double x, double y, int flagDirection, double tol)
533
                        throws GraphException {
534
                try {
535
                        Point2D nearestPoint = new Point2D.Double();
536
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
537
                        if (idArc == -1)
538
                                return null;
539
                        GvFlag flag = new GvFlag(x, y);
540
                        flag.setIdArc(idArc);
541

    
542
                        flag.setPct(percentAlong(idArc, x, y));
543
                        flag.setDirec(flagDirection);
544
                        flag.setIdFlag(flags.size());
545
                        callFlagsChanged(IFlagListener.FLAG_ADDED);
546
                        return flag;
547
                } catch (DriverIOException e) {
548
                        e.printStackTrace();
549
                        throw new GraphException(e);
550
                }
551

    
552
        }
553

    
554
        /**
555
         * Adds 2 flags on a network. (On both sides of an arc)
556
         * 
557
         * @param x
558
         * @param y
559
         * @param tol
560
         *            tolerance in map units
561
         * @return null if there is no place to add flag. You can increase the
562
         *         tolerance, then.
563
         * @throws GraphException 
564
         */
565
        public GvFlag addFlag(double x, double y, double tol) throws GraphException {
566
                try {
567
                        Point2D nearestPoint = new Point2D.Double();
568
                        int idArc = findClosestArc(x, y, tol, nearestPoint);
569
                        if (idArc == -1)
570
                                return null;
571

    
572
                        GvFlag flag = new GvFlag(x, y);
573
                        flag.setIdArc(idArc);
574
                        EdgePair edgePair = graph.getEdgesByIdArc(idArc);
575
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
576

    
577
                        flag.setPct(percentAlong(idArc, x, y));
578
                        flag.setIdFlag(flags.size());
579
                        flags.add(flag);
580
                        callFlagsChanged(IFlagListener.FLAG_ADDED);
581
                        return flag;
582
                } catch (DriverIOException e) {
583
                        e.printStackTrace();
584
                        throw new GraphException(e);
585
                }
586

    
587
        }
588

    
589
        /**
590
         * Create a flag in both directions, but NOT add it to the Network.
591
         * We use it on onetomany solver
592
         * @param x
593
         * @param y
594
         * @param tol
595
         * @return
596
         * @throws GraphException
597
         */
598
        public GvFlag createFlag(double x, double y, double tol) 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

    
605
                        GvFlag flag = new GvFlag(x, y);
606
                        flag.setIdArc(idArc);
607
//                        EdgePair edgePair = graph.getEdgesByIdArc(idArc);
608
                        flag.setDirec(GvFlag.BOTH_DIRECTIONS);
609

    
610
                        flag.setPct(percentAlong(idArc, x, y));
611
                        flag.setIdFlag(flags.size());
612
                        return flag;
613
                } catch (DriverIOException e) {
614
                        e.printStackTrace();
615
                        throw new GraphException(e);
616
                }
617

    
618
        }
619

    
620
        public GvFlag addFlagToNode(double x, double y, double tol) throws GraphException {
621
                Point2D nearestPoint = new Point2D.Double();
622
                int idArc = findClosestArc(x, y, tol, nearestPoint);
623
                if (idArc == -1)
624
                        return null;
625

    
626
                GvFlag flag = new GvFlag(x, y);
627
                flag.setIdArc(idArc);
628
                flag.setDirec(GvFlag.BOTH_DIRECTIONS);
629
                int idNode = getClosestIdNode(flag);
630
                
631
                GvNode node = graph.getNodeByID(idNode);
632
                flag.setOriginalPoint(node.getX(), node.getY());
633
                flag.setIdFlag(flags.size());
634
                flags.add(flag);
635
                callFlagsChanged(IFlagListener.FLAG_ADDED);
636
                return flag;
637

    
638
        }
639

    
640

    
641
        public void addFlag(GvFlag flag) {
642
                flags.add(flag);
643
                callFlagsChanged(IFlagListener.FLAG_ADDED);
644
        }
645

    
646
        public GvFlag[] getFlags() {
647
                ArrayList aux = new ArrayList();
648
                for (int i=0; i < getOriginaFlags().size(); i++)
649
                {
650
                        GvFlag flag = (GvFlag) getOriginaFlags().get(i);
651
                        if (flag.isEnabled()) aux.add(flag);
652
                }
653

    
654
                return (GvFlag[]) aux.toArray(new GvFlag[0]);
655
        }
656
        
657
        /**
658
         * Suitable to change directly the flags collection
659
         * @return
660
         */
661
        public ArrayList getOriginaFlags() {
662
                return flags;
663
        }
664

    
665

    
666
        public void setFlags(ArrayList flags) {
667
                this.flags = flags;
668
        }
669

    
670
        public IGraph getGraph() {
671
                return graph;
672
        }
673

    
674
        public void setGraph(IGraph graph) {
675
                this.graph = graph;
676
                numOriginalEdges = graph.numEdges();
677
                numOriginalNodes = graph.numVertices();
678
        }
679

    
680
        public FLyrVect getLayer() {
681
                return lyrVect;
682
        }
683

    
684
        public void setLayer(FLyrVect lyr) {
685
                this.lyrVect = lyr;
686
        }
687

    
688
        public void removeFlags() {
689
                flags = new ArrayList();
690
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
691
        }
692
        
693
        public void removeFlag(GvFlag flag){
694
                flags.remove(flag);
695
                callFlagsChanged(IFlagListener.FLAG_REMOVED);
696
        }
697

    
698
        void PartirArco(int idEdge, int idNode) {
699
                // Se supone que el nuevo Nodo YA est? creado. Aqui dentro se coge el
700
                // arco viejo y se le pega un tajo.
701
                // (Se modifican los enlaces de los nodos de ese arco y se crean los
702
                // arcos nuevos, fijando sus costes).
703
                // Para sacar el porcentaje nos aprovechamos de que el nuevo nodo est?
704
                // puesto en base a ese porcentaje
705
                // en distancia de los extremos.
706
                GvEdge oldEdge;
707
                GvNode pN1, pN2;
708
                double pct;
709

    
710
                oldEdge = graph.getEdgeByID(idEdge);
711

    
712
                // OJO, controlando los ceros por si acaso la recta es horizontal o
713
                // vertical (Y si mide cero???)
714

    
715
                // pN1 = &Nodos[Arcos[idArco].idNodo1];
716
                // pN2 = &Nodos[Arcos[idArco].idNodo2];
717
                pN1 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeOrig());
718
                pN2 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeEnd());
719
                GvNode newNode = graph.getNodeByID(idNode);
720

    
721
                if (newNode.getX() != pN1.getX())
722
                        pct = Math.abs((newNode.getX() - pN1.getX())
723
                                        / (pN2.getX() - pN1.getX()));
724
                else
725
                        pct = Math.abs((newNode.getY() - pN1.getY())
726
                                        / (pN2.getY() - pN1.getY()));
727

    
728
                GvEdge first = new GvEdge();
729
                first.setIdEdge(graph.numEdges());
730
                first.setIdArc(oldEdge.getIdArc());
731
                first.setDistance(oldEdge.getDistance() * pct);
732
                first.setWeight(oldEdge.getWeight() * pct);
733

    
734
                first.setDirec(oldEdge.getDirec());
735
                first.setIdNodeOrig(oldEdge.getIdNodeOrig());
736
                first.setType(oldEdge.getType());
737
                first.setIdNodeEnd(idNode);
738
                graph.addEdge(first);
739

    
740
                GvEdge second = new GvEdge();
741
                second.setIdEdge(graph.numEdges());
742
                second.setDistance(oldEdge.getDistance() * (1.0 - pct));
743
                second.setWeight(oldEdge.getWeight() * (1.0 - pct));
744
                second.setIdArc(oldEdge.getIdArc());
745
                second.setDirec(oldEdge.getDirec());
746
                second.setType(oldEdge.getType());
747
                second.setIdNodeOrig(idNode);
748
                second.setIdNodeEnd(oldEdge.getIdNodeEnd());
749
                graph.addEdge(second);
750

    
751
                // ////////////////////////////////////////////////////
752
                // Ahora retocamos los enlaces que salen de cada nodo
753
                // ////////////////////////////////////////////////////
754
                int i;
755
                // boolean encontrado = false;
756
                for (i = 0; i < pN1.getEnlaces().size(); i++) {
757
                        GvEdge aux = (GvEdge) pN1.getEnlaces().get(i);
758
                        if (aux.getIdEdge() == idEdge) {
759
                                pN1.getEnlaces().set(i, first);
760
                                // encontrado = true;
761
                                break;
762
                        }
763
                } // for
764

    
765
                newNode.getEnlaces().add(second);
766

    
767
        }
768

    
769
        public ArrayList getModifiedCosts() {
770
                return modifiedCosts;
771
                
772
        }
773

    
774
        /**
775
         * Create, add and apply a new modified cost to the graph. 
776
         * @param idArc where the cost will be applied.
777
         * @param newCost. -1 if you want tu put a BARRIER.
778
         * @param direction. 1-> edge of digitalized direction. 2-> inverse edge. 3-> Both directions
779
         */
780
        public GvModifiedCost addModifiedCost(int idArc, double newCost, int direction) {
781
                GvModifiedCost modifiedCost = new GvModifiedCost(idArc, newCost, direction);
782
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
783
                modifiedCost.setIdEdge(edgePair.idEdge);
784
                modifiedCost.setIdInverseEdge(edgePair.idInverseEdge);
785
                if (direction == 3)
786
                {
787
                        if (edgePair.getIdEdge() != -1)
788
                        {
789
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
790
                                modifiedCost.setOldCost(edge.getWeight());
791
                                edge.setWeight(-1.0);
792
                        }
793
                        if (edgePair.getIdInverseEdge() != -1)
794
                        {
795
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
796
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
797
                                inverseEdge.setWeight(-1.0);
798
                        }
799
                }
800
                if (direction == 1)
801
                {
802
                        if (edgePair.getIdEdge() != -1)
803
                        {
804
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
805
                                modifiedCost.setOldCost(edge.getWeight());
806
                                edge.setWeight(-1.0);
807
                        }
808
                }
809
                if (direction == 2)
810
                {
811
                        if (edgePair.getIdInverseEdge() != -1)
812
                        {
813
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
814
                                modifiedCost.setOldInverseCost(inverseEdge.getWeight());
815
                                inverseEdge.setWeight(-1.0);
816
                        }
817
                }
818
                modifiedCosts.add(modifiedCost);
819
                modifiedCost.setApplied(true);
820
                return modifiedCost;
821
        }
822

    
823
        /**
824
         * Be careful about the ORDER!!!!
825
         * @param modifiedCost
826
         */
827
        public boolean removeModifiedCost(GvModifiedCost modifiedCost) {
828
                if (!modifiedCosts.remove(modifiedCost))
829
                        return false;
830
                int idArc = modifiedCost.getIdArc();
831
                int direction = modifiedCost.getDirection();
832
                EdgePair edgePair = getGraph().getEdgesByIdArc(idArc);
833
                if (direction == 3)
834
                {
835
                        if (edgePair.getIdEdge() != -1)
836
                        {
837
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
838
                                edge.setWeight(modifiedCost.getOldCost());
839
                        }
840
                        if (edgePair.getIdInverseEdge() != -1)
841
                        {
842
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
843
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
844
                        }
845
                }
846
                if (direction == 1)
847
                {
848
                        if (edgePair.getIdEdge() != -1)
849
                        {
850
                                GvEdge edge = getGraph().getEdgeByID(edgePair.getIdEdge());
851
                                edge.setWeight(modifiedCost.getOldCost());
852
                        }
853
                }
854
                if (direction == 2)
855
                {
856
                        if (edgePair.getIdInverseEdge() != -1)
857
                        {
858
                                GvEdge inverseEdge = getGraph().getEdgeByID(edgePair.getIdInverseEdge());
859
                                inverseEdge.setWeight(modifiedCost.getOldInverseCost());
860
                        }
861
                }
862
                return true;
863
        }
864

    
865
        public void addFlagListener(IFlagListener listener) {
866
                if (!flagListeners.contains(listener)) {
867
                        flagListeners.add(listener);
868
                }
869
        }
870
        
871
        private void callFlagsChanged(int reason) {
872
                if (dispatching) {
873
                        for (int i=0; i < flagListeners.size(); i++)
874
                        {
875
                                IFlagListener listener = (IFlagListener) flagListeners.get(i);
876
                                listener.flagsChanged(reason);
877
                        }
878
                }
879
        }
880
        
881
        /**
882
         * Useful to do batch modifies. (For example, add lot of flags
883
         * and when finished (endModifying), throw event.
884
         */
885
        public void beginModifyingFlags() {
886
                dispatching = false;
887
        }
888

    
889
        public void endModifyingFlags() {
890
                dispatching = true;
891
                callFlagsChanged(IFlagListener.FLAG_MANY_CHANGES);
892
        }
893
        /**
894
         * Mueve un flag de la posici?n from a la posici?n to.
895
         *
896
         * @param from origen.
897
         * @param to destino.
898
         * 
899
         */
900
        public void moveTo(int from, int to) throws CancelationException {
901
                int newfrom=flags.size()-from-1;
902
                int newto=flags.size()-to-1;
903
                if ( newfrom < 0 || newfrom >=flags.size() || newto < 0 || newto >= flags.size()) return;
904
                GvFlag aux = (GvFlag) flags.get(newfrom);
905
                flags.remove(newfrom);
906
                flags.add(newto, aux);
907
                callFlagsChanged(IFlagListener.FLAG_REORDER);
908
        }
909

    
910
        public ArrayList getEdgeTypes() {
911
                // TODO: Tener esto precalculado
912
                TreeMap map = new TreeMap();
913
                ArrayList ret = new ArrayList();
914
                for (int i = 0; i < graph.numEdges(); i++)
915
                {
916
                        GvEdge edge = graph.getEdgeByID(i);
917
                        Integer type = new Integer(edge.getType());
918
                        if (!map.containsKey(type))
919
                        {
920
                                map.put(type, type);                                
921
                        }
922
                }
923
                Iterator it = map.entrySet().iterator();
924
                while (it.hasNext())
925
                {
926
                        Map.Entry entry = (Map.Entry) it.next();
927
                        Integer type = (Integer) entry.getKey();
928
                        ret.add(type);
929
                }
930
                return ret;
931
        }
932

    
933
        public Hashtable getVelocities() {
934
                return velocities ;
935
        }
936

    
937
        public void setVelocities(Hashtable veloMeters) {
938
                for (int i=0; i < getGraph().numEdges(); i++)
939
                {
940
                        GvEdge edge = getGraph().getEdgeByID(i);
941
                        
942
                        Integer key = new Integer(edge.getType());
943
                        Double vel = (Double) veloMeters.get(key);
944
                        edge.setWeight(edge.getDistance() / vel.doubleValue()); // segundos
945
                }
946
                this.velocities = veloMeters;
947

    
948
                
949
        }
950

    
951
}